summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/core/src/android/text/VariableFontPerfTest.java132
-rw-r--r--apct-tests/perftests/core/src/android/widget/EditTextLongTextPerfTest.java4
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java59
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java130
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java79
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java16
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java12
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java16
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/SearchResult.java38
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java220
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java12
-rw-r--r--apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java1
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java18
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java2
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java (renamed from apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/AppSearchImpl.java)2
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java (renamed from apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverter.java)80
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java (renamed from apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverter.java)45
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java (renamed from apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchResultToProtoConverter.java)23
-rw-r--r--apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java (renamed from apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchSpecToProtoConverter.java)43
-rw-r--r--apex/extservices/Android.bp39
-rw-r--r--apex/extservices/apex_manifest.json4
-rw-r--r--apex/extservices/com.android.extservices.avbpubkeybin1032 -> 0 bytes
-rw-r--r--apex/extservices/com.android.extservices.pem51
-rw-r--r--apex/extservices/com.android.extservices.pk8bin2376 -> 0 bytes
-rw-r--r--apex/extservices/com.android.extservices.x509.pem36
-rw-r--r--apex/extservices/testing/Android.bp25
-rw-r--r--apex/extservices/testing/test_manifest.json4
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java44
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/AlarmStore.java15
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java59
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/LazyAlarmStore.java217
-rw-r--r--apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java57
-rw-r--r--api/Android.bp38
-rw-r--r--api/current.txt21
-rw-r--r--api/module-lib-current.txt222
-rw-r--r--api/module-lib-lint-baseline.txt29
-rw-r--r--api/module-lib-removed.txt1
-rw-r--r--api/system-current.txt29
-rw-r--r--api/system-lint-baseline.txt8
-rw-r--r--api/test-current.txt2
-rw-r--r--cmds/statsd/src/anomaly/AlarmTracker.h1
-rw-r--r--cmds/statsd/src/anomaly/AnomalyTracker.cpp21
-rw-r--r--cmds/statsd/src/anomaly/AnomalyTracker.h31
-rw-r--r--cmds/statsd/src/anomaly/DurationAnomalyTracker.h6
-rw-r--r--cmds/statsd/src/atoms.proto60
-rw-r--r--cmds/statsd/src/metrics/DurationMetricProducer.cpp22
-rw-r--r--cmds/statsd/src/metrics/DurationMetricProducer.h8
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.cpp1
-rw-r--r--cmds/statsd/src/metrics/MetricProducer.h17
-rw-r--r--cmds/statsd/src/metrics/MetricsManager.cpp18
-rw-r--r--cmds/statsd/src/metrics/duration_helper/DurationTracker.h12
-rw-r--r--cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp4
-rw-r--r--cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h12
-rw-r--r--cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp7
-rw-r--r--cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h4
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp126
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/config_update_utils.h45
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp98
-rw-r--r--cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h41
-rw-r--r--cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp339
-rw-r--r--cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp88
-rw-r--r--core/api/current.txt9
-rw-r--r--core/api/system-current.txt24
-rw-r--r--core/api/system-lint-baseline.txt6
-rw-r--r--core/java/android/app/ActivityManager.java9
-rw-r--r--core/java/android/app/AppOpsManager.java29
-rw-r--r--core/java/android/app/IActivityManager.aidl1
-rw-r--r--core/java/android/app/INotificationManager.aidl2
-rw-r--r--core/java/android/app/Notification.java34
-rw-r--r--core/java/android/app/PendingIntent.java12
-rw-r--r--core/java/android/app/TaskInfo.java18
-rw-r--r--core/java/android/app/backup/BackupManager.java22
-rw-r--r--core/java/android/app/backup/FullBackup.java3
-rw-r--r--core/java/android/content/pm/IOnAppsChangedListener.aidl2
-rw-r--r--core/java/android/content/pm/LauncherActivityInfo.java11
-rw-r--r--core/java/android/content/pm/LauncherApps.java13
-rw-r--r--core/java/android/content/pm/OWNERS1
-rw-r--r--core/java/android/content/pm/PackageInstaller.java7
-rw-r--r--core/java/android/content/pm/PackageParser.java6
-rw-r--r--core/java/android/content/pm/parsing/OWNERS5
-rw-r--r--core/java/android/content/rollback/IRollbackManager.aidl4
-rw-r--r--core/java/android/hardware/face/FaceManager.java9
-rw-r--r--core/java/android/hardware/face/IFaceService.aidl6
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java29
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintService.aidl3
-rw-r--r--core/java/android/hardware/usb/AccessoryFilter.java2
-rw-r--r--core/java/android/inputmethodservice/IInputMethodWrapper.java6
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java132
-rw-r--r--core/java/android/os/CombinedVibrationEffect.java403
-rw-r--r--core/java/android/os/UserManager.java3
-rw-r--r--core/java/android/provider/DeviceConfig.java9
-rw-r--r--core/java/android/provider/Settings.java16
-rw-r--r--core/java/android/security/keymaster/KeymasterDefs.java3
-rw-r--r--core/java/android/uwb/AngleMeasurement.java35
-rw-r--r--core/java/android/uwb/AngleOfArrivalMeasurement.java36
-rw-r--r--core/java/android/uwb/DistanceMeasurement.java33
-rw-r--r--core/java/android/uwb/RangingMeasurement.java40
-rw-r--r--core/java/android/uwb/RangingParams.java62
-rw-r--r--core/java/android/uwb/RangingReport.java29
-rw-r--r--core/java/android/uwb/UwbAddress.java65
-rw-r--r--core/java/android/view/ImeInsetsSourceConsumer.java97
-rw-r--r--core/java/android/view/InsetsController.java39
-rw-r--r--core/java/android/view/SurfaceControl.java83
-rw-r--r--core/java/android/view/ViewRootImpl.java45
-rw-r--r--core/java/android/view/WindowManager.java70
-rw-r--r--core/java/android/view/inputmethod/InputMethod.java2
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java35
-rw-r--r--core/java/android/window/DisplayAreaOrganizer.java4
-rw-r--r--core/java/android/window/IDisplayAreaOrganizerController.aidl4
-rw-r--r--core/java/com/android/internal/BrightnessSynchronizer.java4
-rw-r--r--core/java/com/android/internal/app/ChooserFlags.java2
-rw-r--r--core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java5
-rw-r--r--core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java257
-rw-r--r--core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl2
-rw-r--r--core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java19
-rw-r--r--core/java/com/android/internal/jank/FrameTracker.java2
-rw-r--r--core/java/com/android/internal/jank/InteractionJankMonitor.java9
-rw-r--r--core/java/com/android/internal/jank/PerfettoTrigger.java52
-rw-r--r--core/java/com/android/internal/view/IInputMethod.aidl2
-rw-r--r--core/java/com/android/internal/view/IInputMethodClient.aidl3
-rw-r--r--core/jni/android_view_MotionEvent.cpp15
-rw-r--r--core/jni/android_view_SurfaceControl.cpp40
-rw-r--r--core/proto/android/app/settings_enums.proto20
-rw-r--r--core/proto/android/inputmethodservice/inputmethodservice.proto4
-rw-r--r--core/proto/android/server/alarm/alarmmanagerservice.proto2
-rw-r--r--core/proto/android/stats/tls/enums.proto10
-rw-r--r--core/proto/android/view/imeinsetssourceconsumer.proto2
-rw-r--r--core/proto/android/view/windowlayoutparams.proto8
-rw-r--r--core/res/res/layout/notification_material_action_list.xml8
-rw-r--r--core/res/res/values-es/strings.xml6
-rw-r--r--core/res/res/values-gu/strings.xml2
-rw-r--r--core/res/res/values-km/strings.xml6
-rw-r--r--core/res/res/values-mr/strings.xml6
-rw-r--r--core/res/res/values-ne/strings.xml6
-rw-r--r--core/res/res/values/config.xml2
-rw-r--r--core/res/res/values/dimens.xml1
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java2
-rw-r--r--core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java101
-rw-r--r--core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java92
-rw-r--r--core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java12
-rw-r--r--core/tests/coretests/src/android/os/CombinedVibrationEffectTest.java121
-rw-r--r--core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java51
-rw-r--r--core/tests/coretests/src/android/widget/TextViewOnReceiveContentTest.java (renamed from core/tests/coretests/src/android/widget/TextViewOnReceiveContentCallbackTest.java)4
-rw-r--r--graphics/java/android/graphics/Typeface.java6
-rw-r--r--graphics/java/android/graphics/fonts/Font.java64
-rw-r--r--keystore/java/android/security/Credentials.java42
-rw-r--r--keystore/java/android/security/KeyPairGeneratorSpec.java26
-rw-r--r--keystore/java/android/security/KeyStoreParameter.java28
-rw-r--r--libs/WindowManager/Shell/res/values/dimen.xml3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java27
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActivityController.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java21
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java15
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java17
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java56
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java14
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java4
-rw-r--r--media/java/android/media/AudioFormat.java2
-rw-r--r--media/java/android/media/MediaPlayer.java106
-rw-r--r--media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java2
-rw-r--r--media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java2
-rw-r--r--media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java66
-rw-r--r--media/java/android/media/tv/tuner/frontend/FrontendStatus.java25
-rw-r--r--media/jni/android_media_tv_Tuner.cpp5
-rw-r--r--packages/CompanionDeviceManager/res/layout/buttons.xml4
-rw-r--r--packages/CompanionDeviceManager/res/layout/device_chooser.xml2
-rw-r--r--packages/CompanionDeviceManager/res/layout/title.xml1
-rw-r--r--packages/CompanionDeviceManager/res/values/themes.xml1
-rw-r--r--packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java23
-rw-r--r--packages/DynamicSystemInstallationService/res/values-af/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-am/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-ar/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-as/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-az/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-b+sr+Latn/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-be/strings.xml4
-rw-r--r--packages/DynamicSystemInstallationService/res/values-bg/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-bn/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-bs/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-ca/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-cs/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-da/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-de/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-el/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-en-rAU/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-en-rCA/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-en-rGB/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-en-rIN/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-en-rXC/strings.xml1
-rw-r--r--packages/DynamicSystemInstallationService/res/values-es-rUS/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-es/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-et/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-eu/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-fa/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-fi/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-fr-rCA/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-fr/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-gl/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-gu/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-hi/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-hr/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-hu/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-hy/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-in/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-is/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-it/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-iw/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-ja/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-ka/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-kk/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-km/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-kn/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-ko/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-ky/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-lo/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-lt/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-lv/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-mk/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-ml/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-mn/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-mr/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-ms/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-my/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-nb/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-ne/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-nl/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-or/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-pa/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-pl/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-pt-rBR/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-pt-rPT/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-pt/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-ro/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-ru/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-si/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-sk/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-sl/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-sq/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-sr/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-sv/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-sw/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-ta/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-te/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-th/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-tl/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-tr/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-uk/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-ur/strings.xml4
-rw-r--r--packages/DynamicSystemInstallationService/res/values-uz/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-vi/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-zh-rCN/strings.xml2
-rw-r--r--packages/DynamicSystemInstallationService/res/values-zh-rHK/strings.xml4
-rw-r--r--packages/DynamicSystemInstallationService/res/values-zh-rTW/strings.xml4
-rw-r--r--packages/DynamicSystemInstallationService/res/values-zu/strings.xml2
-rw-r--r--packages/SettingsLib/HelpUtils/res/values-es/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-fi/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-gu/strings.xml4
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java2
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml2
-rw-r--r--packages/SystemUI/res/values-af/strings.xml9
-rw-r--r--packages/SystemUI/res/values-am/strings.xml9
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml9
-rw-r--r--packages/SystemUI/res/values-as/strings.xml9
-rw-r--r--packages/SystemUI/res/values-az/strings.xml9
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml9
-rw-r--r--packages/SystemUI/res/values-be/strings.xml9
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml9
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml12
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml9
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml11
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml9
-rw-r--r--packages/SystemUI/res/values-da/strings.xml9
-rw-r--r--packages/SystemUI/res/values-de/strings.xml12
-rw-r--r--packages/SystemUI/res/values-el/strings.xml9
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml6
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml6
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml9
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml9
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml6
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml12
-rw-r--r--packages/SystemUI/res/values-es/strings.xml9
-rw-r--r--packages/SystemUI/res/values-et/strings.xml9
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml9
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml9
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml9
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml9
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml9
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml12
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml22
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml9
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml9
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml9
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml9
-rw-r--r--packages/SystemUI/res/values-in/strings.xml9
-rw-r--r--packages/SystemUI/res/values-is/strings.xml9
-rw-r--r--packages/SystemUI/res/values-it/strings.xml9
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml9
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml9
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml9
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml9
-rw-r--r--packages/SystemUI/res/values-km/strings.xml29
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml12
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml9
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml9
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml6
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml9
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml9
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml9
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml9
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml9
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml12
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml9
-rw-r--r--packages/SystemUI/res/values-my/strings.xml9
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml9
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml12
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml9
-rw-r--r--packages/SystemUI/res/values-or/strings.xml12
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml12
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml9
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml9
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml9
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml9
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml9
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml9
-rw-r--r--packages/SystemUI/res/values-si/strings.xml9
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml9
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml9
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml9
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml9
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml9
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml9
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml9
-rw-r--r--packages/SystemUI/res/values-te/strings.xml9
-rw-r--r--packages/SystemUI/res/values-th/strings.xml9
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml9
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml9
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml9
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml12
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml9
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml9
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml9
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml9
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml9
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml9
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/ScreenDecorations.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java39
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java27
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java42
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java48
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/SecureSettingTest.kt153
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java36
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java48
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java8
-rw-r--r--packages/VpnDialogs/AndroidManifest.xml3
-rw-r--r--packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-bn/strings.xml21
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerService.java11
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java40
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java2
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java100
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java8
-rw-r--r--services/core/java/com/android/server/RescueParty.java50
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java9
-rw-r--r--services/core/java/com/android/server/am/AppProfiler.java7
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java1
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java16
-rw-r--r--services/core/java/com/android/server/am/SettingsToPropertiesMapper.java1
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java30
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java2
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/Face10.java348
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceService.java286
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java113
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java21
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java3
-rw-r--r--services/core/java/com/android/server/camera/CameraServiceProxy.java140
-rw-r--r--services/core/java/com/android/server/compat/CompatChange.java6
-rw-r--r--services/core/java/com/android/server/compat/PlatformCompat.java3
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java142
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java4
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java10
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java393
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java143
-rw-r--r--services/core/java/com/android/server/location/ContextHubServiceUtil.java29
-rw-r--r--services/core/java/com/android/server/location/LocationProviderManager.java65
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssLocationProvider.java6
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java16
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java30
-rw-r--r--services/core/java/com/android/server/pm/LauncherAppsService.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java27
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java17
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java14
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java2
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java117
-rw-r--r--services/core/java/com/android/server/policy/DisplayFoldController.java31
-rw-r--r--services/core/java/com/android/server/power/AttentionDetector.java82
-rw-r--r--services/core/java/com/android/server/rollback/Rollback.java27
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerInternal.java9
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java82
-rw-r--r--services/core/java/com/android/server/rollback/RollbackStore.java2
-rw-r--r--services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java29
-rw-r--r--services/core/java/com/android/server/stats/pull/StatsPullAtomService.java9
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java6
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java20
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java3
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java16
-rw-r--r--services/core/java/com/android/server/wm/DisplayWindowSettings.java845
-rw-r--r--services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java549
-rw-r--r--services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java4
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java4
-rw-r--r--services/core/java/com/android/server/wm/LockTaskController.java104
-rw-r--r--services/core/java/com/android/server/wm/RecentTasks.java20
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java3
-rw-r--r--services/core/java/com/android/server/wm/Task.java65
-rw-r--r--services/core/java/com/android/server/wm/TaskOrganizerController.java46
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java42
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java98
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfaceController.java3
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java65
-rw-r--r--services/java/com/android/server/SystemServer.java14
-rw-r--r--services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java9
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java50
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java39
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java55
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java (renamed from services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/AppSearchImplTest.java)2
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java (renamed from services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverterTest.java)20
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java (renamed from services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverterTest.java)6
-rw-r--r--services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java (renamed from services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SnippetTest.java)4
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/Face10Test.java11
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyConstantsTest.java40
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyEventLoggerTest.java21
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java147
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java1576
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java44
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/FactoryResetProtectionPolicyTest.java16
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java76
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java57
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java481
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/SecurityEventTest.java82
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java93
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java48
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java171
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/permission/PermissionManagerServiceTest.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java30
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java37
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java12
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java56
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java147
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java24
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java367
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java467
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java80
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java22
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java43
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java27
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java42
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java17
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java14
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java12
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskTests.java18
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TransitionTests.java14
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java14
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java37
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java29
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java186
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java16
-rwxr-xr-xtelecomm/java/android/telecom/Call.java7
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java3
-rw-r--r--telephony/java/android/telephony/ims/ImsRcsManager.java13
-rw-r--r--telephony/java/android/telephony/ims/RcsContactTerminatedReason.aidl (renamed from core/tests/coretests/src/android/app/appsearch/external/app/SearchResultsTest.java)16
-rw-r--r--telephony/java/android/telephony/ims/RcsContactTerminatedReason.java75
-rw-r--r--telephony/java/android/telephony/ims/RcsUceAdapter.java242
-rw-r--r--telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl75
-rw-r--r--telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl3
-rw-r--r--telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl12
-rw-r--r--telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl41
-rw-r--r--telephony/java/android/telephony/ims/aidl/IOptionsResponseCallback.aidl29
-rw-r--r--telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl29
-rw-r--r--telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl1
-rw-r--r--telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl36
-rw-r--r--telephony/java/android/telephony/ims/aidl/RcsOptionsResponseAidlWrapper.java54
-rw-r--r--telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java51
-rw-r--r--telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java95
-rw-r--r--telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java4
-rw-r--r--telephony/java/android/telephony/ims/feature/RcsFeature.java166
-rw-r--r--telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java8
-rw-r--r--telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java338
-rw-r--r--telephony/java/com/android/internal/telephony/RILConstants.java147
-rw-r--r--tests/RollbackTest/NetworkStagedRollbackTest/src/com/android/tests/rollback/host/NetworkStagedRollbackTest.java13
-rw-r--r--tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java30
-rw-r--r--tests/RollbackTest/lib/src/com/android/tests/rollback/host/WatchdogEventLogger.java100
-rw-r--r--tests/vcn/Android.bp27
-rw-r--r--tests/vcn/AndroidManifest.xml28
-rw-r--r--tests/vcn/AndroidTest.xml28
-rw-r--r--tests/vcn/TEST_MAPPING7
-rw-r--r--wifi/aidl-export/android/net/wifi/aware/AwareResources.aidl19
-rw-r--r--wifi/api/current.txt12
-rw-r--r--wifi/api/system-current.txt5
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java46
-rw-r--r--wifi/java/android/net/wifi/WifiInfo.java42
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkSuggestion.java85
-rw-r--r--wifi/java/android/net/wifi/aware/AwareResources.java146
-rw-r--r--wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl2
-rw-r--r--wifi/java/android/net/wifi/aware/WifiAwareManager.java19
-rw-r--r--wifi/tests/src/android/net/wifi/WifiConfigurationTest.java33
-rw-r--r--wifi/tests/src/android/net/wifi/WifiInfoTest.java44
-rw-r--r--wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java81
-rw-r--r--wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java11
569 files changed, 13478 insertions, 5739 deletions
diff --git a/apct-tests/perftests/core/src/android/text/VariableFontPerfTest.java b/apct-tests/perftests/core/src/android/text/VariableFontPerfTest.java
new file mode 100644
index 000000000000..fbe67a477f5d
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/text/VariableFontPerfTest.java
@@ -0,0 +1,132 @@
+/*
+ * 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 android.text;
+
+import android.graphics.Paint;
+import android.graphics.RecordingCanvas;
+import android.graphics.RenderNode;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Random;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class VariableFontPerfTest {
+ private static final int WORD_LENGTH = 9; // Random word has 9 characters.
+ private static final boolean NO_STYLE_TEXT = false;
+
+ private static final TextPaint PAINT = new TextPaint();
+
+ public VariableFontPerfTest() {}
+
+ @Rule
+ public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+ private final TextPerfUtils mTextUtil = new TextPerfUtils();
+
+ @Before
+ public void setUp() {
+ mTextUtil.resetRandom(0 /* seed */);
+ }
+
+ @Test
+ public void testDraw_SetVariationOnce() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final Paint paint = new Paint(PAINT);
+ paint.setFontVariationSettings("'wght' 700");
+ final RenderNode node = RenderNode.create("benchmark", null);
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final RecordingCanvas c = node.beginRecording(1200, 200);
+ state.resumeTiming();
+
+ c.drawText(text, 0, text.length(), 0, 100, paint);
+
+ state.pauseTiming();
+ node.endRecording();
+ state.resumeTiming();
+
+ }
+ }
+
+ @Test
+ public void testDraw_SetVariationEachDraw() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final Paint paint = new Paint(PAINT);
+ final RenderNode node = RenderNode.create("benchmark", null);
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final RecordingCanvas c = node.beginRecording(1200, 200);
+ paint.setFontVariationSettings("'wght' 700");
+ state.resumeTiming();
+
+ c.drawText(text, 0, text.length(), 0, 100, paint);
+
+ state.pauseTiming();
+ node.endRecording();
+ state.resumeTiming();
+
+ }
+ }
+
+ @Test
+ public void testDraw_SetDifferentVariationEachDraw() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+ final Paint paint = new Paint(PAINT);
+ final RenderNode node = RenderNode.create("benchmark", null);
+ final Random random = new Random(0);
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ final RecordingCanvas c = node.beginRecording(1200, 200);
+ int weight = random.nextInt(1000);
+ paint.setFontVariationSettings("'wght' " + weight);
+ state.resumeTiming();
+
+ c.drawText(text, 0, text.length(), 0, 100, paint);
+
+ state.pauseTiming();
+ node.endRecording();
+ state.resumeTiming();
+ }
+ }
+
+ @Test
+ public void testSetFontVariationSettings() {
+ final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ final Paint paint = new Paint(PAINT);
+ final Random random = new Random(0);
+ while (state.keepRunning()) {
+ state.pauseTiming();
+ int weight = random.nextInt(1000);
+ state.resumeTiming();
+
+ paint.setFontVariationSettings("'wght' " + weight);
+ }
+ }
+}
diff --git a/apct-tests/perftests/core/src/android/widget/EditTextLongTextPerfTest.java b/apct-tests/perftests/core/src/android/widget/EditTextLongTextPerfTest.java
index f4ad5ddd3ed2..c48fa4ffd030 100644
--- a/apct-tests/perftests/core/src/android/widget/EditTextLongTextPerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/EditTextLongTextPerfTest.java
@@ -43,8 +43,8 @@ public class EditTextLongTextPerfTest {
@Parameters(name = "{0}")
public static Collection cases() {
return Arrays.asList(new Object[][] {
- { "10x30K", 10, 30000 },
- { "300x1K", 300, 1000 },
+ { "10x3K", 10, 3000 },
+ { "30x1K", 30, 1000 },
});
}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java
index 5f2fabe52929..beb9ad3d27ea 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchEmail.java
@@ -27,8 +27,6 @@ import android.app.appsearch.AppSearchSchema.PropertyConfig;
*
* <p>This class is a higher level implement of {@link GenericDocument}.
*
- * <p>This class will eventually migrate to Jetpack, where it will become public API.
- *
* @hide
*/
@@ -99,10 +97,9 @@ public class AppSearchEmail extends GenericDocument {
}
/**
- * Get the from address of {@link AppSearchEmail}.
+ * Gets the from address of {@link AppSearchEmail}.
*
- * @return Returns the subject of {@link AppSearchEmail} or {@code null} if it's not been set
- * yet.
+ * @return The subject of {@link AppSearchEmail} or {@code null} if it's not been set yet.
*/
@Nullable
public String getFrom() {
@@ -110,10 +107,10 @@ public class AppSearchEmail extends GenericDocument {
}
/**
- * Get the destination addresses of {@link AppSearchEmail}.
+ * Gets the destination addresses of {@link AppSearchEmail}.
*
- * @return Returns the destination addresses of {@link AppSearchEmail} or {@code null} if it's
- * not been set yet.
+ * @return The destination addresses of {@link AppSearchEmail} or {@code null} if it's not
+ * been set yet.
*/
@Nullable
public String[] getTo() {
@@ -121,10 +118,9 @@ public class AppSearchEmail extends GenericDocument {
}
/**
- * Get the CC list of {@link AppSearchEmail}.
+ * Gets the CC list of {@link AppSearchEmail}.
*
- * @return Returns the CC list of {@link AppSearchEmail} or {@code null} if it's not been set
- * yet.
+ * @return The CC list of {@link AppSearchEmail} or {@code null} if it's not been set yet.
*/
@Nullable
public String[] getCc() {
@@ -132,10 +128,9 @@ public class AppSearchEmail extends GenericDocument {
}
/**
- * Get the BCC list of {@link AppSearchEmail}.
+ * Gets the BCC list of {@link AppSearchEmail}.
*
- * @return Returns the BCC list of {@link AppSearchEmail} or {@code null} if it's not been set
- * yet.
+ * @return The BCC list of {@link AppSearchEmail} or {@code null} if it's not been set yet.
*/
@Nullable
public String[] getBcc() {
@@ -143,10 +138,9 @@ public class AppSearchEmail extends GenericDocument {
}
/**
- * Get the subject of {@link AppSearchEmail}.
+ * Gets the subject of {@link AppSearchEmail}.
*
- * @return Returns the value subject of {@link AppSearchEmail} or {@code null} if it's not been
- * set yet.
+ * @return The value subject of {@link AppSearchEmail} or {@code null} if it's not been set yet.
*/
@Nullable
public String getSubject() {
@@ -154,9 +148,9 @@ public class AppSearchEmail extends GenericDocument {
}
/**
- * Get the body of {@link AppSearchEmail}.
+ * Gets the body of {@link AppSearchEmail}.
*
- * @return Returns the body of {@link AppSearchEmail} or {@code null} if it's not been set yet.
+ * @return The body of {@link AppSearchEmail} or {@code null} if it's not been set yet.
*/
@Nullable
public String getBody() {
@@ -169,7 +163,8 @@ public class AppSearchEmail extends GenericDocument {
public static class Builder extends GenericDocument.Builder<AppSearchEmail.Builder> {
/**
- * Create a new {@link AppSearchEmail.Builder}
+ * Creates a new {@link AppSearchEmail.Builder}
+ *
* @param uri The Uri of the Email.
*/
public Builder(@NonNull String uri) {
@@ -177,56 +172,56 @@ public class AppSearchEmail extends GenericDocument {
}
/**
- * Set the from address of {@link AppSearchEmail}
+ * Sets the from address of {@link AppSearchEmail}
*/
@NonNull
public AppSearchEmail.Builder setFrom(@NonNull String from) {
- setProperty(KEY_FROM, from);
+ setPropertyString(KEY_FROM, from);
return this;
}
/**
- * Set the destination address of {@link AppSearchEmail}
+ * Sets the destination address of {@link AppSearchEmail}
*/
@NonNull
public AppSearchEmail.Builder setTo(@NonNull String... to) {
- setProperty(KEY_TO, to);
+ setPropertyString(KEY_TO, to);
return this;
}
/**
- * Set the CC list of {@link AppSearchEmail}
+ * Sets the CC list of {@link AppSearchEmail}
*/
@NonNull
public AppSearchEmail.Builder setCc(@NonNull String... cc) {
- setProperty(KEY_CC, cc);
+ setPropertyString(KEY_CC, cc);
return this;
}
/**
- * Set the BCC list of {@link AppSearchEmail}
+ * Sets the BCC list of {@link AppSearchEmail}
*/
@NonNull
public AppSearchEmail.Builder setBcc(@NonNull String... bcc) {
- setProperty(KEY_BCC, bcc);
+ setPropertyString(KEY_BCC, bcc);
return this;
}
/**
- * Set the subject of {@link AppSearchEmail}
+ * Sets the subject of {@link AppSearchEmail}
*/
@NonNull
public AppSearchEmail.Builder setSubject(@NonNull String subject) {
- setProperty(KEY_SUBJECT, subject);
+ setPropertyString(KEY_SUBJECT, subject);
return this;
}
/**
- * Set the body of {@link AppSearchEmail}
+ * Sets the body of {@link AppSearchEmail}
*/
@NonNull
public AppSearchEmail.Builder setBody(@NonNull String body) {
- setProperty(KEY_BODY, body);
+ setPropertyString(KEY_BODY, body);
return this;
}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java
index 90e4df68f734..3933726d6729 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/AppSearchSchema.java
@@ -16,10 +16,12 @@
package android.app.appsearch;
+import android.annotation.SuppressLint;
import android.os.Bundle;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.appsearch.exceptions.IllegalSchemaException;
import android.util.ArraySet;
@@ -28,6 +30,8 @@ import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
import java.util.Set;
/**
@@ -39,13 +43,8 @@ import java.util.Set;
* @hide
*/
public final class AppSearchSchema {
- /** @hide */
-
- public static final String SCHEMA_TYPE_FIELD = "schemaType";
-
- /** @hide */
-
- public static final String PROPERTIES_FIELD = "properties";
+ private static final String SCHEMA_TYPE_FIELD = "schemaType";
+ private static final String PROPERTIES_FIELD = "properties";
private final Bundle mBundle;
@@ -71,10 +70,35 @@ public final class AppSearchSchema {
return mBundle.toString();
}
+ /** Returns the name of this schema type, e.g. Email. */
+ @NonNull
+ public String getSchemaTypeName() {
+ return mBundle.getString(SCHEMA_TYPE_FIELD, "");
+ }
+
+ /**
+ * Returns the list of {@link PropertyConfig}s that are part of this schema.
+ *
+ * <p>This method creates a new list when called.
+ */
+ @NonNull
+ public List<PropertyConfig> getProperties() {
+ ArrayList<Bundle> propertyBundles =
+ mBundle.getParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD);
+ if (propertyBundles.isEmpty()) {
+ return Collections.emptyList();
+ }
+ List<PropertyConfig> ret = new ArrayList<>(propertyBundles.size());
+ for (int i = 0; i < propertyBundles.size(); i++) {
+ ret.add(new PropertyConfig(propertyBundles.get(i)));
+ }
+ return ret;
+ }
+
/** Builder for {@link AppSearchSchema objects}. */
public static final class Builder {
private final String mTypeName;
- private final ArrayList<Bundle> mProperties = new ArrayList<>();
+ private final ArrayList<Bundle> mPropertyBundles = new ArrayList<>();
private final Set<String> mPropertyNames = new ArraySet<>();
private boolean mBuilt = false;
@@ -85,15 +109,19 @@ public final class AppSearchSchema {
}
/** Adds a property to the given type. */
+ // TODO(b/171360120): MissingGetterMatchingBuilder expects a method called getPropertys, but
+ // we provide the (correct) method getProperties. Once the bug referenced in this TODO is
+ // fixed, remove this SuppressLint.
+ @SuppressLint("MissingGetterMatchingBuilder")
@NonNull
public AppSearchSchema.Builder addProperty(@NonNull PropertyConfig propertyConfig) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkNotNull(propertyConfig);
- if (!mPropertyNames.add(propertyConfig.mName)) {
- throw new IllegalSchemaException(
- "Property defined more than once: " + propertyConfig.mName);
+ String name = propertyConfig.getName();
+ if (!mPropertyNames.add(name)) {
+ throw new IllegalSchemaException("Property defined more than once: " + name);
}
- mProperties.add(propertyConfig.mBundle);
+ mPropertyBundles.add(propertyConfig.mBundle);
return this;
}
@@ -107,7 +135,7 @@ public final class AppSearchSchema {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Bundle bundle = new Bundle();
bundle.putString(AppSearchSchema.SCHEMA_TYPE_FIELD, mTypeName);
- bundle.putParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD, mProperties);
+ bundle.putParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD, mPropertyBundles);
mBuilt = true;
return new AppSearchSchema(bundle);
}
@@ -120,29 +148,12 @@ public final class AppSearchSchema {
* a property.
*/
public static final class PropertyConfig {
- /** @hide */
-
- public static final String NAME_FIELD = "name";
-
- /** @hide */
-
- public static final String DATA_TYPE_FIELD = "dataType";
-
- /** @hide */
-
- public static final String SCHEMA_TYPE_FIELD = "schemaType";
-
- /** @hide */
-
- public static final String CARDINALITY_FIELD = "cardinality";
-
- /** @hide */
-
- public static final String INDEXING_TYPE_FIELD = "indexingType";
-
- /** @hide */
-
- public static final String TOKENIZER_TYPE_FIELD = "tokenizerType";
+ private static final String NAME_FIELD = "name";
+ private static final String DATA_TYPE_FIELD = "dataType";
+ private static final String SCHEMA_TYPE_FIELD = "schemaType";
+ private static final String CARDINALITY_FIELD = "cardinality";
+ private static final String INDEXING_TYPE_FIELD = "indexingType";
+ private static final String TOKENIZER_TYPE_FIELD = "tokenizerType";
/**
* Physical data-types of the contents of the property.
@@ -259,11 +270,9 @@ public final class AppSearchSchema {
/** Tokenization for plain text. */
public static final int TOKENIZER_TYPE_PLAIN = 1;
- final String mName;
final Bundle mBundle;
- PropertyConfig(@NonNull String name, @NonNull Bundle bundle) {
- mName = Preconditions.checkNotNull(name);
+ PropertyConfig(@NonNull Bundle bundle) {
mBundle = Preconditions.checkNotNull(bundle);
}
@@ -272,6 +281,45 @@ public final class AppSearchSchema {
return mBundle.toString();
}
+ /** Returns the name of this property. */
+ @NonNull
+ public String getName() {
+ return mBundle.getString(NAME_FIELD, "");
+ }
+
+ /** Returns the type of data the property contains (e.g. string, int, bytes, etc). */
+ public @DataType int getDataType() {
+ return mBundle.getInt(DATA_TYPE_FIELD, -1);
+ }
+
+ /**
+ * Returns the logical schema-type of the contents of this property.
+ *
+ * <p>Only set when {@link #getDataType} is set to {@link #DATA_TYPE_DOCUMENT}.
+ * Otherwise, it is {@code null}.
+ */
+ @Nullable
+ public String getSchemaType() {
+ return mBundle.getString(SCHEMA_TYPE_FIELD);
+ }
+
+ /**
+ * Returns the cardinality of the property (whether it is optional, required or repeated).
+ */
+ public @Cardinality int getCardinality() {
+ return mBundle.getInt(CARDINALITY_FIELD, -1);
+ }
+
+ /** Returns how the property is indexed. */
+ public @IndexingType int getIndexingType() {
+ return mBundle.getInt(INDEXING_TYPE_FIELD);
+ }
+
+ /** Returns how this property is tokenized (split into words). */
+ public @TokenizerType int getTokenizerType() {
+ return mBundle.getInt(TOKENIZER_TYPE_FIELD);
+ }
+
/**
* Builder for {@link PropertyConfig}.
*
@@ -286,13 +334,11 @@ public final class AppSearchSchema {
* is also required.
*/
public static final class Builder {
- private final String mName;
private final Bundle mBundle = new Bundle();
private boolean mBuilt = false;
/** Creates a new {@link PropertyConfig.Builder}. */
public Builder(@NonNull String propertyName) {
- mName = Preconditions.checkNotNull(propertyName);
mBundle.putString(NAME_FIELD, propertyName);
}
@@ -386,7 +432,7 @@ public final class AppSearchSchema {
throw new IllegalSchemaException("Missing field: cardinality");
}
mBuilt = true;
- return new PropertyConfig(mName, mBundle);
+ return new PropertyConfig(mBundle);
}
}
}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java b/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java
index 9fe2c67d00f2..48d3ac09d997 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/GenericDocument.java
@@ -30,6 +30,7 @@ import com.android.internal.util.Preconditions;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Set;
/**
@@ -65,20 +66,14 @@ public class GenericDocument {
/** The default time-to-live in millisecond of a document, which is infinity. */
private static final long DEFAULT_TTL_MILLIS = 0L;
- /** @hide */
-
- public static final String PROPERTIES_FIELD = "properties";
-
- /** @hide */
-
- public static final String BYTE_ARRAY_FIELD = "byteArray";
-
- static final String SCHEMA_TYPE_FIELD = "schemaType";
- static final String URI_FIELD = "uri";
- static final String SCORE_FIELD = "score";
- static final String TTL_MILLIS_FIELD = "ttlMillis";
- static final String CREATION_TIMESTAMP_MILLIS_FIELD = "creationTimestampMillis";
- static final String NAMESPACE_FIELD = "namespace";
+ private static final String PROPERTIES_FIELD = "properties";
+ private static final String BYTE_ARRAY_FIELD = "byteArray";
+ private static final String SCHEMA_TYPE_FIELD = "schemaType";
+ private static final String URI_FIELD = "uri";
+ private static final String SCORE_FIELD = "score";
+ private static final String TTL_MILLIS_FIELD = "ttlMillis";
+ private static final String CREATION_TIMESTAMP_MILLIS_FIELD = "creationTimestampMillis";
+ private static final String NAMESPACE_FIELD = "namespace";
/**
* The maximum number of indexed properties a document can have.
@@ -190,6 +185,12 @@ public class GenericDocument {
return mBundle.getInt(SCORE_FIELD, DEFAULT_SCORE);
}
+ /** Returns the names of all properties defined in this document. */
+ @NonNull
+ public Set<String> getPropertyNames() {
+ return Collections.unmodifiableSet(mProperties.keySet());
+ }
+
/**
* Retrieves a {@link String} value by key.
*
@@ -437,8 +438,6 @@ public class GenericDocument {
@Override
public boolean equals(@Nullable Object other) {
- // Check only proto's equality is sufficient here since all properties in
- // mProperties are ordered by keys and stored in proto.
if (this == other) {
return true;
}
@@ -450,8 +449,8 @@ public class GenericDocument {
}
/**
- * Deeply checks two bundle is equally or not.
- * <p> Two bundle will be considered equally if they contains same content.
+ * Deeply checks two bundles are equally or not.
+ * <p> Two bundles will be considered equally if they contain same content.
*/
@SuppressWarnings("unchecked")
private static boolean bundleEquals(Bundle one, Bundle two) {
@@ -472,7 +471,7 @@ public class GenericDocument {
return false;
} else if (valueOne == null && (valueTwo != null || !two.containsKey(key))) {
// If we call bundle.get(key) when the 'key' doesn't actually exist in the
- // bundle, we'll get back a null. So make sure that both values are null and
+ // bundle, we'll get back a null. So make sure that both values are null and
// both keys exist in the bundle.
return false;
} else if (valueOne instanceof boolean[]) {
@@ -538,8 +537,8 @@ public class GenericDocument {
/**
* Calculates the hash code for a bundle.
- * <p> The hash code is only effected by the content in the bundle. Bundles will get
- * consistent hash code if they have same content.
+ * <p> The hash code is only effected by the contents in the bundle. Bundles will get
+ * consistent hash code if they have same contents.
*/
@SuppressWarnings("unchecked")
private static int bundleHashCode(Bundle bundle) {
@@ -648,8 +647,11 @@ public class GenericDocument {
/**
* The builder class for {@link GenericDocument}.
*
- * @param <BuilderType> Type of subclass who extend this.
+ * @param <BuilderType> Type of subclass who extends this.
*/
+ // This builder is specifically designed to be extended by classes deriving from
+ // GenericDocument.
+ @SuppressLint("StaticFinalBuilder")
public static class Builder<BuilderType extends Builder> {
private final Bundle mProperties = new Bundle();
@@ -662,12 +664,11 @@ public class GenericDocument {
*
* @param uri The uri of {@link GenericDocument}.
* @param schemaType The schema type of the {@link GenericDocument}. The passed-in
- * {@code schemaType} must be defined using {@code AppSearchManager#setSchema} prior
+ * {@code schemaType} must be defined using {@link AppSearchSession#setSchema} prior
* to inserting a document of this {@code schemaType} into the AppSearch index using
- * {@code AppSearchManager#putDocuments}. Otherwise, the document will be
- * rejected by {@code AppSearchManager#putDocuments}.
+ * {@link AppSearchSession#putDocuments}. Otherwise, the document will be
+ * rejected by {@link AppSearchSession#putDocuments}.
*/
- //TODO(b/157082794) Linkify AppSearchManager once that API is public.
@SuppressWarnings("unchecked")
public Builder(@NonNull String uri, @NonNull String schemaType) {
Preconditions.checkNotNull(uri);
@@ -685,9 +686,12 @@ public class GenericDocument {
}
/**
- * Set the app-defined namespace this Document resides in. No special values are
- * reserved or understood by the infrastructure. URIs are unique within a namespace. The
- * number of namespaces per app should be kept small for efficiency reasons.
+ * Sets the app-defined namespace this Document resides in. No special values are
+ * reserved or understood by the infrastructure.
+ *
+ * <p>URIs are unique within a namespace.
+ *
+ * <p>The number of namespaces per app should be kept small for efficiency reasons.
*/
@NonNull
public BuilderType setNamespace(@NonNull String namespace) {
@@ -714,7 +718,7 @@ public class GenericDocument {
}
/**
- * Set the creation timestamp in milliseconds of the {@link GenericDocument}. Should be
+ * Sets the creation timestamp of the {@link GenericDocument}, in milliseconds. Should be
* set using a value obtained from the {@link System#currentTimeMillis()} time base.
*/
@NonNull
@@ -726,7 +730,7 @@ public class GenericDocument {
}
/**
- * Set the TTL (Time To Live) of the {@link GenericDocument}, in milliseconds.
+ * Sets the TTL (Time To Live) of the {@link GenericDocument}, in milliseconds.
*
* <p>After this many milliseconds since the {@link #setCreationTimestampMillis creation
* timestamp}, the document is deleted.
@@ -752,7 +756,7 @@ public class GenericDocument {
* @param values The {@code String} values of the property.
*/
@NonNull
- public BuilderType setProperty(@NonNull String key, @NonNull String... values) {
+ public BuilderType setPropertyString(@NonNull String key, @NonNull String... values) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkNotNull(key);
Preconditions.checkNotNull(values);
@@ -768,7 +772,7 @@ public class GenericDocument {
* @param values The {@code boolean} values of the property.
*/
@NonNull
- public BuilderType setProperty(@NonNull String key, @NonNull boolean... values) {
+ public BuilderType setPropertyBoolean(@NonNull String key, @NonNull boolean... values) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkNotNull(key);
Preconditions.checkNotNull(values);
@@ -784,7 +788,7 @@ public class GenericDocument {
* @param values The {@code long} values of the property.
*/
@NonNull
- public BuilderType setProperty(@NonNull String key, @NonNull long... values) {
+ public BuilderType setPropertyLong(@NonNull String key, @NonNull long... values) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkNotNull(key);
Preconditions.checkNotNull(values);
@@ -800,7 +804,7 @@ public class GenericDocument {
* @param values The {@code double} values of the property.
*/
@NonNull
- public BuilderType setProperty(@NonNull String key, @NonNull double... values) {
+ public BuilderType setPropertyDouble(@NonNull String key, @NonNull double... values) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkNotNull(key);
Preconditions.checkNotNull(values);
@@ -815,7 +819,7 @@ public class GenericDocument {
* @param values The {@code byte[]} of the property.
*/
@NonNull
- public BuilderType setProperty(@NonNull String key, @NonNull byte[]... values) {
+ public BuilderType setPropertyBytes(@NonNull String key, @NonNull byte[]... values) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkNotNull(key);
Preconditions.checkNotNull(values);
@@ -831,7 +835,8 @@ public class GenericDocument {
* @param values The {@link GenericDocument} values of the property.
*/
@NonNull
- public BuilderType setProperty(@NonNull String key, @NonNull GenericDocument... values) {
+ public BuilderType setPropertyDocument(
+ @NonNull String key, @NonNull GenericDocument... values) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkNotNull(key);
Preconditions.checkNotNull(values);
diff --git a/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java b/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java
index 3c0e746f92ab..e1e0eda7558c 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/GetByUriRequest.java
@@ -17,12 +17,12 @@
package android.app.appsearch;
import android.annotation.NonNull;
-
import android.util.ArraySet;
import com.android.internal.util.Preconditions;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.Set;
/**
@@ -40,18 +40,16 @@ public final class GetByUriRequest {
mUris = uris;
}
- /** @hide */
-
+ /** Returns the namespace to get documents from. */
@NonNull
public String getNamespace() {
return mNamespace;
}
- /** @hide */
-
+ /** Returns the URIs to get from the namespace. */
@NonNull
public Set<String> getUris() {
- return mUris;
+ return Collections.unmodifiableSet(mUris);
}
/** Builder for {@link GetByUriRequest} objects. */
@@ -75,14 +73,14 @@ public final class GetByUriRequest {
/** Adds one or more URIs to the request. */
@NonNull
- public Builder addUris(@NonNull String... uris) {
+ public Builder addUri(@NonNull String... uris) {
Preconditions.checkNotNull(uris);
- return addUris(Arrays.asList(uris));
+ return addUri(Arrays.asList(uris));
}
/** Adds one or more URIs to the request. */
@NonNull
- public Builder addUris(@NonNull Collection<String> uris) {
+ public Builder addUri(@NonNull Collection<String> uris) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkNotNull(uris);
mUris.addAll(uris);
diff --git a/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java b/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java
index 7e97542c6f02..1f90bc184f6f 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/PutDocumentsRequest.java
@@ -16,13 +16,16 @@
package android.app.appsearch;
-import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.annotation.NonNull;
+import android.app.appsearch.exceptions.AppSearchException;
import com.android.internal.util.Preconditions;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
/**
@@ -38,11 +41,10 @@ public final class PutDocumentsRequest {
mDocuments = documents;
}
- /** @hide */
-
+ /** Returns the documents that are part of this request. */
@NonNull
public List<GenericDocument> getDocuments() {
- return mDocuments;
+ return Collections.unmodifiableList(mDocuments);
}
/** Builder for {@link PutDocumentsRequest} objects. */
@@ -51,6 +53,7 @@ public final class PutDocumentsRequest {
private boolean mBuilt = false;
/** Adds one or more documents to the request. */
+ @SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments()
@NonNull
public Builder addGenericDocument(@NonNull GenericDocument... documents) {
Preconditions.checkNotNull(documents);
@@ -58,6 +61,7 @@ public final class PutDocumentsRequest {
}
/** Adds one or more documents to the request. */
+ @SuppressLint("MissingGetterMatchingBuilder") // Merged list available from getDocuments()
@NonNull
public Builder addGenericDocument(@NonNull Collection<GenericDocument> documents) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
diff --git a/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java b/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java
index a047041a3082..486857fba1de 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/RemoveByUriRequest.java
@@ -17,12 +17,12 @@
package android.app.appsearch;
import android.annotation.NonNull;
-
import android.util.ArraySet;
import com.android.internal.util.Preconditions;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.Set;
/**
@@ -40,18 +40,16 @@ public final class RemoveByUriRequest {
mUris = uris;
}
- /** @hide */
-
+ /** Returns the namespace to remove documents from. */
@NonNull
public String getNamespace() {
return mNamespace;
}
- /** @hide */
-
+ /** Returns the URIs to remove from the namespace. */
@NonNull
public Set<String> getUris() {
- return mUris;
+ return Collections.unmodifiableSet(mUris);
}
/** Builder for {@link RemoveByUriRequest} objects. */
@@ -75,14 +73,14 @@ public final class RemoveByUriRequest {
/** Adds one or more URIs to the request. */
@NonNull
- public Builder addUris(@NonNull String... uris) {
+ public Builder addUri(@NonNull String... uris) {
Preconditions.checkNotNull(uris);
- return addUris(Arrays.asList(uris));
+ return addUri(Arrays.asList(uris));
}
/** Adds one or more URIs to the request. */
@NonNull
- public Builder addUris(@NonNull Collection<String> uris) {
+ public Builder addUri(@NonNull Collection<String> uris) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkNotNull(uris);
mUris.addAll(uris);
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java b/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java
index 758280bbc322..99cb2f16ca4d 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchResult.java
@@ -49,19 +49,22 @@ public final class SearchResult {
@NonNull
private final Bundle mDocumentBundle;
+ /** Cache of the inflated document. Comes from inflating mDocumentBundle at first use. */
@Nullable
private GenericDocument mDocument;
- @Nullable
- private final List<Bundle> mMatchBundles;
-
/**
- * Contains a list of Snippets that matched the request. Only populated when requested in
- * both {@link SearchSpec.Builder#setSnippetCount(int)}
- * and {@link SearchSpec.Builder#setSnippetCountPerProperty(int)}.
+ * Contains a list of MatchInfo bundles that matched the request.
+ *
+ * Only populated when requested in both {@link SearchSpec.Builder#setSnippetCount} and
+ * {@link SearchSpec.Builder#setSnippetCountPerProperty}.
*
* @see #getMatches()
*/
+ @NonNull
+ private final List<Bundle> mMatchBundles;
+
+ /** Cache of the inflated matches. Comes from inflating mMatchBundles at first use. */
@Nullable
private List<MatchInfo> mMatches;
@@ -70,7 +73,7 @@ public final class SearchResult {
public SearchResult(@NonNull Bundle bundle) {
mBundle = Preconditions.checkNotNull(bundle);
mDocumentBundle = Preconditions.checkNotNull(bundle.getBundle(DOCUMENT_FIELD));
- mMatchBundles = bundle.getParcelableArrayList(MATCHES_FIELD);
+ mMatchBundles = Preconditions.checkNotNull(bundle.getParcelableArrayList(MATCHES_FIELD));
}
/** @hide */
@@ -93,19 +96,16 @@ public final class SearchResult {
}
/**
- * Contains a list of Snippets that matched the request. Only populated when requested in
- * both {@link SearchSpec.Builder#setSnippetCount(int)}
- * and {@link SearchSpec.Builder#setSnippetCountPerProperty(int)}.
+ * Contains a list of Snippets that matched the request.
*
- * @return List of matches based on {@link SearchSpec}, if snippeting is disabled and this
- * method is called it will return {@code null}. Users can also restrict snippet population
- * using {@link SearchSpec.Builder#setSnippetCount} and
- * {@link SearchSpec.Builder#setSnippetCountPerProperty(int)}, for all results after that
- * value this method will return {@code null}.
+ * @return List of matches based on {@link SearchSpec}. If snippeting is disabled using
+ * {@link SearchSpec.Builder#setSnippetCount} or
+ * {@link SearchSpec.Builder#setSnippetCountPerProperty}, for all results after that
+ * value, this method returns an empty list.
*/
- @Nullable
+ @NonNull
public List<MatchInfo> getMatches() {
- if (mMatchBundles != null && mMatches == null) {
+ if (mMatches == null) {
mMatches = new ArrayList<>(mMatchBundles.size());
for (int i = 0; i < mMatchBundles.size(); i++) {
MatchInfo matchInfo = new MatchInfo(getDocument(), mMatchBundles.get(i));
@@ -119,8 +119,8 @@ public final class SearchResult {
* Snippet: It refers to a substring of text from the content of document that is returned as a
* part of search result.
* This class represents a match objects for any Snippets that might be present in
- * {@link SearchResults} from query. Using this class user can get the full text, exact matches
- * and Snippets of document content for a given match.
+ * {@link SearchResults} from query. Using this class
+ * user can get the full text, exact matches and Snippets of document content for a given match.
*
* <p>Class Example 1:
* A document contains following text in property subject:
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
index c8719059fa8c..15acf103f2e6 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SearchSpec.java
@@ -16,16 +16,23 @@
package android.app.appsearch;
+import android.annotation.SuppressLint;
import android.os.Bundle;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.app.appsearch.exceptions.AppSearchException;
import android.app.appsearch.exceptions.IllegalSearchSpecException;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
/**
* This class represents the specification logic for AppSearch. It can be used to set the type of
@@ -34,69 +41,26 @@ import java.lang.annotation.RetentionPolicy;
*/
// TODO(sidchhabra) : AddResultSpec fields for Snippets etc.
public final class SearchSpec {
- /** @hide */
-
- public static final String TERM_MATCH_TYPE_FIELD = "termMatchType";
-
- /** @hide */
-
- public static final String SCHEMA_TYPES_FIELD = "schemaType";
-
- /** @hide */
-
- public static final String NAMESPACE_FIELD = "namespace";
-
- /** @hide */
-
- public static final String NUM_PER_PAGE_FIELD = "numPerPage";
-
- /** @hide */
-
- public static final String RANKING_STRATEGY_FIELD = "rankingStrategy";
-
- /** @hide */
-
- public static final String ORDER_FIELD = "order";
-
- /** @hide */
-
- public static final String SNIPPET_COUNT_FIELD = "snippetCount";
-
- /** @hide */
-
- public static final String SNIPPET_COUNT_PER_PROPERTY_FIELD = "snippetCountPerProperty";
-
- /** @hide */
-
- public static final String MAX_SNIPPET_FIELD = "maxSnippet";
+ static final String TERM_MATCH_TYPE_FIELD = "termMatchType";
+ static final String SCHEMA_TYPE_FIELD = "schemaType";
+ static final String NAMESPACE_FIELD = "namespace";
+ static final String NUM_PER_PAGE_FIELD = "numPerPage";
+ static final String RANKING_STRATEGY_FIELD = "rankingStrategy";
+ static final String ORDER_FIELD = "order";
+ static final String SNIPPET_COUNT_FIELD = "snippetCount";
+ static final String SNIPPET_COUNT_PER_PROPERTY_FIELD = "snippetCountPerProperty";
+ static final String MAX_SNIPPET_FIELD = "maxSnippet";
/** @hide */
public static final int DEFAULT_NUM_PER_PAGE = 10;
+ // TODO(b/170371356): In framework, we may want these limits might be flag controlled.
private static final int MAX_NUM_PER_PAGE = 10_000;
private static final int MAX_SNIPPET_COUNT = 10_000;
private static final int MAX_SNIPPET_PER_PROPERTY_COUNT = 10_000;
private static final int MAX_SNIPPET_SIZE_LIMIT = 10_000;
- private final Bundle mBundle;
-
- /** @hide */
-
- public SearchSpec(@NonNull Bundle bundle) {
- Preconditions.checkNotNull(bundle);
- mBundle = bundle;
- }
-
- /**
- * Returns the {@link Bundle} populated by this builder.
- * @hide
- */
- @NonNull
- public Bundle getBundle() {
- return mBundle;
- }
-
/**
* Term Match Type for the query.
* @hide
@@ -108,7 +72,7 @@ public final class SearchSpec {
TERM_MATCH_PREFIX
})
@Retention(RetentionPolicy.SOURCE)
- public @interface TermMatchCode {}
+ public @interface TermMatch {}
/**
* Query terms will only match exact tokens in the index.
@@ -126,14 +90,14 @@ public final class SearchSpec {
* @hide
*/
// NOTE: The integer values of these constants must match the proto enum constants in
- // {@link ScoringSpecProto.RankingStrategy.Code }
+ // {@link ScoringSpecProto.RankingStrategy.Code}
@IntDef(value = {
RANKING_STRATEGY_NONE,
RANKING_STRATEGY_DOCUMENT_SCORE,
RANKING_STRATEGY_CREATION_TIMESTAMP
})
@Retention(RetentionPolicy.SOURCE)
- public @interface RankingStrategyCode {}
+ public @interface RankingStrategy {}
/** No Ranking, results are returned in arbitrary order.*/
public static final int RANKING_STRATEGY_NONE = 0;
@@ -147,23 +111,109 @@ public final class SearchSpec {
* @hide
*/
// NOTE: The integer values of these constants must match the proto enum constants in
- // {@link ScoringSpecProto.Order.Code }
+ // {@link ScoringSpecProto.Order.Code}
@IntDef(value = {
ORDER_DESCENDING,
ORDER_ASCENDING
})
@Retention(RetentionPolicy.SOURCE)
- public @interface OrderCode {}
+ public @interface Order {}
/** Search results will be returned in a descending order. */
public static final int ORDER_DESCENDING = 0;
/** Search results will be returned in an ascending order. */
public static final int ORDER_ASCENDING = 1;
+ private final Bundle mBundle;
+
+ /** @hide */
+
+ public SearchSpec(@NonNull Bundle bundle) {
+ Preconditions.checkNotNull(bundle);
+ mBundle = bundle;
+ }
+
+ /**
+ * Returns the {@link Bundle} populated by this builder.
+ * @hide
+ */
+
+ @NonNull
+ public Bundle getBundle() {
+ return mBundle;
+ }
+
+ /** Returns how the query terms should match terms in the index. */
+ public @TermMatch int getTermMatch() {
+ return mBundle.getInt(TERM_MATCH_TYPE_FIELD, -1);
+ }
+
+ /**
+ * Returns the list of schema types to search for.
+ *
+ * <p>If empty, the query will search over all schema types.
+ */
+ @NonNull
+ public List<String> getSchemas() {
+ List<String> schemas = mBundle.getStringArrayList(SCHEMA_TYPE_FIELD);
+ if (schemas == null) {
+ return Collections.emptyList();
+ }
+ return Collections.unmodifiableList(schemas);
+ }
+
+ /**
+ * Returns the list of namespaces to search for.
+ *
+ * <p>If empty, the query will search over all namespaces.
+ */
+ @NonNull
+ public List<String> getNamespaces() {
+ List<String> namespaces = mBundle.getStringArrayList(NAMESPACE_FIELD);
+ if (namespaces == null) {
+ return Collections.emptyList();
+ }
+ return Collections.unmodifiableList(namespaces);
+ }
+
+ /** Returns the number of results per page in the returned object. */
+ public int getNumPerPage() {
+ return mBundle.getInt(NUM_PER_PAGE_FIELD, DEFAULT_NUM_PER_PAGE);
+ }
+
+ /** Returns the ranking strategy. */
+ public @RankingStrategy int getRankingStrategy() {
+ return mBundle.getInt(RANKING_STRATEGY_FIELD);
+ }
+
+ /** Returns the order of returned search results (descending or ascending). */
+ public @Order int getOrder() {
+ return mBundle.getInt(ORDER_FIELD);
+ }
+
+ /** Returns how many documents to generate snippets for. */
+ public int getSnippetCount() {
+ return mBundle.getInt(SNIPPET_COUNT_FIELD);
+ }
+
+ /**
+ * Returns how many matches for each property of a matching document to generate snippets for.
+ */
+ public int getSnippetCountPerProperty() {
+ return mBundle.getInt(SNIPPET_COUNT_PER_PROPERTY_FIELD);
+ }
+
+ /** Returns the maximum size of a snippet in characters. */
+ public int getMaxSnippetSize() {
+ return mBundle.getInt(MAX_SNIPPET_FIELD);
+ }
+
/** Builder for {@link SearchSpec objects}. */
public static final class Builder {
private final Bundle mBundle;
+ private final ArrayList<String> mSchemaTypes = new ArrayList<>();
+ private final ArrayList<String> mNamespaces = new ArrayList<>();
private boolean mBuilt = false;
/** Creates a new {@link SearchSpec.Builder}. */
@@ -176,7 +226,7 @@ public final class SearchSpec {
* Indicates how the query terms should match {@code TermMatchCode} in the index.
*/
@NonNull
- public Builder setTermMatch(@TermMatchCode int termMatchTypeCode) {
+ public Builder setTermMatch(@TermMatch int termMatchTypeCode) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkArgumentInRange(termMatchTypeCode, TERM_MATCH_EXACT_ONLY,
TERM_MATCH_PREFIX, "Term match type");
@@ -187,13 +237,27 @@ public final class SearchSpec {
/**
* Adds a Schema type filter to {@link SearchSpec} Entry. Only search for documents that
* have the specified schema types.
+ *
* <p>If unset, the query will search over all schema types.
*/
@NonNull
- public Builder setSchemaTypes(@NonNull String... schemaTypes) {
+ public Builder addSchema(@NonNull String... schemaTypes) {
Preconditions.checkNotNull(schemaTypes);
Preconditions.checkState(!mBuilt, "Builder has already been used");
- mBundle.putStringArray(SCHEMA_TYPES_FIELD, schemaTypes);
+ return addSchema(Arrays.asList(schemaTypes));
+ }
+
+ /**
+ * Adds a Schema type filter to {@link SearchSpec} Entry. Only search for documents that
+ * have the specified schema types.
+ *
+ * <p>If unset, the query will search over all schema types.
+ */
+ @NonNull
+ public Builder addSchema(@NonNull Collection<String> schemaTypes) {
+ Preconditions.checkNotNull(schemaTypes);
+ Preconditions.checkState(!mBuilt, "Builder has already been used");
+ mSchemaTypes.addAll(schemaTypes);
return this;
}
@@ -203,10 +267,22 @@ public final class SearchSpec {
* <p>If unset, the query will search over all namespaces.
*/
@NonNull
- public Builder setNamespaces(@NonNull String... namespaces) {
+ public Builder addNamespace(@NonNull String... namespaces) {
+ Preconditions.checkNotNull(namespaces);
+ Preconditions.checkState(!mBuilt, "Builder has already been used");
+ return addNamespace(Arrays.asList(namespaces));
+ }
+
+ /**
+ * Adds a namespace filter to {@link SearchSpec} Entry. Only search for documents that
+ * have the specified namespaces.
+ * <p>If unset, the query will search over all namespaces.
+ */
+ @NonNull
+ public Builder addNamespace(@NonNull Collection<String> namespaces) {
Preconditions.checkNotNull(namespaces);
Preconditions.checkState(!mBuilt, "Builder has already been used");
- mBundle.putStringArray(NAMESPACE_FIELD, namespaces);
+ mNamespaces.addAll(namespaces);
return this;
}
@@ -224,7 +300,7 @@ public final class SearchSpec {
/** Sets ranking strategy for AppSearch results.*/
@NonNull
- public Builder setRankingStrategy(@RankingStrategyCode int rankingStrategy) {
+ public Builder setRankingStrategy(@RankingStrategy int rankingStrategy) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkArgumentInRange(rankingStrategy, RANKING_STRATEGY_NONE,
RANKING_STRATEGY_CREATION_TIMESTAMP, "Result ranking strategy");
@@ -238,7 +314,7 @@ public final class SearchSpec {
* <p>This order field will be ignored if RankingStrategy = {@code RANKING_STRATEGY_NONE}.
*/
@NonNull
- public Builder setOrder(@OrderCode int order) {
+ public Builder setOrder(@Order int order) {
Preconditions.checkState(!mBuilt, "Builder has already been used");
Preconditions.checkArgumentInRange(order, ORDER_DESCENDING, ORDER_ASCENDING,
"Result ranking order");
@@ -264,11 +340,12 @@ public final class SearchSpec {
}
/**
- * Only the first {@code matchesCountPerProperty} matches for a every property of
- * {@link GenericDocument} will contain snippet information.
+ * Sets {@code snippetCountPerProperty}. Only the first {@code snippetCountPerProperty}
+ * snippets for a every property of {@link GenericDocument} will contain snippet
+ * information.
*
- * <p>If set to 0, snippeting is disabled and {@link SearchResult#getMatches} will return
- * {@code null} for that result.
+ * <p>If set to 0, snippeting is disabled and {@link SearchResult#getMatches}
+ * will return {@code null} for that result.
*
* <p>The value should be set in range[0, 10k].
*/
@@ -286,10 +363,13 @@ public final class SearchSpec {
* {@code maxSnippetSize/2} bytes before the middle of the matching token and end at
* {@code maxSnippetSize/2} bytes after the middle of the matching token. It respects
* token boundaries, therefore the returned window may be smaller than requested.
+ *
* <p> Setting {@code maxSnippetSize} to 0 will disable windowing and an empty string will
* be returned. If matches enabled is also set to false, then snippeting is disabled.
+ *
* <p>Ex. {@code maxSnippetSize} = 16. "foo bar baz bat rat" with a query of "baz" will
* return a window of "bar baz bat" which is only 11 bytes long.
+ *
* <p>The value should be in range[0, 10k].
*/
@NonNull
@@ -312,6 +392,8 @@ public final class SearchSpec {
if (!mBundle.containsKey(TERM_MATCH_TYPE_FIELD)) {
throw new IllegalSearchSpecException("Missing termMatchType field.");
}
+ mBundle.putStringArrayList(NAMESPACE_FIELD, mNamespaces);
+ mBundle.putStringArrayList(SCHEMA_TYPE_FIELD, mSchemaTypes);
mBuilt = true;
return new SearchSpec(mBundle);
}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java b/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java
index b2e9d469764d..f2c81564908c 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/SetSchemaRequest.java
@@ -16,13 +16,17 @@
package android.app.appsearch;
+import android.annotation.SuppressLint;
+
import android.annotation.NonNull;
+import android.app.appsearch.exceptions.AppSearchException;
import android.util.ArraySet;
-
import com.android.internal.util.Preconditions;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
import java.util.Set;
/**
@@ -40,15 +44,13 @@ public final class SetSchemaRequest {
mForceOverride = forceOverride;
}
- /** @hide */
-
+ /** Returns the schemas that are part of this request. */
@NonNull
public Set<AppSearchSchema> getSchemas() {
return mSchemas;
}
- /** @hide */
-
+ /** Returns whether this request will force the schema to be overridden. */
public boolean isForceOverride() {
return mForceOverride;
}
diff --git a/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java b/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java
index d490469be3d6..15d0992cd081 100644
--- a/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java
+++ b/apex/appsearch/framework/java/android/app/appsearch/exceptions/AppSearchException.java
@@ -54,6 +54,7 @@ public class AppSearchException extends Exception {
mResultCode = resultCode;
}
+ /** Returns the result code this exception was constructed with. */
public @AppSearchResult.ResultCode int getResultCode() {
return mResultCode;
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
index 7cd6ee24cb20..f2830e5b8e6d 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -33,11 +33,11 @@ import android.os.UserHandle;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.Preconditions;
import com.android.server.SystemService;
-import com.android.server.appsearch.external.localbackend.AppSearchImpl;
-import com.android.server.appsearch.external.localbackend.converter.GenericDocumentToProtoConverter;
-import com.android.server.appsearch.external.localbackend.converter.SchemaToProtoConverter;
-import com.android.server.appsearch.external.localbackend.converter.SearchResultToProtoConverter;
-import com.android.server.appsearch.external.localbackend.converter.SearchSpecToProtoConverter;
+import com.android.server.appsearch.external.localstorage.AppSearchImpl;
+import com.android.server.appsearch.external.localstorage.converter.GenericDocumentToProtoConverter;
+import com.android.server.appsearch.external.localstorage.converter.SchemaToProtoConverter;
+import com.android.server.appsearch.external.localstorage.converter.SearchResultToProtoConverter;
+import com.android.server.appsearch.external.localstorage.converter.SearchSpecToProtoConverter;
import com.google.android.icing.proto.DocumentProto;
import com.google.android.icing.proto.SchemaProto;
@@ -46,6 +46,7 @@ import com.google.android.icing.proto.SearchResultProto;
import com.google.android.icing.proto.SearchSpecProto;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -193,7 +194,12 @@ public class AppSearchManagerService extends SystemService {
SearchSpecToProtoConverter.toResultSpecProto(searchSpec),
SearchSpecToProtoConverter.toScoringSpecProto(searchSpec));
List<SearchResult> searchResultList =
- SearchResultToProtoConverter.convert(searchResultProto);
+ new ArrayList<>(searchResultProto.getResultsCount());
+ for (int i = 0; i < searchResultProto.getResultsCount(); i++) {
+ SearchResult result = SearchResultToProtoConverter.convertSearchResult(
+ searchResultProto.getResults(i));
+ searchResultList.add(result);
+ }
SearchResults searchResults =
new SearchResults(searchResultList, searchResultProto.getNextPageToken());
callback.complete(AppSearchResult.newSuccessfulResult(searchResults));
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
index 60f7005a7c0a..2871eb622f11 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
@@ -24,7 +24,7 @@ import android.os.Environment;
import android.os.storage.StorageManager;
import android.util.SparseArray;
-import com.android.server.appsearch.external.localbackend.AppSearchImpl;
+import com.android.server.appsearch.external.localstorage.AppSearchImpl;
import java.io.File;
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index 642378d992ac..b1a79f84714d 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/AppSearchImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.appsearch.external.localbackend;
+package com.android.server.appsearch.external.localstorage;
import android.util.Log;
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java
index fdeb90dc9b0e..60684f09a202 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverter.java
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-package com.android.server.appsearch.external.localbackend.converter;
-
-import android.os.Bundle;
+package com.android.server.appsearch.external.localstorage.converter;
import android.annotation.NonNull;
@@ -43,7 +41,6 @@ public final class GenericDocumentToProtoConverter {
@SuppressWarnings("unchecked")
public static DocumentProto convert(@NonNull GenericDocument document) {
Preconditions.checkNotNull(document);
- Bundle properties = document.getBundle().getBundle(GenericDocument.PROPERTIES_FIELD);
DocumentProto.Builder mProtoBuilder = DocumentProto.newBuilder();
mProtoBuilder.setUri(document.getUri())
.setSchema(document.getSchemaType())
@@ -51,42 +48,45 @@ public final class GenericDocumentToProtoConverter {
.setScore(document.getScore())
.setTtlMs(document.getTtlMillis())
.setCreationTimestampMs(document.getCreationTimestampMillis());
- ArrayList<String> keys = new ArrayList<>(properties.keySet());
+ ArrayList<String> keys = new ArrayList<>(document.getPropertyNames());
Collections.sort(keys);
for (int i = 0; i < keys.size(); i++) {
String name = keys.get(i);
- Object values = properties.get(name);
PropertyProto.Builder propertyProto = PropertyProto.newBuilder().setName(name);
- if (values instanceof boolean[]) {
- for (boolean value : (boolean[]) values) {
- propertyProto.addBooleanValues(value);
+ String[] stringValues = document.getPropertyStringArray(name);
+ long[] longValues = document.getPropertyLongArray(name);
+ double[] doubleValues = document.getPropertyDoubleArray(name);
+ boolean[] booleanValues = document.getPropertyBooleanArray(name);
+ byte[][] bytesValues = document.getPropertyBytesArray(name);
+ GenericDocument[] documentValues = document.getPropertyDocumentArray(name);
+ if (stringValues != null) {
+ for (int j = 0; j < stringValues.length; j++) {
+ propertyProto.addStringValues(stringValues[j]);
}
- } else if (values instanceof long[]) {
- for (long value : (long[]) values) {
- propertyProto.addInt64Values(value);
+ } else if (longValues != null) {
+ for (int j = 0; j < longValues.length; j++) {
+ propertyProto.addInt64Values(longValues[j]);
}
- } else if (values instanceof double[]) {
- for (double value : (double[]) values) {
- propertyProto.addDoubleValues(value);
+ } else if (doubleValues != null) {
+ for (int j = 0; j < doubleValues.length; j++) {
+ propertyProto.addDoubleValues(doubleValues[j]);
}
- } else if (values instanceof String[]) {
- for (String value : (String[]) values) {
- propertyProto.addStringValues(value);
+ } else if (booleanValues != null) {
+ for (int j = 0; j < booleanValues.length; j++) {
+ propertyProto.addBooleanValues(booleanValues[j]);
}
- } else if (values instanceof ArrayList) {
- for (Bundle bundle : (ArrayList<Bundle>) values) {
- byte[] value = bundle.getByteArray(GenericDocument.BYTE_ARRAY_FIELD);
- propertyProto.addBytesValues(ByteString.copyFrom(value));
+ } else if (bytesValues != null) {
+ for (int j = 0; j < bytesValues.length; j++) {
+ propertyProto.addBytesValues(ByteString.copyFrom(bytesValues[j]));
}
- } else if (values instanceof Bundle[]) {
- for (Bundle bundle : (Bundle[]) values) {
- GenericDocument value = new GenericDocument(bundle);
- propertyProto.addDocumentValues(convert(value));
+ } else if (documentValues != null) {
+ for (int j = 0; j < documentValues.length; j++) {
+ DocumentProto proto = convert(documentValues[j]);
+ propertyProto.addDocumentValues(proto);
}
} else {
throw new IllegalStateException(
- "Property \"" + name + "\" has unsupported value type \""
- + values.getClass().getSimpleName() + "\"");
+ "Property \"" + name + "\" has unsupported value type");
}
mProtoBuilder.addProperties(propertyProto);
}
@@ -107,42 +107,42 @@ public final class GenericDocumentToProtoConverter {
for (int i = 0; i < proto.getPropertiesCount(); i++) {
PropertyProto property = proto.getProperties(i);
String name = property.getName();
- if (property.getBooleanValuesCount() > 0) {
- boolean[] values = new boolean[property.getBooleanValuesCount()];
+ if (property.getStringValuesCount() > 0) {
+ String[] values = new String[property.getStringValuesCount()];
for (int j = 0; j < values.length; j++) {
- values[j] = property.getBooleanValues(j);
+ values[j] = property.getStringValues(j);
}
- documentBuilder.setProperty(name, values);
+ documentBuilder.setPropertyString(name, values);
} else if (property.getInt64ValuesCount() > 0) {
long[] values = new long[property.getInt64ValuesCount()];
for (int j = 0; j < values.length; j++) {
values[j] = property.getInt64Values(j);
}
- documentBuilder.setProperty(name, values);
+ documentBuilder.setPropertyLong(name, values);
} else if (property.getDoubleValuesCount() > 0) {
double[] values = new double[property.getDoubleValuesCount()];
for (int j = 0; j < values.length; j++) {
values[j] = property.getDoubleValues(j);
}
- documentBuilder.setProperty(name, values);
- } else if (property.getStringValuesCount() > 0) {
- String[] values = new String[property.getStringValuesCount()];
+ documentBuilder.setPropertyDouble(name, values);
+ } else if (property.getBooleanValuesCount() > 0) {
+ boolean[] values = new boolean[property.getBooleanValuesCount()];
for (int j = 0; j < values.length; j++) {
- values[j] = property.getStringValues(j);
+ values[j] = property.getBooleanValues(j);
}
- documentBuilder.setProperty(name, values);
+ documentBuilder.setPropertyBoolean(name, values);
} else if (property.getBytesValuesCount() > 0) {
byte[][] values = new byte[property.getBytesValuesCount()][];
for (int j = 0; j < values.length; j++) {
values[j] = property.getBytesValues(j).toByteArray();
}
- documentBuilder.setProperty(name, values);
+ documentBuilder.setPropertyBytes(name, values);
} else if (property.getDocumentValuesCount() > 0) {
GenericDocument[] values = new GenericDocument[property.getDocumentValuesCount()];
for (int j = 0; j < values.length; j++) {
values[j] = convert(property.getDocumentValues(j));
}
- documentBuilder.setProperty(name, values);
+ documentBuilder.setPropertyDocument(name, values);
} else {
throw new IllegalStateException("Unknown type of value: " + name);
}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java
index ca0d2ee970cb..403711f29544 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverter.java
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-package com.android.server.appsearch.external.localbackend.converter;
-
-import android.os.Bundle;
+package com.android.server.appsearch.external.localstorage.converter;
import android.annotation.NonNull;
@@ -28,7 +26,7 @@ import com.google.android.icing.proto.PropertyConfigProto;
import com.google.android.icing.proto.SchemaTypeConfigProto;
import com.google.android.icing.proto.TermMatchType;
-import java.util.ArrayList;
+import java.util.List;
/**
* Translates an {@link AppSearchSchema} into a {@link SchemaTypeConfigProto}.
@@ -45,31 +43,26 @@ public final class SchemaToProtoConverter {
@NonNull
public static SchemaTypeConfigProto convert(@NonNull AppSearchSchema schema) {
Preconditions.checkNotNull(schema);
- Bundle bundle = schema.getBundle();
SchemaTypeConfigProto.Builder protoBuilder =
- SchemaTypeConfigProto.newBuilder()
- .setSchemaType(bundle.getString(AppSearchSchema.SCHEMA_TYPE_FIELD, ""));
- ArrayList<Bundle> properties =
- bundle.getParcelableArrayList(AppSearchSchema.PROPERTIES_FIELD);
- if (properties != null) {
- for (int i = 0; i < properties.size(); i++) {
- PropertyConfigProto propertyProto = convertProperty(properties.get(i));
- protoBuilder.addProperties(propertyProto);
- }
+ SchemaTypeConfigProto.newBuilder().setSchemaType(schema.getSchemaTypeName());
+ List<AppSearchSchema.PropertyConfig> properties = schema.getProperties();
+ for (int i = 0; i < properties.size(); i++) {
+ PropertyConfigProto propertyProto = convertProperty(properties.get(i));
+ protoBuilder.addProperties(propertyProto);
}
return protoBuilder.build();
}
@NonNull
- private static PropertyConfigProto convertProperty(@NonNull Bundle bundle) {
- Preconditions.checkNotNull(bundle);
+ private static PropertyConfigProto convertProperty(
+ @NonNull AppSearchSchema.PropertyConfig property) {
+ Preconditions.checkNotNull(property);
PropertyConfigProto.Builder propertyConfigProto = PropertyConfigProto.newBuilder()
- .setPropertyName(bundle.getString(AppSearchSchema.PropertyConfig.NAME_FIELD, ""));
+ .setPropertyName(property.getName());
IndexingConfig.Builder indexingConfig = IndexingConfig.newBuilder();
// Set dataType
- @AppSearchSchema.PropertyConfig.DataType int dataType =
- bundle.getInt(AppSearchSchema.PropertyConfig.DATA_TYPE_FIELD);
+ @AppSearchSchema.PropertyConfig.DataType int dataType = property.getDataType();
PropertyConfigProto.DataType.Code dataTypeProto =
PropertyConfigProto.DataType.Code.forNumber(dataType);
if (dataTypeProto == null) {
@@ -78,12 +71,13 @@ public final class SchemaToProtoConverter {
propertyConfigProto.setDataType(dataTypeProto);
// Set schemaType
- propertyConfigProto.setSchemaType(
- bundle.getString(AppSearchSchema.PropertyConfig.SCHEMA_TYPE_FIELD, ""));
+ String schemaType = property.getSchemaType();
+ if (schemaType != null) {
+ propertyConfigProto.setSchemaType(schemaType);
+ }
// Set cardinality
- @AppSearchSchema.PropertyConfig.Cardinality int cardinality =
- bundle.getInt(AppSearchSchema.PropertyConfig.CARDINALITY_FIELD);
+ @AppSearchSchema.PropertyConfig.Cardinality int cardinality = property.getCardinality();
PropertyConfigProto.Cardinality.Code cardinalityProto =
PropertyConfigProto.Cardinality.Code.forNumber(cardinality);
if (cardinalityProto == null) {
@@ -92,8 +86,7 @@ public final class SchemaToProtoConverter {
propertyConfigProto.setCardinality(cardinalityProto);
// Set indexingType
- @AppSearchSchema.PropertyConfig.IndexingType int indexingType =
- bundle.getInt(AppSearchSchema.PropertyConfig.INDEXING_TYPE_FIELD);
+ @AppSearchSchema.PropertyConfig.IndexingType int indexingType = property.getIndexingType();
TermMatchType.Code termMatchTypeProto;
switch (indexingType) {
case AppSearchSchema.PropertyConfig.INDEXING_TYPE_NONE:
@@ -112,7 +105,7 @@ public final class SchemaToProtoConverter {
// Set tokenizerType
@AppSearchSchema.PropertyConfig.TokenizerType int tokenizerType =
- bundle.getInt(AppSearchSchema.PropertyConfig.TOKENIZER_TYPE_FIELD);
+ property.getTokenizerType();
IndexingConfig.TokenizerType.Code tokenizerTypeProto =
IndexingConfig.TokenizerType.Code.forNumber(tokenizerType);
if (tokenizerTypeProto == null) {
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchResultToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java
index 524c80dd0609..9f7c6968e993 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchResultToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchResultToProtoConverter.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.appsearch.external.localbackend.converter;
+package com.android.server.appsearch.external.localstorage.converter;
import android.os.Bundle;
@@ -22,43 +22,32 @@ import android.annotation.NonNull;
import android.app.appsearch.GenericDocument;
import android.app.appsearch.SearchResult;
-import android.app.appsearch.SearchResults;
import com.google.android.icing.proto.SearchResultProto;
import com.google.android.icing.proto.SnippetMatchProto;
import com.google.android.icing.proto.SnippetProto;
import java.util.ArrayList;
-import java.util.List;
/**
- * Translates a {@link SearchResultProto} into {@link SearchResults}.
+ * Translates a {@link SearchResultProto} into {@link SearchResult}s.
+ *
* @hide
*/
public class SearchResultToProtoConverter {
private SearchResultToProtoConverter() {}
- /** Translates a {@link SearchResultProto} into a list of {@link SearchResult}. */
- @NonNull
- public static List<SearchResult> convert(@NonNull SearchResultProto searchResultProto) {
- List<SearchResult> results = new ArrayList<>(searchResultProto.getResultsCount());
- for (int i = 0; i < searchResultProto.getResultsCount(); i++) {
- results.add(convertSearchResult(searchResultProto.getResults(i)));
- }
- return results;
- }
-
/** Translate a {@link SearchResultProto.ResultProto} into {@link SearchResult}. */
@NonNull
- static SearchResult convertSearchResult(@NonNull SearchResultProto.ResultProto proto) {
+ public static SearchResult convertSearchResult(
+ @NonNull SearchResultProto.ResultProtoOrBuilder proto) {
Bundle bundle = new Bundle();
GenericDocument document = GenericDocumentToProtoConverter.convert(proto.getDocument());
bundle.putBundle(SearchResult.DOCUMENT_FIELD, document.getBundle());
- ArrayList<Bundle> matchList = null;
+ ArrayList<Bundle> matchList = new ArrayList<>();
if (proto.hasSnippet()) {
- matchList = new ArrayList<>();
for (int i = 0; i < proto.getSnippet().getEntriesCount(); i++) {
SnippetProto.EntryProto entry = proto.getSnippet().getEntries(i);
for (int j = 0; j < entry.getSnippetMatchesCount(); j++) {
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchSpecToProtoConverter.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java
index a5d913a20590..14822dcdc793 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localbackend/converter/SearchSpecToProtoConverter.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/converter/SearchSpecToProtoConverter.java
@@ -14,9 +14,7 @@
* limitations under the License.
*/
-package com.android.server.appsearch.external.localbackend.converter;
-
-import android.os.Bundle;
+package com.android.server.appsearch.external.localstorage.converter;
import android.annotation.NonNull;
@@ -28,8 +26,6 @@ import com.google.android.icing.proto.ScoringSpecProto;
import com.google.android.icing.proto.SearchSpecProto;
import com.google.android.icing.proto.TermMatchType;
-import java.util.Arrays;
-
/**
* Translates a {@link SearchSpec} into icing search protos.
* @hide
@@ -42,25 +38,17 @@ public final class SearchSpecToProtoConverter {
@NonNull
public static SearchSpecProto toSearchSpecProto(@NonNull SearchSpec spec) {
Preconditions.checkNotNull(spec);
- Bundle bundle = spec.getBundle();
- SearchSpecProto.Builder protoBuilder = SearchSpecProto.newBuilder();
+ SearchSpecProto.Builder protoBuilder = SearchSpecProto.newBuilder()
+ .addAllSchemaTypeFilters(spec.getSchemas())
+ .addAllNamespaceFilters(spec.getNamespaces());
- @SearchSpec.TermMatchCode int termMatchCode =
- bundle.getInt(SearchSpec.TERM_MATCH_TYPE_FIELD);
+ @SearchSpec.TermMatch int termMatchCode = spec.getTermMatch();
TermMatchType.Code termMatchCodeProto = TermMatchType.Code.forNumber(termMatchCode);
if (termMatchCodeProto == null || termMatchCodeProto.equals(TermMatchType.Code.UNKNOWN)) {
throw new IllegalArgumentException("Invalid term match type: " + termMatchCode);
}
protoBuilder.setTermMatchType(termMatchCodeProto);
- String[] schemaTypes = bundle.getStringArray(SearchSpec.SCHEMA_TYPES_FIELD);
- if (schemaTypes != null) {
- protoBuilder.addAllSchemaTypeFilters(Arrays.asList(schemaTypes));
- }
- String[] namespaces = bundle.getStringArray(SearchSpec.NAMESPACE_FIELD);
- if (namespaces != null) {
- protoBuilder.addAllNamespaceFilters(Arrays.asList(namespaces));
- }
return protoBuilder.build();
}
@@ -68,27 +56,23 @@ public final class SearchSpecToProtoConverter {
@NonNull
public static ResultSpecProto toResultSpecProto(@NonNull SearchSpec spec) {
Preconditions.checkNotNull(spec);
- Bundle bundle = spec.getBundle();
return ResultSpecProto.newBuilder()
- .setNumPerPage(bundle.getInt(
- SearchSpec.NUM_PER_PAGE_FIELD, SearchSpec.DEFAULT_NUM_PER_PAGE))
- .setSnippetSpec(ResultSpecProto.SnippetSpecProto.newBuilder()
- .setNumToSnippet(bundle.getInt(SearchSpec.SNIPPET_COUNT_FIELD))
- .setNumMatchesPerProperty(
- bundle.getInt(SearchSpec.SNIPPET_COUNT_PER_PROPERTY_FIELD))
- .setMaxWindowBytes(bundle.getInt(SearchSpec.MAX_SNIPPET_FIELD)))
+ .setNumPerPage(spec.getNumPerPage())
+ .setSnippetSpec(
+ ResultSpecProto.SnippetSpecProto.newBuilder()
+ .setNumToSnippet(spec.getSnippetCount())
+ .setNumMatchesPerProperty(spec.getSnippetCountPerProperty())
+ .setMaxWindowBytes(spec.getMaxSnippetSize()))
.build();
-
}
/** Extracts {@link ScoringSpecProto} information from a {@link SearchSpec}. */
@NonNull
public static ScoringSpecProto toScoringSpecProto(@NonNull SearchSpec spec) {
Preconditions.checkNotNull(spec);
- Bundle bundle = spec.getBundle();
ScoringSpecProto.Builder protoBuilder = ScoringSpecProto.newBuilder();
- @SearchSpec.OrderCode int orderCode = bundle.getInt(SearchSpec.ORDER_FIELD);
+ @SearchSpec.Order int orderCode = spec.getOrder();
ScoringSpecProto.Order.Code orderCodeProto =
ScoringSpecProto.Order.Code.forNumber(orderCode);
if (orderCodeProto == null) {
@@ -96,8 +80,7 @@ public final class SearchSpecToProtoConverter {
}
protoBuilder.setOrderBy(orderCodeProto);
- @SearchSpec.RankingStrategyCode int rankingStrategyCode =
- bundle.getInt(SearchSpec.RANKING_STRATEGY_FIELD);
+ @SearchSpec.RankingStrategy int rankingStrategyCode = spec.getRankingStrategy();
ScoringSpecProto.RankingStrategy.Code rankingStrategyCodeProto =
ScoringSpecProto.RankingStrategy.Code.forNumber(rankingStrategyCode);
if (rankingStrategyCodeProto == null) {
diff --git a/apex/extservices/Android.bp b/apex/extservices/Android.bp
deleted file mode 100644
index 0c6c4c23dce1..000000000000
--- a/apex/extservices/Android.bp
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-apex {
- name: "com.android.extservices",
- defaults: ["com.android.extservices-defaults"],
- manifest: "apex_manifest.json",
-}
-
-apex_defaults {
- name: "com.android.extservices-defaults",
- updatable: true,
- min_sdk_version: "current",
- key: "com.android.extservices.key",
- certificate: ":com.android.extservices.certificate",
- apps: ["ExtServices"],
-}
-
-apex_key {
- name: "com.android.extservices.key",
- public_key: "com.android.extservices.avbpubkey",
- private_key: "com.android.extservices.pem",
-}
-
-android_app_certificate {
- name: "com.android.extservices.certificate",
- certificate: "com.android.extservices",
-}
diff --git a/apex/extservices/apex_manifest.json b/apex/extservices/apex_manifest.json
deleted file mode 100644
index b4acf1283d3e..000000000000
--- a/apex/extservices/apex_manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.extservices",
- "version": 300000000
-}
diff --git a/apex/extservices/com.android.extservices.avbpubkey b/apex/extservices/com.android.extservices.avbpubkey
deleted file mode 100644
index f37d3e4a14d4..000000000000
--- a/apex/extservices/com.android.extservices.avbpubkey
+++ /dev/null
Binary files differ
diff --git a/apex/extservices/com.android.extservices.pem b/apex/extservices/com.android.extservices.pem
deleted file mode 100644
index 7bfbd34ff9b9..000000000000
--- a/apex/extservices/com.android.extservices.pem
+++ /dev/null
@@ -1,51 +0,0 @@
------BEGIN RSA PRIVATE KEY-----
-MIIJKAIBAAKCAgEAuYshVDiRkt3tmBhqcWkKOm5GcviKpLbHSPpYQDHGDwS0dqqL
-SqAd1/BgT/bVVtUkAciFApPnXn96WhNYCypptyC5FHCxM21uBCGmow+3WermD++w
-5dQk4QP2ONPIpG+KzOWBl9SiBud4SpOHDyr0JycBsrXS89Tln9kAsTDuDEFfXL/J
-8cX/S3IUwhPV0pAlgUIHdDp0DGFjZaJlEZBZ+HmImriC/AUNUMVb5lfbczXOEZPF
-0A9+JzYschfXUxn8nu1N7RN5GDbq+chszx1FMVhuFUheukkd4dLNSDl0O0RlUnD+
-C/xz1ilDzEVZhnMtMnxS9oJ8bA/HUVMfsFnaQbgGmQ0CcxFxnfbYyGXGG1H+b8vA
-MTVQi5rZXG2p+VgHIAKVrYmpETVnRPgoMqp18KuGtp5SDngi13G3YEzS7iFbqfYh
-6iW2G974nD/Dq0cSire8Oljd9PEaMCMZiP5PTFJp0G/mtw7ROoyZqsSM6rX3XVTo
-Y5dBmBMctSJ8rgDMi0ZNvRH+rq/E5+RT6yMAJ7DDbOJzBnQ3IIoGn8NzUT3P1FCB
-HYEp1U2N7QNirIQMAuVz3IlHae9N1kl3eGAO6f2CjV7vZmFpDeWw+KSYs71mRkOb
-WBgl6D9FFq4u1azrU3AwV0dj3x1eU6yVnKUy1J7ppF/mcR+VzH7ThzTdV7cCAwEA
-AQKCAgEApWFU2Mv/PYhg0bPZlLLKsiA+3RWaBo0AfpTd+oIjBpnr/OWweFjVoPcZ
-8cyShe4/RPOlUxHgJcO8m/MoA/PO/LLHJWf5GlzMthQEgs1sYVJVtBiydXitUn+E
-hUyIR8FAV7et1lZqAXtqJhbvSF7B9u/2vIMCv+GgtuTmkAmL9RKD3Jj6eG1CS84o
-oICrkx52v4rKOBgt/icEQMAKFCi1eRti3n3eCqK6JqdzbZIcAcoQnmw34mccy/im
-jx+fBuxf1oywa8NyqVmyAehazBVL6lrm7ENwY9zuLK4H2fuUFYu2QFCEsMxZt6da
-TgX2cTfSLnDQRfcyzeMWhu9vjHHabjpLNjiCKhIhGyO0rO1rtea8ajZHgM/2sxXq
-6gLynW0dlatlxmjANlN9WQPGNdzvcIFJ0TLnI4mlJnWpqCsN9iW1d4ey13WiZUVR
-DgtnR60zao+LRCCM4D3cuVLq0DjL2BlHGXnOPK/LpQG1LbI1TroZpgSEHSZlQRzT
-ql9txgNqTHxijXuPL2VhhwhW7cqDoO8sLwV3BqDMIH56U0cbUBiSA/G9fKeI/DEG
-i7LcrMgrBk+xnuAWoFHuzfBMAdD9i3kYyk+41tOmcza2TNJgxadVYp5woHFvYvS/
-GKaNiRz0XmcijO5Ir0yxgCq21BdkWzo5zVrTFABiKeR7YXiee8kCggEBAOeULWgR
-spolJJrACWJspRvKb9FGnbGiYOnCGJoAc751kuXmNxoyWnEwgcjrSEoayNPUfOtz
-IgA+twqjgl0Zec2XFPfUcgWUBrrvvUEV4NIH5ibaR7ezHGeovCWs9XoDyzHHvhDr
-c6T5kXFZ60rS5h6LGUnE1hkHFJoHuTIBbn9j7eIbri8S71i7HWQ04s4KuQ+Bwbxm
-UnkEhbc+zMWHXfXy7rx4/eEZcZwtEybIORcHXYNPGeqMfOlcEMHpKEOi+NvDA6cp
-vTaTSwJ6ZBgYh7Tw3bNgRxSknaIhcGwMD0ojStjC5xzXT1Zr2Z3GXwYvOGcq3MeZ
-z+V2cx5xuwyp7R0CggEBAM0cKKNZEZwi/1zBPUDMFB4iJoX12BxQX6e5wdlHGXgF
-XeZwCnaIxOxMDxH79M5Svmpdu/jkUijI/pRvcE1iohFyIBvTUSDmlAoy4keXqMEQ
-M2hA+TwVA3JLmMcV8HKy/MFlwwKJB1JDcoxGjnXsM5UjVTD2jilO7vlJZs3+0ws0
-R7qzRT3ED25QTpZyDYcKE2otc5bzIZG3yAaJtWd3NugWsKpxDgr2RFUGJiHBq72n
-48FkSjfgaDTn83zYcPvS0Uykb2ho8G/N+EurstL41n3nQo0I7FLbyptOopDDwsSp
-Ndejn08NVAQ+xFAafOyqHkA3Ytpl0QCZDpMBuLdvw+MCggEAOVMt1kgjPRMat4/4
-ArxANtvqyBRB7vnyIYthiaW5ARmbrntJgpuaVdCbIABWGbn9oqpD7gjHDuZ3axPE
-roUi6KiQkTSusQDOlbHI2Haw+2znJRD9ldSpoGNdh7oD3htYTk9Sll+ideEthrCq
-lRAV1NO8A83M7c8Z43Mr/dvq3XAAL+uIN7DpPL687NRGnJh87QDC039ExR5Ad3b9
-O5xhvwNO46rTtcgVnoJt7ji8IR46oMmQ8cWrGh0nLMkppWyPS98/ZT7ozryxYcCo
-TGquFTVWvBOGJO8G8l5ytNxbYI/R9Exy52nJAuyZpvu3BBHmVWt/0Y0asIOcxZmD
-owPhZQKCAQAfWAFBzReq05JQe1s/7q/YVwGqEQKgeQvVFsbvzDSxKajK0S5YJNhq
-/8iByA4GBZEBsidKhqGjh+uXhVwVB1Ca9+S+O9G3BGV1FYeMxzlLn40rjlpH+zIW
-okTLj6e5724+o61kUspioNn9Y77beGf9j3OyUsswttZAFB54tktL+AZKGqEnKjHt
-eqo3xWAZ1clXvXBfjfIAUaRok1y8XfRvDSCcO0CZHj8c+x6SpAT5q5FbeVb6KPnj
-s9p6ppzFbtb7Llm0C+1KOKCL98YRBWPJw7Bg2w86LkpM53xiQPgfk3gd5uwuaWwA
-ZhMb5qBWjjynNY+OrmZ8/+bBQk8XASZfAoIBAFkHOnZOD1JJQ0QvaJ9tuCgHi216
-I8QPMMTdm3ZEDHSYMNwl7ayeseBcmB2zaqBKYz75qcU0SK4lnZkR2wIpbsHZNSVM
-J0WpN6r9G4JdnVi11J04RsfSMjCUr/PTVMmPvw8xPHrCxkJmB+d56olSE80I1Jrx
-djCv1LtSsT10W7FIcY82/cOi4xxGLOA70lDCf+szofQgVP8WvuOA1YaFw98ca8zc
-A401CyNexk24/c3d6C19YW/MppdE0uGMxL/oHsPgwkZAf6LmvF/UF71PsBUEniLc
-YFaJl3wn1cPfBBo9L4sZzyP2qokL8YHdg+wW7b4IOsYwbeqceBvqPtcUUPs=
------END RSA PRIVATE KEY-----
diff --git a/apex/extservices/com.android.extservices.pk8 b/apex/extservices/com.android.extservices.pk8
deleted file mode 100644
index 59585a212592..000000000000
--- a/apex/extservices/com.android.extservices.pk8
+++ /dev/null
Binary files differ
diff --git a/apex/extservices/com.android.extservices.x509.pem b/apex/extservices/com.android.extservices.x509.pem
deleted file mode 100644
index e0343b81d279..000000000000
--- a/apex/extservices/com.android.extservices.x509.pem
+++ /dev/null
@@ -1,36 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIGLTCCBBWgAwIBAgIUdqdMmx/5OsCP3Ew3/hcr7+1ACHEwDQYJKoZIhvcNAQEL
-BQAwgaQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
-DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
-b2lkMSAwHgYDVQQDDBdjb20uYW5kcm9pZC5leHRzZXJ2aWNlczEiMCAGCSqGSIb3
-DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAgFw0yMDAxMTcxMDIxMzZaGA80NzU3
-MTIxMzEwMjEzNlowgaQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
-MRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYD
-VQQLDAdBbmRyb2lkMSAwHgYDVQQDDBdjb20uYW5kcm9pZC5leHRzZXJ2aWNlczEi
-MCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCAiIwDQYJKoZIhvcN
-AQEBBQADggIPADCCAgoCggIBANKaSeLGaFRRt779vAtTfG3t2aQZrWOByUYc7yUN
-RdmJqWxU47OL5urYmanWPbz2f972Q9oi8x+8y4ny9SEY3wg0pUbzvKNTXpkxWyG1
-HE2C2zTfzuDDLpDIf2usWynt1wLVhpYC3k+7Yv2vOIK5dKkezh6PfdKmsbDae5DE
-d22tTSYZ5KwNpIWrgQle26cRG5sqhAFdkpgGMF00Huz06cjUoTjs2sNSlXTRBOTP
-CCy8UoRjBivQZkwHbddfsn+Z22ARPG8JDg/n4mEi8C0T6bJeQeirSPkBCkD6Djgq
-7RddJ2eLYZII8l8r6A6x+6cnTkXHaV5g3LUwPvi8XEn9IUuT9WJNRje/vfYLycTQ
-kP415CZMxDvsi1Ul4YsbL3enE89ryGMTpVZPogch/36DG5Sye28yISItNUy3urJa
-OXbg7mh+MwPd4bQaW4CJk+AUweKaF4aV0SZFT+nCewL4xLdGdy889KazlW98NqtK
-hOSxIg1jHkZq48ajuq2A+ns1yDKt1l0f9IYCz3mz/IXInokbkjPvHahJTJ+OMHXO
-THD8e5gBzcK841jJk+H3EsIYOHsp66uy2IgEHN+9pAS6vI0xfrXOYuKzuSL3oxcV
-FlVTimt4xokMMerdcW4KD+MC5NFEip4DUS4JKCyG0wRI3ffEs9Zcpxi3QSibrjLW
-rz+hAgMBAAGjUzBRMB0GA1UdDgQWBBTP2AhZzEUUgtAFlkaMaq+RvY06fDAfBgNV
-HSMEGDAWgBTP2AhZzEUUgtAFlkaMaq+RvY06fDAPBgNVHRMBAf8EBTADAQH/MA0G
-CSqGSIb3DQEBCwUAA4ICAQCbwtfo37j62Sudmt32PCfRN/r5ZNDNNA2JhR8uDUmX
-xXfF5YfDvSKsNLiQKcDagu6a+0C+QnzXHXCBlXZFrTJ8NAVMlmqdHGwoFoYMfJZH
-R1lCTidyFMoMLJ8GRGPJjzDkKnOeAqKMCtKvXoH2r12+JB2/ov4ooLREu/wPkEXT
-OymkyWNP5XLQTKWqfEQyXXFpuwZ+m35Wkr0Fm92mZeJpVeIZPK7M7aK3zyoj7XJP
-YLMsR/AQs8OULdpfNMddAuN3ndlYu03LZlsF6LG5bduaDDcESJ5hdJrgBa/NBKRU
-IbS+q/6WAjYKMNRT/fPGew4wUzlWKi1Ihdk79oaqKKijE1b2JSJD1/SEYiBf+JPE
-bXobUrMbBwFpdhT+YLMF9FsuPQKsUIONaWiO4QcQoY/rQwGxPP6fV8ZbBrUWJewj
-MpSdU9foZNa/TmOAgfS/JxH+nXnG4+H1m8mdNBsxvsYmF2ZuGb/jdEeA2cuHIJDZ
-FJeWwCFxzlCGZJaUsxsnZByADBuufUVaO/9gGs0YQC/JP1i9hK4DyZdKwZpXdLi2
-Nw27Qma4WEIZnMb6Rgk1nTV+7ALcOSIhGgFOOeDTuCGfnEcz2coai5fbD/K6Q7Xu
-IRNyxHQjheZPdei2x912Ex/KqKGfaFaZJxrvCSKdhzxcTFIsO4JuZs+SDpRTKcI7
-Cw==
------END CERTIFICATE-----
diff --git a/apex/extservices/testing/Android.bp b/apex/extservices/testing/Android.bp
deleted file mode 100644
index 88a47246c824..000000000000
--- a/apex/extservices/testing/Android.bp
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-apex_test {
- name: "test_com.android.extservices",
- visibility: [
- "//system/apex/tests",
- ],
- defaults: ["com.android.extservices-defaults"],
- manifest: "test_manifest.json",
- file_contexts: ":com.android.extservices-file_contexts",
- // Test APEX, should never be installed
- installable: false,
-}
diff --git a/apex/extservices/testing/test_manifest.json b/apex/extservices/testing/test_manifest.json
deleted file mode 100644
index 23a50e37bdd3..000000000000
--- a/apex/extservices/testing/test_manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.extservices",
- "version": 2147483647
-}
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index c8a04d674739..ba2a8a34a92b 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -268,6 +268,7 @@ public class AlarmManagerService extends SystemService {
*/
Bundle mIdleOptions;
+ // TODO(b/172085676): Move inside alarm store.
private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
new SparseArray<>();
private final SparseArray<AlarmManager.AlarmClockInfo> mTmpSparseAlarmClockArray =
@@ -276,6 +277,9 @@ public class AlarmManagerService extends SystemService {
new SparseBooleanArray();
private boolean mNextAlarmClockMayChange;
+ @GuardedBy("mLock")
+ private final Runnable mAlarmClockUpdater = () -> mNextAlarmClockMayChange = true;
+
// May only use on mHandler's thread, locking not required.
private final SparseArray<AlarmManager.AlarmClockInfo> mHandlerSparseAlarmClockArray =
new SparseArray<>();
@@ -410,6 +414,9 @@ public class AlarmManagerService extends SystemService {
private static final String KEY_APP_STANDBY_RESTRICTED_WINDOW =
"app_standby_restricted_window";
+ @VisibleForTesting
+ static final String KEY_LAZY_BATCHING = "lazy_batching";
+
private static final long DEFAULT_MIN_FUTURITY = 5 * 1000;
private static final long DEFAULT_MIN_INTERVAL = 60 * 1000;
private static final long DEFAULT_MAX_INTERVAL = 365 * DateUtils.DAY_IN_MILLIS;
@@ -432,6 +439,8 @@ public class AlarmManagerService extends SystemService {
private static final int DEFAULT_APP_STANDBY_RESTRICTED_QUOTA = 1;
private static final long DEFAULT_APP_STANDBY_RESTRICTED_WINDOW = MILLIS_IN_DAY;
+ private static final boolean DEFAULT_LAZY_BATCHING = false;
+
// Minimum futurity of a new alarm
public long MIN_FUTURITY = DEFAULT_MIN_FUTURITY;
@@ -460,6 +469,8 @@ public class AlarmManagerService extends SystemService {
public int APP_STANDBY_RESTRICTED_QUOTA = DEFAULT_APP_STANDBY_RESTRICTED_QUOTA;
public long APP_STANDBY_RESTRICTED_WINDOW = DEFAULT_APP_STANDBY_RESTRICTED_WINDOW;
+ public boolean LAZY_BATCHING = DEFAULT_LAZY_BATCHING;
+
private long mLastAllowWhileIdleWhitelistDuration = -1;
Constants() {
@@ -538,6 +549,14 @@ public class AlarmManagerService extends SystemService {
case KEY_APP_STANDBY_RESTRICTED_WINDOW:
updateStandbyWindowsLocked();
break;
+ case KEY_LAZY_BATCHING:
+ final boolean oldLazyBatching = LAZY_BATCHING;
+ LAZY_BATCHING = properties.getBoolean(
+ KEY_LAZY_BATCHING, DEFAULT_LAZY_BATCHING);
+ if (oldLazyBatching != LAZY_BATCHING) {
+ migrateAlarmsToNewStoreLocked();
+ }
+ break;
default:
if (name.startsWith(KEY_PREFIX_STANDBY_QUOTA) && !standbyQuotaUpdated) {
// The quotas need to be updated in order, so we can't just rely
@@ -551,6 +570,15 @@ public class AlarmManagerService extends SystemService {
}
}
+ private void migrateAlarmsToNewStoreLocked() {
+ final AlarmStore newStore = LAZY_BATCHING ? new LazyAlarmStore()
+ : new BatchingAlarmStore();
+ final ArrayList<Alarm> allAlarms = mAlarmStore.remove((unused) -> true);
+ newStore.addAll(allAlarms);
+ mAlarmStore = newStore;
+ mAlarmStore.setAlarmClockRemovalListener(mAlarmClockUpdater);
+ }
+
private void updateStandbyQuotasLocked() {
// The bucket quotas need to be read as an atomic unit but the properties passed to
// onPropertiesChanged may only have one key populated at a time.
@@ -659,6 +687,9 @@ public class AlarmManagerService extends SystemService {
TimeUtils.formatDuration(APP_STANDBY_RESTRICTED_WINDOW, pw);
pw.println();
+ pw.print(KEY_LAZY_BATCHING, LAZY_BATCHING);
+ pw.println();
+
pw.decreaseIndent();
}
@@ -770,7 +801,7 @@ public class AlarmManagerService extends SystemService {
// minimum recurrence period or alarm futurity for us to be able to fuzz it
static final long MIN_FUZZABLE_INTERVAL = 10000;
@GuardedBy("mLock")
- final AlarmStore mAlarmStore;
+ AlarmStore mAlarmStore;
// set to non-null if in idle mode; while in this mode, any alarms we don't want
// to run during this time are rescehduled to go off after this alarm.
@@ -781,7 +812,6 @@ public class AlarmManagerService extends SystemService {
AlarmManagerService(Context context, Injector injector) {
super(context);
mInjector = injector;
- mAlarmStore = new BatchingAlarmStore(() -> mNextAlarmClockMayChange = true);
}
public AlarmManagerService(Context context) {
@@ -1219,6 +1249,11 @@ public class AlarmManagerService extends SystemService {
synchronized (mLock) {
mHandler = new AlarmHandler();
mConstants = new Constants();
+
+ mAlarmStore = mConstants.LAZY_BATCHING ? new LazyAlarmStore()
+ : new BatchingAlarmStore();
+ mAlarmStore.setAlarmClockRemovalListener(mAlarmClockUpdater);
+
mAppWakeupHistory = new AppWakeupHistory(Constants.DEFAULT_APP_STANDBY_WINDOW);
mNextWakeup = mNextNonWakeup = 0;
@@ -3055,12 +3090,13 @@ public class AlarmManagerService extends SystemService {
static final void dumpAlarmList(IndentingPrintWriter ipw, ArrayList<Alarm> list,
long nowELAPSED, SimpleDateFormat sdf) {
- for (int i = list.size() - 1; i >= 0; i--) {
+ final int n = list.size();
+ for (int i = n - 1; i >= 0; i--) {
final Alarm a = list.get(i);
final String label = Alarm.typeToString(a.type);
ipw.print(label);
ipw.print(" #");
- ipw.print(i);
+ ipw.print(n - i);
ipw.print(": ");
ipw.println(a);
ipw.increaseIndent();
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmStore.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmStore.java
index 7a846b9b82db..0e442d09d5a5 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmStore.java
@@ -40,6 +40,13 @@ public interface AlarmStore {
void add(Alarm a);
/**
+ * Adds all the given alarms to this store.
+ *
+ * @param alarms The alarms to add.
+ */
+ void addAll(ArrayList<Alarm> alarms);
+
+ /**
* Removes alarms that pass the given predicate.
*
* @param whichAlarms The predicate describing the alarms to remove.
@@ -48,11 +55,17 @@ public interface AlarmStore {
ArrayList<Alarm> remove(Predicate<Alarm> whichAlarms);
/**
+ * Set a listener to be invoked whenever an alarm clock is removed by a call to
+ * {@link #remove(Predicate) remove} from this store.
+ */
+ void setAlarmClockRemovalListener(Runnable listener);
+
+ /**
* Gets the earliest alarm with the flag {@link android.app.AlarmManager#FLAG_WAKE_FROM_IDLE}
* based on {@link Alarm#getWhenElapsed()}.
*
* @return An alarm object matching the description above or {@code null} if no such alarm was
- * found.
+ * found.
*/
Alarm getNextWakeFromIdleAlarm();
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java b/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java
index cbfe80bdce24..e7edfb7b56b9 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/BatchingAlarmStore.java
@@ -41,45 +41,22 @@ import java.util.function.Predicate;
*/
public class BatchingAlarmStore implements AlarmStore {
- private ArrayList<Batch> mAlarmBatches = new ArrayList<>();
+ private final ArrayList<Batch> mAlarmBatches = new ArrayList<>();
private int mSize;
- private AlarmClockRemovalListener mAlarmClockRemovalListener;
+ private Runnable mOnAlarmClockRemoved;
interface Stats {
int REBATCH_ALL_ALARMS = 0;
}
- final StatLogger mStatLogger = new StatLogger("Alarm store stats", new String[]{
+ final StatLogger mStatLogger = new StatLogger("BatchingAlarmStore stats", new String[]{
"REBATCH_ALL_ALARMS",
});
- private static final Comparator<Batch> sBatchOrder = (b1, b2) -> {
- long when1 = b1.mStart;
- long when2 = b2.mStart;
- if (when1 > when2) {
- return 1;
- }
- if (when1 < when2) {
- return -1;
- }
- return 0;
- };
+ private static final Comparator<Batch> sBatchOrder = Comparator.comparingLong(b -> b.mStart);
- private static final Comparator<Alarm> sIncreasingTimeOrder = (a1, a2) -> {
- long when1 = a1.getWhenElapsed();
- long when2 = a2.getWhenElapsed();
- if (when1 > when2) {
- return 1;
- }
- if (when1 < when2) {
- return -1;
- }
- return 0;
- };
-
- BatchingAlarmStore(AlarmClockRemovalListener listener) {
- mAlarmClockRemovalListener = listener;
- }
+ private static final Comparator<Alarm> sIncreasingTimeOrder = Comparator.comparingLong(
+ Alarm::getWhenElapsed);
@Override
public void add(Alarm a) {
@@ -88,6 +65,16 @@ public class BatchingAlarmStore implements AlarmStore {
}
@Override
+ public void addAll(ArrayList<Alarm> alarms) {
+ if (alarms == null) {
+ return;
+ }
+ for (final Alarm a : alarms) {
+ add(a);
+ }
+ }
+
+ @Override
public ArrayList<Alarm> remove(Predicate<Alarm> whichAlarms) {
final ArrayList<Alarm> removed = new ArrayList<>();
for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
@@ -106,6 +93,11 @@ public class BatchingAlarmStore implements AlarmStore {
}
@Override
+ public void setAlarmClockRemovalListener(Runnable listener) {
+ mOnAlarmClockRemoved = listener;
+ }
+
+ @Override
public Alarm getNextWakeFromIdleAlarm() {
for (final Batch batch : mAlarmBatches) {
if ((batch.mFlags & AlarmManager.FLAG_WAKE_FROM_IDLE) == 0) {
@@ -317,8 +309,8 @@ public class BatchingAlarmStore implements AlarmStore {
Alarm alarm = mAlarms.get(i);
if (predicate.test(alarm)) {
removed.add(mAlarms.remove(i));
- if (alarm.alarmClock != null && mAlarmClockRemovalListener != null) {
- mAlarmClockRemovalListener.onRemoved();
+ if (alarm.alarmClock != null && mOnAlarmClockRemoved != null) {
+ mOnAlarmClockRemoved.run();
}
if (isTimeTickAlarm(alarm)) {
// This code path is not invoked when delivering alarms, only when removing
@@ -388,9 +380,4 @@ public class BatchingAlarmStore implements AlarmStore {
proto.end(token);
}
}
-
- @FunctionalInterface
- interface AlarmClockRemovalListener {
- void onRemoved();
- }
}
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/LazyAlarmStore.java b/apex/jobscheduler/service/java/com/android/server/alarm/LazyAlarmStore.java
new file mode 100644
index 000000000000..8ca14463a3b5
--- /dev/null
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/LazyAlarmStore.java
@@ -0,0 +1,217 @@
+/*
+ * 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.alarm;
+
+import static com.android.server.alarm.AlarmManagerService.TAG;
+import static com.android.server.alarm.AlarmManagerService.dumpAlarmList;
+import static com.android.server.alarm.AlarmManagerService.isTimeTickAlarm;
+
+import android.app.AlarmManager;
+import android.util.IndentingPrintWriter;
+import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.internal.util.StatLogger;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.function.Predicate;
+
+/**
+ * Lazy implementation of an alarm store.
+ * This keeps the alarms in a sorted list, and only batches them at the time of delivery.
+ */
+public class LazyAlarmStore implements AlarmStore {
+
+ private final ArrayList<Alarm> mAlarms = new ArrayList<>();
+ private Runnable mOnAlarmClockRemoved;
+
+ interface Stats {
+ int GET_NEXT_DELIVERY_TIME = 0;
+ int GET_NEXT_WAKEUP_DELIVERY_TIME = 1;
+ }
+
+ final StatLogger mStatLogger = new StatLogger("LazyAlarmStore stats", new String[]{
+ "GET_NEXT_DELIVERY_TIME",
+ "GET_NEXT_WAKEUP_DELIVERY_TIME",
+ });
+
+ // Decreasing time order because it is more efficient to remove from the tail of an array list.
+ private static final Comparator<Alarm> sDecreasingTimeOrder = Comparator.comparingLong(
+ Alarm::getWhenElapsed).reversed();
+
+ @Override
+ public void add(Alarm a) {
+ int index = Collections.binarySearch(mAlarms, a, sDecreasingTimeOrder);
+ if (index < 0) {
+ index = 0 - index - 1;
+ }
+ mAlarms.add(index, a);
+ }
+
+ @Override
+ public void addAll(ArrayList<Alarm> alarms) {
+ if (alarms == null) {
+ return;
+ }
+ mAlarms.addAll(alarms);
+ Collections.sort(alarms, sDecreasingTimeOrder);
+ }
+
+ @Override
+ public ArrayList<Alarm> remove(Predicate<Alarm> whichAlarms) {
+ final ArrayList<Alarm> removedAlarms = new ArrayList<>();
+ for (int i = mAlarms.size() - 1; i >= 0; i--) {
+ if (whichAlarms.test(mAlarms.get(i))) {
+ final Alarm removed = mAlarms.remove(i);
+ if (removed.alarmClock != null && mOnAlarmClockRemoved != null) {
+ mOnAlarmClockRemoved.run();
+ }
+ if (isTimeTickAlarm(removed)) {
+ // This code path is not invoked when delivering alarms, only when removing
+ // alarms due to the caller cancelling it or getting uninstalled, etc.
+ Slog.wtf(TAG, "Removed TIME_TICK alarm");
+ }
+ removedAlarms.add(removed);
+ }
+ }
+ return removedAlarms;
+ }
+
+ @Override
+ public void setAlarmClockRemovalListener(Runnable listener) {
+ mOnAlarmClockRemoved = listener;
+ }
+
+ @Override
+ public Alarm getNextWakeFromIdleAlarm() {
+ for (int i = mAlarms.size() - 1; i >= 0; i--) {
+ final Alarm alarm = mAlarms.get(i);
+ if ((alarm.flags & AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
+ return alarm;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public int size() {
+ return mAlarms.size();
+ }
+
+ @Override
+ public long getNextWakeupDeliveryTime() {
+ final long start = mStatLogger.getTime();
+ long nextWakeup = 0;
+ for (int i = mAlarms.size() - 1; i >= 0; i--) {
+ final Alarm a = mAlarms.get(i);
+ if (!a.wakeup) {
+ continue;
+ }
+ if (nextWakeup == 0) {
+ nextWakeup = a.getMaxWhenElapsed();
+ } else {
+ if (a.getWhenElapsed() > nextWakeup) {
+ break;
+ }
+ nextWakeup = Math.min(nextWakeup, a.getMaxWhenElapsed());
+ }
+ }
+ mStatLogger.logDurationStat(Stats.GET_NEXT_WAKEUP_DELIVERY_TIME, start);
+ return nextWakeup;
+ }
+
+ @Override
+ public long getNextDeliveryTime() {
+ final long start = mStatLogger.getTime();
+ final int n = mAlarms.size();
+ if (n == 0) {
+ return 0;
+ }
+ long nextDelivery = mAlarms.get(n - 1).getMaxWhenElapsed();
+ for (int i = n - 2; i >= 0; i--) {
+ final Alarm a = mAlarms.get(i);
+ if (a.getWhenElapsed() > nextDelivery) {
+ break;
+ }
+ nextDelivery = Math.min(nextDelivery, a.getMaxWhenElapsed());
+ }
+ mStatLogger.logDurationStat(Stats.GET_NEXT_DELIVERY_TIME, start);
+ return nextDelivery;
+ }
+
+ @Override
+ public ArrayList<Alarm> removePendingAlarms(long nowElapsed) {
+ final ArrayList<Alarm> pending = new ArrayList<>();
+ final ArrayList<Alarm> standAlones = new ArrayList<>();
+
+ for (int i = mAlarms.size() - 1; i >= 0; i--) {
+ final Alarm alarm = mAlarms.get(i);
+ if (alarm.getWhenElapsed() > nowElapsed) {
+ break;
+ }
+ pending.add(alarm);
+ if ((alarm.flags & AlarmManager.FLAG_STANDALONE) != 0) {
+ standAlones.add(alarm);
+ }
+ }
+ if (!standAlones.isEmpty()) {
+ // If there are deliverable standalone alarms, others must not go out yet.
+ mAlarms.removeAll(standAlones);
+ return standAlones;
+ }
+ mAlarms.removeAll(pending);
+ return pending;
+ }
+
+ @Override
+ public boolean updateAlarmDeliveries(AlarmDeliveryCalculator deliveryCalculator) {
+ boolean changed = false;
+ for (final Alarm alarm : mAlarms) {
+ changed |= deliveryCalculator.updateAlarmDelivery(alarm);
+ }
+ if (changed) {
+ Collections.sort(mAlarms, sDecreasingTimeOrder);
+ }
+ return changed;
+ }
+
+ @Override
+ public ArrayList<Alarm> asList() {
+ final ArrayList<Alarm> copy = new ArrayList<>(mAlarms);
+ Collections.reverse(copy);
+ return copy;
+ }
+
+ @Override
+ public void dump(IndentingPrintWriter ipw, long nowElapsed, SimpleDateFormat sdf) {
+ ipw.println(mAlarms.size() + " pending alarms: ");
+ ipw.increaseIndent();
+ dumpAlarmList(ipw, mAlarms, nowElapsed, sdf);
+ ipw.decreaseIndent();
+ mStatLogger.dump(ipw);
+ }
+
+ @Override
+ public void dumpProto(ProtoOutputStream pos, long nowElapsed) {
+ for (final Alarm a : mAlarms) {
+ a.dumpDebug(pos, AlarmManagerServiceDumpProto.PENDING_ALARMS, nowElapsed);
+ }
+ }
+}
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 b5e72247a4a3..fbda86f9ce22 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -54,6 +54,7 @@ import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -194,40 +195,38 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
int numRecords = 0;
// Add in all the apps for every user/profile.
for (UserHandle userHandle : users) {
- List<PackageInfo> pi =
- pm.getInstalledPackagesAsUser(PackageManager.MATCH_UNINSTALLED_PACKAGES
- | PackageManager.MATCH_ANY_USER
- | PackageManager.MATCH_APEX,
- userHandle.getIdentifier());
- for (int j = 0; j < pi.size(); j++) {
- if (pi.get(j).applicationInfo != null) {
+ List<PackageInfo> packagesPlusApex = getAllPackagesWithApex(pm, userHandle);
+ for (int j = 0; j < packagesPlusApex.size(); j++) {
+ if (packagesPlusApex.get(j).applicationInfo != null) {
String installer;
try {
- installer = pm.getInstallerPackageName(pi.get(j).packageName);
+ installer = pm.getInstallerPackageName(
+ packagesPlusApex.get(j).packageName);
} catch (IllegalArgumentException e) {
installer = "";
}
long applicationInfoToken =
output.start(ProtoOutputStream.FIELD_TYPE_MESSAGE
| ProtoOutputStream.FIELD_COUNT_REPEATED
- | APPLICATION_INFO_FIELD_ID);
+ | APPLICATION_INFO_FIELD_ID);
output.write(ProtoOutputStream.FIELD_TYPE_INT32
- | ProtoOutputStream.FIELD_COUNT_SINGLE | UID_FIELD_ID,
- pi.get(j).applicationInfo.uid);
+ | ProtoOutputStream.FIELD_COUNT_SINGLE | UID_FIELD_ID,
+ packagesPlusApex.get(j).applicationInfo.uid);
output.write(ProtoOutputStream.FIELD_TYPE_INT64
- | ProtoOutputStream.FIELD_COUNT_SINGLE
- | VERSION_FIELD_ID, pi.get(j).getLongVersionCode());
+ | ProtoOutputStream.FIELD_COUNT_SINGLE
+ | VERSION_FIELD_ID,
+ packagesPlusApex.get(j).getLongVersionCode());
output.write(ProtoOutputStream.FIELD_TYPE_STRING
- | ProtoOutputStream.FIELD_COUNT_SINGLE
- | VERSION_STRING_FIELD_ID,
- pi.get(j).versionName);
+ | ProtoOutputStream.FIELD_COUNT_SINGLE
+ | VERSION_STRING_FIELD_ID,
+ packagesPlusApex.get(j).versionName);
output.write(ProtoOutputStream.FIELD_TYPE_STRING
| ProtoOutputStream.FIELD_COUNT_SINGLE
- | PACKAGE_NAME_FIELD_ID, pi.get(j).packageName);
+ | PACKAGE_NAME_FIELD_ID, packagesPlusApex.get(j).packageName);
output.write(ProtoOutputStream.FIELD_TYPE_STRING
- | ProtoOutputStream.FIELD_COUNT_SINGLE
+ | ProtoOutputStream.FIELD_COUNT_SINGLE
| INSTALLER_FIELD_ID,
- installer == null ? "" : installer);
+ installer == null ? "" : installer);
numRecords++;
output.end(applicationInfoToken);
}
@@ -245,6 +244,26 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
});
}
+ private static List<PackageInfo> getAllPackagesWithApex(PackageManager pm,
+ UserHandle userHandle) {
+ // We want all the uninstalled packages because uninstalled package uids can still be logged
+ // to statsd.
+ List<PackageInfo> allPackages = new ArrayList<>(
+ pm.getInstalledPackagesAsUser(PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_ANY_USER,
+ userHandle.getIdentifier()));
+ // We make a second query to package manager for the apex modules because package manager
+ // returns both installed and uninstalled apexes with
+ // PackageManager.MATCH_UNINSTALLED_PACKAGES flag. We only want active apexes because
+ // inactive apexes can conflict with active ones.
+ for (PackageInfo packageInfo : pm.getInstalledPackages(PackageManager.MATCH_APEX)) {
+ if (packageInfo.isApex) {
+ allPackages.add(packageInfo);
+ }
+ }
+ return allPackages;
+ }
+
private static class WakelockThread extends Thread {
private final PowerManager.WakeLock mWl;
private final Runnable mRunnable;
diff --git a/api/Android.bp b/api/Android.bp
index 21a7166d1354..28b75944072f 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -16,25 +16,6 @@ package {
default_visibility: ["//visibility:private"],
}
-// *-current.txt files for use by modules in other directories like cts
-filegroup {
- name: "frameworks-base-api-current.txt",
- srcs: ["current.txt"],
- visibility: ["//visibility:public"],
-}
-
-filegroup {
- name: "frameworks-base-api-system-current.txt",
- srcs: ["system-current.txt"],
- visibility: ["//visibility:public"],
-}
-
-filegroup {
- name: "frameworks-base-api-system-removed.txt",
- srcs: ["system-removed.txt"],
- visibility: ["//visibility:public"],
-}
-
genrule {
name: "current-api-xml",
tools: ["metalava"],
@@ -45,7 +26,7 @@ genrule {
}
genrule {
- name: "frameworks-base-api-current-merged.txt",
+ name: "frameworks-base-api-current.txt",
srcs: [
":conscrypt.module.public.api{.public.api.txt}",
":framework-appsearch{.public.api.txt}",
@@ -74,10 +55,11 @@ genrule {
dest: "android.txt",
},
],
+ visibility: ["//visibility:public"],
}
genrule {
- name: "frameworks-base-api-removed-merged.txt",
+ name: "frameworks-base-api-removed.txt",
srcs: [
":conscrypt.module.public.api{.public.removed-api.txt}",
":framework-appsearch{.public.removed-api.txt}",
@@ -104,7 +86,7 @@ genrule {
}
genrule {
- name: "frameworks-base-api-system-current-merged.txt",
+ name: "frameworks-base-api-system-current.txt",
srcs: [
":framework-appsearch{.system.api.txt}",
":framework-graphics{.system.api.txt}",
@@ -132,10 +114,11 @@ genrule {
dest: "android.txt",
},
],
+ visibility: ["//visibility:public"],
}
genrule {
- name: "frameworks-base-api-system-removed-merged.txt",
+ name: "frameworks-base-api-system-removed.txt",
srcs: [
":framework-appsearch{.system.removed-api.txt}",
":framework-graphics{.system.removed-api.txt}",
@@ -158,10 +141,11 @@ genrule {
dest: "system-removed.txt",
},
],
+ visibility: ["//visibility:public"],
}
genrule {
- name: "frameworks-base-api-module-lib-current-merged.txt",
+ name: "frameworks-base-api-module-lib-current.txt",
srcs: [
":framework-appsearch{.module-lib.api.txt}",
":framework-graphics{.module-lib.api.txt}",
@@ -192,7 +176,7 @@ genrule {
}
genrule {
- name: "frameworks-base-api-module-lib-removed-merged.txt",
+ name: "frameworks-base-api-module-lib-removed.txt",
srcs: [
":framework-appsearch{.module-lib.removed-api.txt}",
":framework-graphics{.module-lib.removed-api.txt}",
@@ -220,8 +204,8 @@ genrule {
genrule {
name: "combined-removed-dex",
srcs: [
- ":frameworks-base-api-removed-merged.txt",
- ":frameworks-base-api-system-removed-merged.txt",
+ ":frameworks-base-api-removed.txt",
+ ":frameworks-base-api-system-removed.txt",
":android.car-stubs-docs{.removed-api.txt}",
":android.car-system-stubs-docs{.removed-api.txt}",
],
diff --git a/api/current.txt b/api/current.txt
index 9ff7cc255bf4..524f9a0da49e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5528,6 +5528,7 @@ package android.app {
field @Deprecated public static final String EXTRA_PEOPLE = "android.people";
field public static final String EXTRA_PEOPLE_LIST = "android.people.list";
field public static final String EXTRA_PICTURE = "android.picture";
+ field public static final String EXTRA_PICTURE_CONTENT_DESCRIPTION = "android.pictureContentDescription";
field public static final String EXTRA_PROGRESS = "android.progress";
field public static final String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
field public static final String EXTRA_PROGRESS_MAX = "android.progressMax";
@@ -5673,6 +5674,7 @@ package android.app {
method public android.app.Notification.BigPictureStyle bigLargeIcon(android.graphics.Bitmap);
method public android.app.Notification.BigPictureStyle bigLargeIcon(android.graphics.drawable.Icon);
method public android.app.Notification.BigPictureStyle bigPicture(android.graphics.Bitmap);
+ method @NonNull public android.app.Notification.BigPictureStyle bigPictureContentDescription(@Nullable CharSequence);
method public android.app.Notification.BigPictureStyle setBigContentTitle(CharSequence);
method public android.app.Notification.BigPictureStyle setSummaryText(CharSequence);
}
@@ -6138,6 +6140,7 @@ package android.app {
method public android.content.IntentSender getIntentSender();
method public static android.app.PendingIntent getService(android.content.Context, int, @NonNull android.content.Intent, int);
method @Deprecated public String getTargetPackage();
+ method public boolean isImmutable();
method @Nullable public static android.app.PendingIntent readPendingIntentOrNullFromParcel(@NonNull android.os.Parcel);
method public void send() throws android.app.PendingIntent.CanceledException;
method public void send(int) throws android.app.PendingIntent.CanceledException;
@@ -11718,10 +11721,9 @@ package android.content.pm {
method public long getFirstInstallTime();
method public android.graphics.drawable.Drawable getIcon(int);
method public CharSequence getLabel();
+ method public float getLoadingProgress();
method public String getName();
- method public float getProgress();
method public android.os.UserHandle getUser();
- method public boolean isLoading();
method public boolean isStartable();
}
@@ -11762,7 +11764,7 @@ package android.content.pm {
ctor public LauncherApps.Callback();
method public abstract void onPackageAdded(String, android.os.UserHandle);
method public abstract void onPackageChanged(String, android.os.UserHandle);
- method public void onPackageProgressChanged(@NonNull String, @NonNull android.os.UserHandle, float);
+ method public void onPackageLoadingProgressChanged(@NonNull String, @NonNull android.os.UserHandle, float);
method public abstract void onPackageRemoved(String, android.os.UserHandle);
method public abstract void onPackagesAvailable(String[], android.os.UserHandle, boolean);
method public void onPackagesSuspended(String[], android.os.UserHandle);
@@ -16428,6 +16430,7 @@ package android.graphics.fonts {
method public void getMetrics(@NonNull android.graphics.Paint, @Nullable android.graphics.Paint.FontMetrics);
method @NonNull public android.graphics.fonts.FontStyle getStyle();
method @IntRange(from=0) public int getTtcIndex();
+ method public boolean isSameSource(@NonNull android.graphics.fonts.Font);
}
public static final class Font.Builder {
@@ -31862,6 +31865,15 @@ package android.net.wifi.aware {
method public void onAttached(android.net.wifi.aware.WifiAwareSession);
}
+ public final class AwareResources implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getNumOfAvailableDataPaths();
+ method public int getNumOfAvailablePublishSessions();
+ method public int getNumOfAvailableSubscribeSessions();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.AwareResources> CREATOR;
+ }
+
public final class Characteristics implements android.os.Parcelable {
method public int describeContents();
method public int getMaxMatchFilterLength();
@@ -31964,7 +31976,8 @@ package android.net.wifi.aware {
public class WifiAwareManager {
method public void attach(@NonNull android.net.wifi.aware.AttachCallback, @Nullable android.os.Handler);
method public void attach(@NonNull android.net.wifi.aware.AttachCallback, @NonNull android.net.wifi.aware.IdentityChangedListener, @Nullable android.os.Handler);
- method public android.net.wifi.aware.Characteristics getCharacteristics();
+ method @Nullable public android.net.wifi.aware.AwareResources getAvailableAwareResources();
+ method @Nullable public android.net.wifi.aware.Characteristics getCharacteristics();
method public boolean isAvailable();
method public boolean isDeviceAttached();
method public boolean isInstantCommunicationModeEnabled();
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
deleted file mode 100644
index 8ca290fb1b09..000000000000
--- a/api/module-lib-current.txt
+++ /dev/null
@@ -1,222 +0,0 @@
-// Signature format: 2.0
-package android.app {
-
- public class ActivityManager {
- method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void addHomeVisibilityListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.HomeVisibilityListener);
- method @RequiresPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER) public void removeHomeVisibilityListener(@NonNull android.app.HomeVisibilityListener);
- }
-
- public class AppOpsManager {
- field public static final String OPSTR_NO_ISOLATED_STORAGE = "android:no_isolated_storage";
- }
-
- public abstract class HomeVisibilityListener {
- ctor public HomeVisibilityListener();
- method public abstract void onHomeVisibilityChanged(boolean);
- }
-
- public class NotificationManager {
- method public boolean hasEnabledNotificationListener(@NonNull String, @NonNull android.os.UserHandle);
- field public static final String ACTION_NOTIFICATION_LISTENER_ENABLED_CHANGED = "android.app.action.NOTIFICATION_LISTENER_ENABLED_CHANGED";
- }
-
- public class StatusBarManager {
- method @RequiresPermission(android.Manifest.permission.STATUS_BAR) public void setExpansionDisabledForSimNetworkLock(boolean);
- }
-
-}
-
-package android.app.role {
-
- public final class RoleManager {
- method @Nullable public String getSmsRoleHolder(int);
- }
-
-}
-
-package android.content.rollback {
-
- public class RollbackManagerFrameworkInitializer {
- method public static void initialize();
- }
-
-}
-
-package android.graphics {
-
- public final class Compatibility {
- method public static void setTargetSdkVersion(int);
- }
-
- public final class ImageDecoder implements java.lang.AutoCloseable {
- method @AnyThread @NonNull public static android.graphics.ImageDecoder.Source createSource(@NonNull android.content.ContentResolver, @NonNull android.net.Uri, @Nullable android.content.res.Resources);
- }
-
-}
-
-package android.media {
-
- public class AudioManager {
- method public void adjustStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
- method public void adjustSuggestedStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
- method public void setStreamVolumeForUid(int, int, int, @NonNull String, int, int, int);
- field public static final int FLAG_FROM_KEY = 4096; // 0x1000
- }
-
- public class MediaMetadataRetriever implements java.lang.AutoCloseable {
- field public static final int METADATA_KEY_VIDEO_CODEC_MIME_TYPE = 40; // 0x28
- }
-
- @Deprecated public final class MediaParceledListSlice<T extends android.os.Parcelable> implements android.os.Parcelable {
- ctor @Deprecated public MediaParceledListSlice(@NonNull java.util.List<T>);
- method @Deprecated public int describeContents();
- method @Deprecated @NonNull public static <T extends android.os.Parcelable> android.media.MediaParceledListSlice<T> emptyList();
- method @Deprecated public java.util.List<T> getList();
- method @Deprecated public void setInlineCountLimit(int);
- method @Deprecated public void writeToParcel(android.os.Parcel, int);
- field @Deprecated @NonNull public static final android.os.Parcelable.ClassLoaderCreator<android.media.MediaParceledListSlice> CREATOR;
- }
-
-}
-
-package android.media.session {
-
- public static final class MediaController.PlaybackInfo implements android.os.Parcelable {
- ctor public MediaController.PlaybackInfo(int, int, @IntRange(from=0) int, @IntRange(from=0) int, @NonNull android.media.AudioAttributes, @Nullable String);
- }
-
- public final class MediaSession {
- field public static final int FLAG_EXCLUSIVE_GLOBAL_PRIORITY = 65536; // 0x10000
- }
-
- public static final class MediaSession.Token implements android.os.Parcelable {
- method public int getUid();
- }
-
- public final class MediaSessionManager {
- method public void addOnActiveSessionsChangedListener(@NonNull android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, @Nullable android.content.ComponentName, int, @Nullable android.os.Handler);
- method public void dispatchMediaKeyEventAsSystemService(@NonNull android.view.KeyEvent);
- method public boolean dispatchMediaKeyEventToSessionAsSystemService(@NonNull android.view.KeyEvent, @NonNull android.media.session.MediaSession.Token);
- method public void dispatchVolumeKeyEventAsSystemService(@NonNull android.view.KeyEvent, int);
- method public void dispatchVolumeKeyEventToSessionAsSystemService(@NonNull android.view.KeyEvent, @NonNull android.media.session.MediaSession.Token);
- field public static final int RESULT_MEDIA_KEY_HANDLED = 1; // 0x1
- field public static final int RESULT_MEDIA_KEY_NOT_HANDLED = 0; // 0x0
- }
-
- public final class PlaybackState implements android.os.Parcelable {
- method public boolean isActiveState();
- }
-
-}
-
-package android.net {
-
- public final class TetheringConstants {
- field public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
- field public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
- field public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
- field public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
- field public static final String EXTRA_SET_ALARM = "extraSetAlarm";
- }
-
- public class TetheringManager {
- ctor public TetheringManager(@NonNull android.content.Context, @NonNull java.util.function.Supplier<android.os.IBinder>);
- method public int getLastTetherError(@NonNull String);
- method @NonNull public String[] getTetherableBluetoothRegexs();
- method @NonNull public String[] getTetherableIfaces();
- method @NonNull public String[] getTetherableUsbRegexs();
- method @NonNull public String[] getTetherableWifiRegexs();
- method @NonNull public String[] getTetheredIfaces();
- method @NonNull public String[] getTetheringErroredIfaces();
- method public boolean isTetheringSupported();
- method public boolean isTetheringSupported(@NonNull String);
- method public void requestLatestTetheringEntitlementResult(int, @NonNull android.os.ResultReceiver, boolean);
- method @Deprecated public int setUsbTethering(boolean);
- method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
- method @Deprecated public int tether(@NonNull String);
- method @Deprecated public int untether(@NonNull String);
- }
-
- public static interface TetheringManager.TetheringEventCallback {
- method public default void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps);
- }
-
- public static class TetheringManager.TetheringInterfaceRegexps {
- method @NonNull public java.util.List<java.lang.String> getTetherableBluetoothRegexs();
- method @NonNull public java.util.List<java.lang.String> getTetherableUsbRegexs();
- method @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs();
- }
-
-}
-
-package android.os {
-
- public class Binder implements android.os.IBinder {
- method public final void markVintfStability();
- }
-
- public interface Parcelable {
- method public default int getStability();
- }
-
- public class StatsFrameworkInitializer {
- method public static void registerServiceWrappers();
- method public static void setStatsServiceManager(@NonNull android.os.StatsServiceManager);
- }
-
- public class StatsServiceManager {
- method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsCompanionServiceRegisterer();
- method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsManagerServiceRegisterer();
- method @NonNull public android.os.StatsServiceManager.ServiceRegisterer getStatsdServiceRegisterer();
- }
-
- public static class StatsServiceManager.ServiceNotFoundException extends java.lang.Exception {
- ctor public StatsServiceManager.ServiceNotFoundException(@NonNull String);
- }
-
- public static final class StatsServiceManager.ServiceRegisterer {
- method @Nullable public android.os.IBinder get();
- method @Nullable public android.os.IBinder getOrThrow() throws android.os.StatsServiceManager.ServiceNotFoundException;
- }
-
-}
-
-package android.provider {
-
- public final class DeviceConfig {
- field public static final String NAMESPACE_ALARM_MANAGER = "alarm_manager";
- field public static final String NAMESPACE_APP_STANDBY = "app_standby";
- field public static final String NAMESPACE_DEVICE_IDLE = "device_idle";
- }
-
-}
-
-package android.telephony {
-
- public abstract class CellSignalStrength {
- method public static int getNumSignalStrengthLevels();
- }
-
- public class TelephonyManager {
- method @NonNull public static int[] getAllNetworkTypes();
- }
-
-}
-
-package android.util {
-
- public class AtomicFile {
- ctor public AtomicFile(@NonNull java.io.File, @Nullable android.util.SystemConfigFileCommitEventLogger);
- }
-
- public final class Log {
- method public static int logToRadioBuffer(int, @Nullable String, @Nullable String);
- }
-
- public class SystemConfigFileCommitEventLogger {
- ctor public SystemConfigFileCommitEventLogger(@NonNull String);
- method public void setStartTime(long);
- }
-
-}
-
diff --git a/api/module-lib-lint-baseline.txt b/api/module-lib-lint-baseline.txt
deleted file mode 100644
index 56f7a02260a7..000000000000
--- a/api/module-lib-lint-baseline.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-// Baseline format: 1.0
-ActionValue: android.net.TetheringConstants#EXTRA_ADD_TETHER_TYPE:
- Inconsistent extra value; expected `android.net.extra.ADD_TETHER_TYPE`, was `extraAddTetherType`
-ActionValue: android.net.TetheringConstants#EXTRA_PROVISION_CALLBACK:
- Inconsistent extra value; expected `android.net.extra.PROVISION_CALLBACK`, was `extraProvisionCallback`
-ActionValue: android.net.TetheringConstants#EXTRA_REM_TETHER_TYPE:
- Inconsistent extra value; expected `android.net.extra.REM_TETHER_TYPE`, was `extraRemTetherType`
-ActionValue: android.net.TetheringConstants#EXTRA_RUN_PROVISION:
- Inconsistent extra value; expected `android.net.extra.RUN_PROVISION`, was `extraRunProvision`
-ActionValue: android.net.TetheringConstants#EXTRA_SET_ALARM:
- Inconsistent extra value; expected `android.net.extra.SET_ALARM`, was `extraSetAlarm`
-ActionValue: android.net.TetheringManager#ACTION_TETHER_STATE_CHANGED:
- Inconsistent action value; expected `android.net.action.TETHER_STATE_CHANGED`, was `android.net.conn.TETHER_STATE_CHANGED`
-ActionValue: android.net.TetheringManager#EXTRA_ACTIVE_TETHER:
- Inconsistent extra value; expected `android.net.extra.ACTIVE_TETHER`, was `tetherArray`
-ActionValue: android.net.TetheringManager#EXTRA_AVAILABLE_TETHER:
- Inconsistent extra value; expected `android.net.extra.AVAILABLE_TETHER`, was `availableArray`
-ActionValue: android.net.TetheringManager#EXTRA_ERRORED_TETHER:
- Inconsistent extra value; expected `android.net.extra.ERRORED_TETHER`, was `erroredArray`
-
-
-ManagerConstructor: android.net.TetheringManager#TetheringManager(android.content.Context, java.util.function.Supplier<android.os.IBinder>):
- Managers must always be obtained from Context; no direct constructors
-
-
-PrivateSuperclass: android.location.GnssAntennaInfo.PhaseCenterVariationCorrections:
- Public class android.location.GnssAntennaInfo.PhaseCenterVariationCorrections extends private class android.location.GnssAntennaInfo.SphericalCorrections
-PrivateSuperclass: android.location.GnssAntennaInfo.SignalGainCorrections:
- Public class android.location.GnssAntennaInfo.SignalGainCorrections extends private class android.location.GnssAntennaInfo.SphericalCorrections
diff --git a/api/module-lib-removed.txt b/api/module-lib-removed.txt
deleted file mode 100644
index d802177e249b..000000000000
--- a/api/module-lib-removed.txt
+++ /dev/null
@@ -1 +0,0 @@
-// Signature format: 2.0
diff --git a/api/system-current.txt b/api/system-current.txt
index 87f3f4c65520..095d628d9b78 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4423,11 +4423,11 @@ package android.media {
}
public class MediaPlayer implements android.media.AudioRouting android.media.VolumeAutomation {
- method @RequiresPermission("android.permission.BIND_IMS_SERVICE") public void setOnImsRxNoticeListener(@Nullable android.media.MediaPlayer.OnImsRxNoticeListener, @Nullable android.os.Handler);
+ method @RequiresPermission("android.permission.BIND_IMS_SERVICE") public void setOnRtpRxNoticeListener(@NonNull android.content.Context, @NonNull android.media.MediaPlayer.OnRtpRxNoticeListener, @Nullable android.os.Handler);
}
- public static interface MediaPlayer.OnImsRxNoticeListener {
- method public void onImsRxNotice(@NonNull android.media.MediaPlayer, @NonNull byte[]);
+ public static interface MediaPlayer.OnRtpRxNoticeListener {
+ method public void onRtpRxNotice(@NonNull android.media.MediaPlayer, int, @NonNull int[]);
}
public final class MediaRecorder.AudioSource {
@@ -5725,7 +5725,7 @@ package android.media.tv.tuner.frontend {
method @NonNull public android.media.tv.tuner.frontend.AtscFrontendSettings.Builder setModulation(int);
}
- public class DtmbFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
+ public final class DtmbFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
method public int getBandwidthCapability();
method public int getCodeRateCapability();
method public int getGuardIntervalCapability();
@@ -5734,7 +5734,7 @@ package android.media.tv.tuner.frontend {
method public int getTransmissionModeCapability();
}
- public class DtmbFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
+ public final class DtmbFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
method @NonNull public static android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder builder();
method public int getBandwidth();
method public int getCodeRate();
@@ -5797,6 +5797,7 @@ package android.media.tv.tuner.frontend {
public class DvbcFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
method @NonNull public static android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder builder();
method public int getAnnex();
+ method public int getBandwidth();
method public long getInnerFec();
method public int getModulation();
method public int getOuterFec();
@@ -5808,6 +5809,11 @@ package android.media.tv.tuner.frontend {
field public static final int ANNEX_B = 2; // 0x2
field public static final int ANNEX_C = 4; // 0x4
field public static final int ANNEX_UNDEFINED = 0; // 0x0
+ field public static final int BANDWIDTH_5MHZ = 1; // 0x1
+ field public static final int BANDWIDTH_6MHZ = 2; // 0x2
+ field public static final int BANDWIDTH_7MHZ = 4; // 0x4
+ field public static final int BANDWIDTH_8MHZ = 8; // 0x8
+ field public static final int BANDWIDTH_UNDEFINED = 0; // 0x0
field public static final int MODULATION_AUTO = 1; // 0x1
field public static final int MODULATION_MOD_128QAM = 16; // 0x10
field public static final int MODULATION_MOD_16QAM = 2; // 0x2
@@ -5837,6 +5843,7 @@ package android.media.tv.tuner.frontend {
public static class DvbcFrontendSettings.Builder {
method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings build();
method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setAnnex(int);
+ method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setBandwidth(int);
method @IntRange(from=1) @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setFrequency(int);
method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setInnerFec(long);
method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setModulation(int);
@@ -6130,17 +6137,17 @@ package android.media.tv.tuner.frontend {
method public int getBer();
method @NonNull public int[] getBers();
method @NonNull public int[] getCodeRates();
+ method @NonNull public int[] getExtendedModulations();
method public int getFreqOffset();
method public int getGuardInterval();
method public int getHierarchy();
method public long getInnerFec();
method @NonNull public int[] getInterleaving();
- method @NonNull public int[] getIsdbtSegment();
+ method @IntRange(from=0, to=255) @NonNull public int[] getIsdbtSegment();
method @NonNull public boolean[] getLayerErrors();
method public int getLnbVoltage();
method public int getMer();
method public int getModulation();
- method @NonNull public int[] getModulationsExt();
method public int getPer();
method public int getPerBer();
method public int getPlpId();
@@ -6149,7 +6156,7 @@ package android.media.tv.tuner.frontend {
method public int getSnr();
method public int getSpectralInversion();
method public int getSymbolRate();
- method public int getSystemId();
+ method @IntRange(from=0, to=65535) public int getSystemId();
method public int getTransmissionMode();
method @NonNull public int[] getTsDataRate();
method public int getUec();
@@ -7676,8 +7683,11 @@ package android.net.wifi {
method public double getSuccessfulRxPacketsPerSecond();
method public double getSuccessfulTxPacketsPerSecond();
method public boolean isEphemeral();
+ method public boolean isOemPaid();
+ method public boolean isOemPrivate();
method public boolean isOsuAp();
method public boolean isPasspointAp();
+ method public boolean isTrusted();
method @Nullable public static String sanitizeSsid(@Nullable String);
field public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
field public static final int INVALID_RSSI = -127; // 0xffffff81
@@ -7903,11 +7913,13 @@ package android.net.wifi {
public final class WifiNetworkSuggestion implements android.os.Parcelable {
method @NonNull public android.net.wifi.WifiConfiguration getWifiConfiguration();
method public boolean isOemPaid();
+ method public boolean isOemPrivate();
}
public static final class WifiNetworkSuggestion.Builder {
method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) public android.net.wifi.WifiNetworkSuggestion.Builder setCarrierId(int);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setOemPaid(boolean);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setOemPrivate(boolean);
}
public class WifiScanner {
@@ -9473,6 +9485,7 @@ package android.provider {
field public static final String NAMESPACE_PACKAGE_MANAGER_SERVICE = "package_manager_service";
field public static final String NAMESPACE_PERMISSIONS = "permissions";
field public static final String NAMESPACE_PRIVACY = "privacy";
+ field public static final String NAMESPACE_PROFCOLLECT_NATIVE_BOOT = "profcollect_native_boot";
field public static final String NAMESPACE_ROLLBACK = "rollback";
field public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot";
field public static final String NAMESPACE_RUNTIME = "runtime";
diff --git a/api/system-lint-baseline.txt b/api/system-lint-baseline.txt
index 773ecd034a8e..3ef1f354d9e8 100644
--- a/api/system-lint-baseline.txt
+++ b/api/system-lint-baseline.txt
@@ -41,8 +41,8 @@ BuilderSetStyle: android.net.IpSecTransform.Builder#buildTunnelModeTransform(jav
Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.net.IpSecTransform.Builder.buildTunnelModeTransform(java.net.InetAddress,android.net.IpSecManager.SecurityParameterIndex)
-ExecutorRegistration: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler):
- Registration methods should have overload that accepts delivery Executor: `setOnImsRxNoticeListener`
+ExecutorRegistration: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler):
+ Registration methods should have overload that accepts delivery Executor: `setOnRtpRxNoticeListener`
ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#deletePersistentGroup(android.net.wifi.p2p.WifiP2pManager.Channel, int, android.net.wifi.p2p.WifiP2pManager.ActionListener):
ExecutorRegistration: android.net.wifi.p2p.WifiP2pManager#factoryReset(android.net.wifi.p2p.WifiP2pManager.Channel, android.net.wifi.p2p.WifiP2pManager.ActionListener):
@@ -377,8 +377,8 @@ SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android.
SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioTrack.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler):
- SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaPlayer.setOnImsRxNoticeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.media.MediaPlayer.setOnRtpRxNoticeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.MediaRecorder#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
SamShouldBeLast: android.media.MediaRecorder#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback):
diff --git a/api/test-current.txt b/api/test-current.txt
index f0159cf4dd2f..67b496b4f7ab 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -290,6 +290,7 @@ package android.app {
method @NonNull public android.content.res.Configuration getConfiguration();
method @Nullable public android.app.PictureInPictureParams getPictureInPictureParams();
method @NonNull public android.window.WindowContainerToken getToken();
+ method public boolean hasParentTask();
}
public class TimePickerDialog extends android.app.AlertDialog implements android.content.DialogInterface.OnClickListener android.widget.TimePicker.OnTimeChangedListener {
@@ -1801,6 +1802,7 @@ package android.telephony {
method @NonNull public java.util.List<android.telephony.data.ApnSetting> getDevicePolicyOverrideApns(@NonNull android.content.Context);
method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getLine1AlphaTag();
method public android.util.Pair<java.lang.Integer,java.lang.Integer> getRadioHalVersion();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
method public boolean modifyDevicePolicyOverrideApn(@NonNull android.content.Context, int, @NonNull android.telephony.data.ApnSetting);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void refreshUiccProfile();
method @Deprecated public void setCarrierTestOverride(String, String, String, String, String, String, String);
diff --git a/cmds/statsd/src/anomaly/AlarmTracker.h b/cmds/statsd/src/anomaly/AlarmTracker.h
index 2da4a18682ae..406086da557b 100644
--- a/cmds/statsd/src/anomaly/AlarmTracker.h
+++ b/cmds/statsd/src/anomaly/AlarmTracker.h
@@ -73,6 +73,7 @@ protected:
FRIEND_TEST(AlarmTrackerTest, TestTriggerTimestamp);
FRIEND_TEST(AlarmE2eTest, TestMultipleAlarms);
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateAlarms);
};
} // namespace statsd
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.cpp b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
index 619752c7c44a..6aa410b180b8 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.cpp
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.cpp
@@ -37,14 +37,6 @@ namespace statsd {
AnomalyTracker::AnomalyTracker(const Alert& alert, const ConfigKey& configKey)
: mAlert(alert), mConfigKey(configKey), mNumOfPastBuckets(mAlert.num_buckets() - 1) {
VLOG("AnomalyTracker() called");
- if (mAlert.num_buckets() <= 0) {
- ALOGE("Cannot create AnomalyTracker with %lld buckets", (long long)mAlert.num_buckets());
- return;
- }
- if (!mAlert.has_trigger_if_sum_gt()) {
- ALOGE("Cannot create AnomalyTracker without threshold");
- return;
- }
resetStorage(); // initialization
}
@@ -52,6 +44,10 @@ AnomalyTracker::~AnomalyTracker() {
VLOG("~AnomalyTracker() called");
}
+void AnomalyTracker::onConfigUpdated() {
+ mSubscriptions.clear();
+}
+
void AnomalyTracker::resetStorage() {
VLOG("resetStorage() called.");
mPastBuckets.clear();
@@ -259,6 +255,15 @@ bool AnomalyTracker::isInRefractoryPeriod(const int64_t& timestampNs,
return false;
}
+std::pair<bool, uint64_t> AnomalyTracker::getProtoHash() const {
+ string serializedAlert;
+ if (!mAlert.SerializeToString(&serializedAlert)) {
+ ALOGW("Unable to serialize alert %lld", (long long)mAlert.id());
+ return {false, 0};
+ }
+ return {true, Hash64(serializedAlert)};
+}
+
void AnomalyTracker::informSubscribers(const MetricDimensionKey& key, int64_t metric_id,
int64_t metricValue) {
triggerSubscribers(mAlert.id(), metric_id, key, metricValue, mConfigKey, mSubscriptions);
diff --git a/cmds/statsd/src/anomaly/AnomalyTracker.h b/cmds/statsd/src/anomaly/AnomalyTracker.h
index bf36a3bc8990..9a578ee0696d 100644
--- a/cmds/statsd/src/anomaly/AnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/AnomalyTracker.h
@@ -16,15 +16,15 @@
#pragma once
-#include <stdlib.h>
-
#include <gtest/gtest_prod.h>
+#include <stdlib.h>
#include <utils/RefBase.h>
#include "AlarmMonitor.h"
#include "config/ConfigKey.h"
-#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" // Alert
+#include "frameworks/base/cmds/statsd/src/statsd_config.pb.h" // Alert
#include "frameworks/base/cmds/statsd/src/statsd_metadata.pb.h" // AlertMetadata
+#include "hash.h"
#include "stats_util.h" // HashableDimensionKey and DimToValMap
namespace android {
@@ -41,6 +41,9 @@ public:
virtual ~AnomalyTracker();
+ // Reset appropriate state on a config update. Clear subscriptions so they can be reset.
+ void onConfigUpdated();
+
// Add subscriptions that depend on this alert.
void addSubscription(const Subscription& subscription) {
mSubscriptions.push_back(subscription);
@@ -106,6 +109,26 @@ public:
return mNumOfPastBuckets;
}
+ std::pair<bool, uint64_t> getProtoHash() const;
+
+ // Sets an alarm for the given timestamp.
+ // Replaces previous alarm if one already exists.
+ virtual void startAlarm(const MetricDimensionKey& dimensionKey, const int64_t& eventTime) {
+ return; // The base AnomalyTracker class doesn't have alarms.
+ }
+
+ // Stops the alarm.
+ // If it should have already fired, but hasn't yet (e.g. because the AlarmManager is delayed),
+ // declare the anomaly now.
+ virtual void stopAlarm(const MetricDimensionKey& dimensionKey, const int64_t& timestampNs) {
+ return; // The base AnomalyTracker class doesn't have alarms.
+ }
+
+ // Stop all the alarms owned by this tracker. Does not declare any anomalies.
+ virtual void cancelAllAlarms() {
+ return; // The base AnomalyTracker class doesn't have alarms.
+ }
+
// Declares an anomaly for each alarm in firedAlarms that belongs to this AnomalyTracker,
// and removes it from firedAlarms. Does NOT remove the alarm from the AlarmMonitor.
virtual void informAlarmsFired(const int64_t& timestampNs,
@@ -197,6 +220,8 @@ protected:
FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket);
FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets);
FRIEND_TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period);
+
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateAlerts);
};
} // namespace statsd
diff --git a/cmds/statsd/src/anomaly/DurationAnomalyTracker.h b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
index 686d8f95c7f6..46419149580b 100644
--- a/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
+++ b/cmds/statsd/src/anomaly/DurationAnomalyTracker.h
@@ -34,15 +34,15 @@ public:
// Sets an alarm for the given timestamp.
// Replaces previous alarm if one already exists.
- void startAlarm(const MetricDimensionKey& dimensionKey, const int64_t& eventTime);
+ void startAlarm(const MetricDimensionKey& dimensionKey, const int64_t& eventTime) override;
// Stops the alarm.
// If it should have already fired, but hasn't yet (e.g. because the AlarmManager is delayed),
// declare the anomaly now.
- void stopAlarm(const MetricDimensionKey& dimensionKey, const int64_t& timestampNs);
+ void stopAlarm(const MetricDimensionKey& dimensionKey, const int64_t& timestampNs) override;
// Stop all the alarms owned by this tracker. Does not declare any anomalies.
- void cancelAllAlarms();
+ void cancelAllAlarms() override;
// Declares an anomaly for each alarm in firedAlarms that belongs to this DurationAnomalyTracker
// and removes it from firedAlarms. The AlarmMonitor is not informed.
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index a379847f21da..ac2a8e4ffcd2 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -9754,6 +9754,7 @@ message RebootEscrowRecoveryReported {
/**
* Global display pipeline metrics reported by SurfaceFlinger.
+ * Metrics exist beginning in Android 11.
* Pulled from:
* frameworks/native/services/surfaceflinger/TimeStats/TimeStats.cpp
*/
@@ -9785,18 +9786,48 @@ message SurfaceflingerStatsGlobalInfo {
// perform due to falling back into GPU composition.
optional FrameTimingHistogram render_engine_timing = 8
[(android.os.statsd.log_mode) = MODE_BYTES];
+ // Number of frames where SF saw a frame, based on its frame timeline.
+ // Frame timelines may include transactions without updating buffer contents.
+ // Introduced in Android 12.
+ optional int32 total_timeline_frames = 9;
+ // Number of frames where SF saw a janky frame.
+ // Introduced in Android 12.
+ optional int32 total_janky_frames = 10;
+ // Number of janky frames where SF spent a long time on the CPU.
+ // Introduced in Android 12.
+ optional int32 total_janky_frames_with_long_cpu = 11;
+ // Number of janky frames where SF spent a long time on the GPU.
+ // Introduced in Android 12.
+ optional int32 total_janky_frames_with_long_gpu = 12;
+ // Number of janky frames where SF missed the frame deadline, but there
+ // was not an attributed reason (e.g., maybe HWC missed?)
+ // Introduced in Android 12.
+ optional int32 total_janky_frames_sf_unattributed = 13;
+ // Number of janky frames where the app missed the frame deadline, but
+ // there was not an attributed reason
+ // Introduced in Android 12.
+ optional int32 total_janky_frames_app_unattributed = 14;
+
+ // Next ID: 15
}
/**
* Per-layer display pipeline metrics reported by SurfaceFlinger.
- * The number of layers uploaded will be restricted due to size limitations.
+ * Metrics exist beginning in Android 11.
+ * The number of layers uploaded may be restricted due to size limitations.
* Pulled from:
* frameworks/native/services/surfaceflinger/TimeStats/TimeStats.cpp
*/
message SurfaceflingerStatsLayerInfo {
+ // UID of the application who submitted this layer for presentation
+ // This is intended to be used as a dimension for surfacing rendering
+ // statistics to applications.
+ // Introduced in Android 12.
+ optional int32 uid = 12 [(is_uid) = true];
// The layer for this set of metrics
- // For now we can infer that the package name is included in the layer
- // name.
+ // In many scenarios the package name is included in the layer name, e.g.,
+ // layers created by Window Manager. But this is not a guarantee - in the
+ // general case layer names are arbitrary debug names.
optional string layer_name = 1;
// Total number of frames presented
optional int64 total_frames = 2;
@@ -9830,6 +9861,29 @@ message SurfaceflingerStatsLayerInfo {
optional int64 late_acquire_frames = 10;
// Frames latched early because the desired present time was bad
optional int64 bad_desired_present_frames = 11;
+ // Number of frames where SF saw a frame, based on its frame timeline.
+ // Frame timelines may include transactions without updating buffer contents.
+ // Introduced in Android 12.
+ optional int32 total_timeline_frames = 13;
+ // Number of frames where SF saw a janky frame.
+ // Introduced in Android 12.
+ optional int32 total_janky_frames = 14;
+ // Number of janky frames where SF spent a long time on the CPU.
+ // Introduced in Android 12.
+ optional int32 total_janky_frames_with_long_cpu = 15;
+ // Number of janky frames where SF spent a long time on the GPU.
+ // Introduced in Android 12.
+ optional int32 total_janky_frames_with_long_gpu = 16;
+ // Number of janky frames where SF missed the frame deadline, but there
+ // was not an attributed reason (e.g., maybe HWC missed?)
+ // Introduced in Android 12.
+ optional int32 total_janky_frames_sf_unattributed = 17;
+ // Number of janky frames where the app missed the frame deadline, but
+ // there was not an attributed reason
+ // Introduced in Android 12.
+ optional int32 total_janky_frames_app_unattributed = 18;
+
+ // Next ID: 19
}
/**
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.cpp b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
index b2c0b32bf5ef..8869241ab8aa 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.cpp
@@ -234,14 +234,26 @@ sp<AnomalyTracker> DurationMetricProducer::addAnomalyTracker(
return nullptr;
}
}
- sp<DurationAnomalyTracker> anomalyTracker =
- new DurationAnomalyTracker(alert, mConfigKey, anomalyAlarmMonitor);
- if (anomalyTracker != nullptr) {
- mAnomalyTrackers.push_back(anomalyTracker);
- }
+ sp<AnomalyTracker> anomalyTracker =
+ new DurationAnomalyTracker(alert, mConfigKey, anomalyAlarmMonitor);
+ addAnomalyTrackerLocked(anomalyTracker);
return anomalyTracker;
}
+// Adds an AnomalyTracker that has already been created.
+// Note: this gets called on config updates, and will only get called if the metric and the
+// associated alert are preserved, which means the AnomalyTracker must be a DurationAnomalyTracker.
+void DurationMetricProducer::addAnomalyTracker(sp<AnomalyTracker>& anomalyTracker) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ addAnomalyTrackerLocked(anomalyTracker);
+}
+
+void DurationMetricProducer::addAnomalyTrackerLocked(sp<AnomalyTracker>& anomalyTracker) {
+ mAnomalyTrackers.push_back(anomalyTracker);
+ for (const auto& [_, durationTracker] : mCurrentSlicedDurationTrackerMap) {
+ durationTracker->addAnomalyTracker(anomalyTracker);
+ }
+}
void DurationMetricProducer::onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
const HashableDimensionKey& primaryKey,
const FieldValue& oldState,
diff --git a/cmds/statsd/src/metrics/DurationMetricProducer.h b/cmds/statsd/src/metrics/DurationMetricProducer.h
index 01198a9271d3..5feb09fc1c98 100644
--- a/cmds/statsd/src/metrics/DurationMetricProducer.h
+++ b/cmds/statsd/src/metrics/DurationMetricProducer.h
@@ -55,6 +55,8 @@ public:
sp<AnomalyTracker> addAnomalyTracker(const Alert &alert,
const sp<AlarmMonitor>& anomalyAlarmMonitor) override;
+ void addAnomalyTracker(sp<AnomalyTracker>& anomalyTracker) override;
+
void onStateChanged(const int64_t eventTimeNs, const int32_t atomId,
const HashableDimensionKey& primaryKey, const FieldValue& oldState,
const FieldValue& newState) override;
@@ -128,6 +130,8 @@ private:
std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
std::vector<int>& metricsWithActivation) override;
+ void addAnomalyTrackerLocked(sp<AnomalyTracker>& anomalyTracker);
+
const DurationMetric_AggregationType mAggregationType;
// Index of the SimpleAtomMatcher which defines the start.
@@ -164,9 +168,6 @@ private:
std::unique_ptr<DurationTracker> createDurationTracker(
const MetricDimensionKey& eventKey) const;
- // This hides the base class's std::vector<sp<AnomalyTracker>> mAnomalyTrackers
- std::vector<sp<DurationAnomalyTracker>> mAnomalyTrackers;
-
// Util function to check whether the specified dimension hits the guardrail.
bool hitGuardRailLocked(const MetricDimensionKey& newKey);
@@ -185,6 +186,7 @@ private:
FRIEND_TEST(DurationMetricProducerTest_PartialBucket, TestMaxDurationWithSplitInNextBucket);
FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateAlerts);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricProducer.cpp b/cmds/statsd/src/metrics/MetricProducer.cpp
index 95a7d40ea9a9..5b321a0e3d60 100644
--- a/cmds/statsd/src/metrics/MetricProducer.cpp
+++ b/cmds/statsd/src/metrics/MetricProducer.cpp
@@ -101,6 +101,7 @@ bool MetricProducer::onConfigUpdatedLocked(
}
mEventActivationMap = newEventActivationMap;
mEventDeactivationMap = newEventDeactivationMap;
+ mAnomalyTrackers.clear();
return true;
}
diff --git a/cmds/statsd/src/metrics/MetricProducer.h b/cmds/statsd/src/metrics/MetricProducer.h
index 92c1a6e62640..0dc8edae8056 100644
--- a/cmds/statsd/src/metrics/MetricProducer.h
+++ b/cmds/statsd/src/metrics/MetricProducer.h
@@ -155,6 +155,7 @@ public:
// Update appropriate state on config updates. Primarily, all indices need to be updated.
// This metric and all of its dependencies are guaranteed to be preserved across the update.
// This function also updates several maps used by metricsManager.
+ // This function clears all anomaly trackers. All anomaly trackers need to be added again.
bool onConfigUpdated(
const StatsdConfig& config, const int configIndex, const int metricIndex,
const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
@@ -237,9 +238,6 @@ public:
dumpLatency, str_set, protoOutput);
}
- // Update appropriate state on config updates. Primarily, all indices need to be updated.
- // This metric and all of its dependencies are guaranteed to be preserved across the update.
- // This function also updates several maps used by metricsManager.
virtual bool onConfigUpdatedLocked(
const StatsdConfig& config, const int configIndex, const int metricIndex,
const std::vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
@@ -338,16 +336,20 @@ public:
return mSlicedStateAtoms;
}
- /* If alert is valid, adds an AnomalyTracker and returns it. If invalid, returns nullptr. */
+ /* Adds an AnomalyTracker and returns it. */
virtual sp<AnomalyTracker> addAnomalyTracker(const Alert &alert,
const sp<AlarmMonitor>& anomalyAlarmMonitor) {
std::lock_guard<std::mutex> lock(mMutex);
sp<AnomalyTracker> anomalyTracker = new AnomalyTracker(alert, mConfigKey);
- if (anomalyTracker != nullptr) {
- mAnomalyTrackers.push_back(anomalyTracker);
- }
+ mAnomalyTrackers.push_back(anomalyTracker);
return anomalyTracker;
}
+
+ /* Adds an AnomalyTracker that has already been created */
+ virtual void addAnomalyTracker(sp<AnomalyTracker>& anomalyTracker) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mAnomalyTrackers.push_back(anomalyTracker);
+ }
// End: getters/setters
protected:
/**
@@ -571,6 +573,7 @@ protected:
FRIEND_TEST(ConfigUpdateTest, TestUpdateGaugeMetrics);
FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
FRIEND_TEST(ConfigUpdateTest, TestUpdateMetricsMultipleTypes);
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateAlerts);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/MetricsManager.cpp b/cmds/statsd/src/metrics/MetricsManager.cpp
index ab0d286d6b29..d80f9dbb4256 100644
--- a/cmds/statsd/src/metrics/MetricsManager.cpp
+++ b/cmds/statsd/src/metrics/MetricsManager.cpp
@@ -209,6 +209,9 @@ bool MetricsManager::updateConfig(const StatsdConfig& config, const int64_t time
map<int64_t, uint64_t> newStateProtoHashes;
vector<sp<MetricProducer>> newMetricProducers;
unordered_map<int64_t, int> newMetricProducerMap;
+ vector<sp<AnomalyTracker>> newAnomalyTrackers;
+ unordered_map<int64_t, int> newAlertTrackerMap;
+ vector<sp<AlarmTracker>> newPeriodicAlarmTrackers;
mTagIds.clear();
mConditionToMetricMap.clear();
mTrackerToMetricMap.clear();
@@ -221,11 +224,13 @@ bool MetricsManager::updateConfig(const StatsdConfig& config, const int64_t time
mConfigKey, config, mUidMap, mPullerManager, anomalyAlarmMonitor, periodicAlarmMonitor,
timeBaseNs, currentTimeNs, mAllAtomMatchingTrackers, mAtomMatchingTrackerMap,
mAllConditionTrackers, mConditionTrackerMap, mAllMetricProducers, mMetricProducerMap,
- mStateProtoHashes, mTagIds, newAtomMatchingTrackers, newAtomMatchingTrackerMap,
- newConditionTrackers, newConditionTrackerMap, newMetricProducers, newMetricProducerMap,
- mConditionToMetricMap, mTrackerToMetricMap, mTrackerToConditionMap,
- mActivationAtomTrackerToMetricMap, mDeactivationAtomTrackerToMetricMap,
- mMetricIndexesWithActivation, newStateProtoHashes, mNoReportMetricIds);
+ mAllAnomalyTrackers, mAlertTrackerMap, mStateProtoHashes, mTagIds,
+ newAtomMatchingTrackers, newAtomMatchingTrackerMap, newConditionTrackers,
+ newConditionTrackerMap, newMetricProducers, newMetricProducerMap, newAnomalyTrackers,
+ newAlertTrackerMap, newPeriodicAlarmTrackers, mConditionToMetricMap,
+ mTrackerToMetricMap, mTrackerToConditionMap, mActivationAtomTrackerToMetricMap,
+ mDeactivationAtomTrackerToMetricMap, mMetricIndexesWithActivation, newStateProtoHashes,
+ mNoReportMetricIds);
mAllAtomMatchingTrackers = newAtomMatchingTrackers;
mAtomMatchingTrackerMap = newAtomMatchingTrackerMap;
mAllConditionTrackers = newConditionTrackers;
@@ -233,6 +238,9 @@ bool MetricsManager::updateConfig(const StatsdConfig& config, const int64_t time
mAllMetricProducers = newMetricProducers;
mMetricProducerMap = newMetricProducerMap;
mStateProtoHashes = newStateProtoHashes;
+ mAllAnomalyTrackers = newAnomalyTrackers;
+ mAlertTrackerMap = newAlertTrackerMap;
+ mAllPeriodicAlarmTrackers = newPeriodicAlarmTrackers;
return mConfigValid;
}
diff --git a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
index 657b2e4c3ddf..cf1f437c4168 100644
--- a/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/DurationTracker.h
@@ -71,7 +71,7 @@ public:
sp<ConditionWizard> wizard, int conditionIndex, bool nesting,
int64_t currentBucketStartNs, int64_t currentBucketNum, int64_t startTimeNs,
int64_t bucketSizeNs, bool conditionSliced, bool fullLink,
- const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
+ const std::vector<sp<AnomalyTracker>>& anomalyTrackers)
: mConfigKey(key),
mTrackerId(id),
mEventKey(eventKey),
@@ -93,6 +93,7 @@ public:
sp<ConditionWizard> tmpWizard = mWizard;
mWizard = wizard;
mConditionTrackerIndex = conditionTrackerIndex;
+ mAnomalyTrackers.clear();
};
virtual void noteStart(const HashableDimensionKey& key, bool condition, const int64_t eventTime,
@@ -120,7 +121,7 @@ public:
std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) = 0;
// Predict the anomaly timestamp given the current status.
- virtual int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
+ virtual int64_t predictAnomalyTimestampNs(const AnomalyTracker& anomalyTracker,
const int64_t currentTimestamp) const = 0;
// Dump internal states for debugging
virtual void dumpStates(FILE* out, bool verbose) const = 0;
@@ -132,6 +133,10 @@ public:
// Replace old value with new value for the given state atom.
virtual void updateCurrentStateKey(const int32_t atomId, const FieldValue& newState) = 0;
+ void addAnomalyTracker(sp<AnomalyTracker>& anomalyTracker) {
+ mAnomalyTrackers.push_back(anomalyTracker);
+ }
+
protected:
int64_t getCurrentBucketEndTimeNs() const {
return mStartTimeNs + (mCurrentBucketNum + 1) * mBucketSizeNs;
@@ -218,13 +223,14 @@ protected:
bool mHasLinksToAllConditionDimensionsInTracker;
- std::vector<sp<DurationAnomalyTracker>> mAnomalyTrackers;
+ std::vector<sp<AnomalyTracker>> mAnomalyTrackers;
FRIEND_TEST(OringDurationTrackerTest, TestPredictAnomalyTimestamp);
FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionExpiredAlarm);
FRIEND_TEST(OringDurationTrackerTest, TestAnomalyDetectionFiredAlarm);
FRIEND_TEST(ConfigUpdateTest, TestUpdateDurationMetrics);
+ FRIEND_TEST(ConfigUpdateTest, TestUpdateAlerts);
};
} // namespace statsd
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
index ee4e1672411f..62f49824b874 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.cpp
@@ -30,7 +30,7 @@ MaxDurationTracker::MaxDurationTracker(const ConfigKey& key, const int64_t& id,
int64_t currentBucketStartNs, int64_t currentBucketNum,
int64_t startTimeNs, int64_t bucketSizeNs,
bool conditionSliced, bool fullLink,
- const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
+ const vector<sp<AnomalyTracker>>& anomalyTrackers)
: DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs,
currentBucketNum, startTimeNs, bucketSizeNs, conditionSliced, fullLink,
anomalyTrackers) {
@@ -288,7 +288,7 @@ void MaxDurationTracker::noteConditionChanged(const HashableDimensionKey& key, b
// Note that we don't update mDuration here since it's only updated during noteStop.
}
-int64_t MaxDurationTracker::predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
+int64_t MaxDurationTracker::predictAnomalyTimestampNs(const AnomalyTracker& anomalyTracker,
const int64_t currentTimestamp) const {
// The allowed time we can continue in the current state is the
// (anomaly threshold) - max(elapsed time of the started mInfos).
diff --git a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
index 2891c6e1138a..be2707c60c1b 100644
--- a/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/MaxDurationTracker.h
@@ -29,12 +29,10 @@ namespace statsd {
class MaxDurationTracker : public DurationTracker {
public:
MaxDurationTracker(const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey,
- sp<ConditionWizard> wizard, int conditionIndex,
- bool nesting,
- int64_t currentBucketStartNs, int64_t currentBucketNum,
- int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced,
- bool fullLink,
- const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers);
+ sp<ConditionWizard> wizard, int conditionIndex, bool nesting,
+ int64_t currentBucketStartNs, int64_t currentBucketNum, int64_t startTimeNs,
+ int64_t bucketSizeNs, bool conditionSliced, bool fullLink,
+ const std::vector<sp<AnomalyTracker>>& anomalyTrackers);
MaxDurationTracker(const MaxDurationTracker& tracker) = default;
@@ -57,7 +55,7 @@ public:
void onStateChanged(const int64_t timestamp, const int32_t atomId,
const FieldValue& newState) override;
- int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
+ int64_t predictAnomalyTimestampNs(const AnomalyTracker& anomalyTracker,
const int64_t currentTimestamp) const override;
void dumpStates(FILE* out, bool verbose) const override;
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
index 0d49bbc269a3..247e2e01c992 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.cpp
@@ -28,7 +28,7 @@ OringDurationTracker::OringDurationTracker(
const ConfigKey& key, const int64_t& id, const MetricDimensionKey& eventKey,
sp<ConditionWizard> wizard, int conditionIndex, bool nesting, int64_t currentBucketStartNs,
int64_t currentBucketNum, int64_t startTimeNs, int64_t bucketSizeNs, bool conditionSliced,
- bool fullLink, const vector<sp<DurationAnomalyTracker>>& anomalyTrackers)
+ bool fullLink, const vector<sp<AnomalyTracker>>& anomalyTrackers)
: DurationTracker(key, id, eventKey, wizard, conditionIndex, nesting, currentBucketStartNs,
currentBucketNum, startTimeNs, bucketSizeNs, conditionSliced, fullLink,
anomalyTrackers),
@@ -344,9 +344,8 @@ void OringDurationTracker::onStateChanged(const int64_t timestamp, const int32_t
updateCurrentStateKey(atomId, newState);
}
-int64_t OringDurationTracker::predictAnomalyTimestampNs(
- const DurationAnomalyTracker& anomalyTracker, const int64_t eventTimestampNs) const {
-
+int64_t OringDurationTracker::predictAnomalyTimestampNs(const AnomalyTracker& anomalyTracker,
+ const int64_t eventTimestampNs) const {
// The anomaly threshold.
const int64_t thresholdNs = anomalyTracker.getAnomalyThreshold();
diff --git a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
index bd8017a7decd..6eddee7da252 100644
--- a/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
+++ b/cmds/statsd/src/metrics/duration_helper/OringDurationTracker.h
@@ -31,7 +31,7 @@ public:
int conditionIndex, bool nesting, int64_t currentBucketStartNs,
int64_t currentBucketNum, int64_t startTimeNs, int64_t bucketSizeNs,
bool conditionSliced, bool fullLink,
- const std::vector<sp<DurationAnomalyTracker>>& anomalyTrackers);
+ const std::vector<sp<AnomalyTracker>>& anomalyTrackers);
OringDurationTracker(const OringDurationTracker& tracker) = default;
@@ -54,7 +54,7 @@ public:
int64_t timestampNs,
std::unordered_map<MetricDimensionKey, std::vector<DurationBucket>>* output) override;
- int64_t predictAnomalyTimestampNs(const DurationAnomalyTracker& anomalyTracker,
+ int64_t predictAnomalyTimestampNs(const AnomalyTracker& anomalyTracker,
const int64_t currentTimestamp) const override;
void dumpStates(FILE* out, bool verbose) const override;
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
index 335f7753e5e3..637236145bf5 100644
--- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.cpp
@@ -115,7 +115,6 @@ bool updateAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& ui
vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
set<int64_t>& replacedMatchers) {
const int atomMatcherCount = config.atom_matcher_size();
-
vector<AtomMatcher> matcherProtos;
matcherProtos.reserve(atomMatcherCount);
newAtomMatchingTrackers.reserve(atomMatcherCount);
@@ -891,6 +890,111 @@ bool updateMetrics(const ConfigKey& key, const StatsdConfig& config, const int64
return true;
}
+bool determineAlertUpdateStatus(const Alert& alert,
+ const unordered_map<int64_t, int>& oldAlertTrackerMap,
+ const vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+ const set<int64_t>& replacedMetrics, UpdateStatus& updateStatus) {
+ // Check if new alert.
+ const auto& oldAnomalyTrackerIt = oldAlertTrackerMap.find(alert.id());
+ if (oldAnomalyTrackerIt == oldAlertTrackerMap.end()) {
+ updateStatus = UPDATE_NEW;
+ return true;
+ }
+
+ // This is an existing alert, check if it has changed.
+ string serializedAlert;
+ if (!alert.SerializeToString(&serializedAlert)) {
+ ALOGW("Unable to serialize alert %lld", (long long)alert.id());
+ return false;
+ }
+ uint64_t newProtoHash = Hash64(serializedAlert);
+ const auto [success, oldProtoHash] =
+ oldAnomalyTrackers[oldAnomalyTrackerIt->second]->getProtoHash();
+ if (!success) {
+ return false;
+ }
+ if (newProtoHash != oldProtoHash) {
+ updateStatus = UPDATE_REPLACE;
+ return true;
+ }
+
+ // Check if the metric this alert relies on has changed.
+ if (replacedMetrics.find(alert.metric_id()) != replacedMetrics.end()) {
+ updateStatus = UPDATE_REPLACE;
+ return true;
+ }
+
+ updateStatus = UPDATE_PRESERVE;
+ return true;
+}
+
+bool updateAlerts(const StatsdConfig& config, const unordered_map<int64_t, int>& metricProducerMap,
+ const set<int64_t>& replacedMetrics,
+ const unordered_map<int64_t, int>& oldAlertTrackerMap,
+ const vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+ const sp<AlarmMonitor>& anomalyAlarmMonitor,
+ vector<sp<MetricProducer>>& allMetricProducers,
+ unordered_map<int64_t, int>& newAlertTrackerMap,
+ vector<sp<AnomalyTracker>>& newAnomalyTrackers) {
+ int alertCount = config.alert_size();
+ vector<UpdateStatus> alertUpdateStatuses(alertCount);
+ for (int i = 0; i < alertCount; i++) {
+ if (!determineAlertUpdateStatus(config.alert(i), oldAlertTrackerMap, oldAnomalyTrackers,
+ replacedMetrics, alertUpdateStatuses[i])) {
+ return false;
+ }
+ }
+
+ for (int i = 0; i < alertCount; i++) {
+ const Alert& alert = config.alert(i);
+ newAlertTrackerMap[alert.id()] = newAnomalyTrackers.size();
+ switch (alertUpdateStatuses[i]) {
+ case UPDATE_PRESERVE: {
+ // Find the alert and update it.
+ const auto& oldAnomalyTrackerIt = oldAlertTrackerMap.find(alert.id());
+ if (oldAnomalyTrackerIt == oldAlertTrackerMap.end()) {
+ ALOGW("Could not find AnomalyTracker %lld in the previous config, but "
+ "expected it to be there",
+ (long long)alert.id());
+ return false;
+ }
+ sp<AnomalyTracker> anomalyTracker = oldAnomalyTrackers[oldAnomalyTrackerIt->second];
+ anomalyTracker->onConfigUpdated();
+ // Add the alert to the relevant metric.
+ const auto& metricProducerIt = metricProducerMap.find(alert.metric_id());
+ if (metricProducerIt == metricProducerMap.end()) {
+ ALOGW("alert \"%lld\" has unknown metric id: \"%lld\"", (long long)alert.id(),
+ (long long)alert.metric_id());
+ return false;
+ }
+ allMetricProducers[metricProducerIt->second]->addAnomalyTracker(anomalyTracker);
+ newAnomalyTrackers.push_back(anomalyTracker);
+ break;
+ }
+ case UPDATE_REPLACE:
+ case UPDATE_NEW: {
+ optional<sp<AnomalyTracker>> anomalyTracker = createAnomalyTracker(
+ alert, anomalyAlarmMonitor, metricProducerMap, allMetricProducers);
+ if (!anomalyTracker) {
+ return false;
+ }
+ newAnomalyTrackers.push_back(anomalyTracker.value());
+ break;
+ }
+ default: {
+ ALOGE("Alert \"%lld\" update state is unknown. This should never happen",
+ (long long)alert.id());
+ return false;
+ }
+ }
+ }
+ if (!initSubscribersForSubscriptionType(config, Subscription::ALERT, newAlertTrackerMap,
+ newAnomalyTrackers)) {
+ return false;
+ }
+ return true;
+}
+
bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
const sp<StatsPullerManager>& pullerManager,
const sp<AlarmMonitor>& anomalyAlarmMonitor,
@@ -902,6 +1006,8 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const
const unordered_map<int64_t, int>& oldConditionTrackerMap,
const vector<sp<MetricProducer>>& oldMetricProducers,
const unordered_map<int64_t, int>& oldMetricProducerMap,
+ const vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+ const unordered_map<int64_t, int>& oldAlertTrackerMap,
const map<int64_t, uint64_t>& oldStateProtoHashes, set<int>& allTagIds,
vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
unordered_map<int64_t, int>& newAtomMatchingTrackerMap,
@@ -909,6 +1015,9 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const
unordered_map<int64_t, int>& newConditionTrackerMap,
vector<sp<MetricProducer>>& newMetricProducers,
unordered_map<int64_t, int>& newMetricProducerMap,
+ vector<sp<AnomalyTracker>>& newAnomalyTrackers,
+ unordered_map<int64_t, int>& newAlertTrackerMap,
+ vector<sp<AlarmTracker>>& newPeriodicAlarmTrackers,
unordered_map<int, vector<int>>& conditionToMetricMap,
unordered_map<int, vector<int>>& trackerToMetricMap,
unordered_map<int, vector<int>>& trackerToConditionMap,
@@ -962,10 +1071,23 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const
newMetricProducerMap, newMetricProducers, conditionToMetricMap,
trackerToMetricMap, noReportMetricIds, activationTrackerToMetricMap,
deactivationTrackerToMetricMap, metricsWithActivation, replacedMetrics)) {
- ALOGE("initMetricProducers failed");
+ ALOGE("updateMetrics failed");
+ return false;
+ }
+
+ if (!updateAlerts(config, newMetricProducerMap, replacedMetrics, oldAlertTrackerMap,
+ oldAnomalyTrackers, anomalyAlarmMonitor, newMetricProducers,
+ newAlertTrackerMap, newAnomalyTrackers)) {
+ ALOGE("updateAlerts failed");
return false;
}
+ // Alarms do not have any state, so we can reuse the initialization logic.
+ if (!initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
+ newPeriodicAlarmTrackers)) {
+ ALOGE("initAlarms failed");
+ return false;
+ }
return true;
}
diff --git a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
index 3f1c5326b569..178a9d220b4d 100644
--- a/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
+++ b/cmds/statsd/src/metrics/parsing_utils/config_update_utils.h
@@ -19,6 +19,7 @@
#include <vector>
#include "anomaly/AlarmMonitor.h"
+#include "anomaly/AlarmTracker.h"
#include "condition/ConditionTracker.h"
#include "external/StatsPullerManager.h"
#include "matchers/AtomMatchingTracker.h"
@@ -189,6 +190,45 @@ bool updateMetrics(
std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
std::vector<int>& metricsWithActivation, std::set<int64_t>& replacedMetrics);
+// Function to determine the update status (preserve/replace/new) of an alert.
+// [alert]: the input Alert
+// [oldAlertTrackerMap]: alert id to index mapping in the existing MetricsManager
+// [oldAnomalyTrackers]: stores the existing AnomalyTrackers
+// [replacedMetrics]: set of replaced metric ids. alerts using these metrics must be replaced
+// output:
+// [updateStatus]: update status of the alert. Will be changed from UPDATE_UNKNOWN
+// Returns whether the function was successful or not.
+bool determineAlertUpdateStatus(const Alert& alert,
+ const std::unordered_map<int64_t, int>& oldAlertTrackerMap,
+ const std::vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+ const std::set<int64_t>& replacedMetrics,
+ UpdateStatus& updateStatus);
+
+// Update MetricProducers.
+// input:
+// [config]: the input config
+// [metricProducerMap]: metric id to index mapping in the new config
+// [replacedMetrics]: set of metric ids that have changed and were replaced
+// [oldAlertTrackerMap]: alert id to index mapping in the existing MetricsManager.
+// [oldAnomalyTrackers]: stores the existing AnomalyTrackers
+// [anomalyAlarmMonitor]: AlarmMonitor used for duration metric anomaly detection
+// [allMetricProducers]: stores the sp of the metric producers, AnomalyTrackers need to be added.
+// [stateAtomIdMap]: contains the mapping from state ids to atom ids
+// [allStateGroupMaps]: contains the mapping from atom ids and state values to
+// state group ids for all states
+// output:
+// [newAlertTrackerMap]: mapping of alert id to index in the new config
+// [newAnomalyTrackers]: contains the list of sp to the AnomalyTrackers created.
+bool updateAlerts(const StatsdConfig& config,
+ const std::unordered_map<int64_t, int>& metricProducerMap,
+ const std::set<int64_t>& replacedMetrics,
+ const std::unordered_map<int64_t, int>& oldAlertTrackerMap,
+ const std::vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+ const sp<AlarmMonitor>& anomalyAlarmMonitor,
+ std::vector<sp<MetricProducer>>& allMetricProducers,
+ std::unordered_map<int64_t, int>& newAlertTrackerMap,
+ std::vector<sp<AnomalyTracker>>& newAnomalyTrackers);
+
// Updates the existing MetricsManager from a new StatsdConfig.
// Parameters are the members of MetricsManager. See MetricsManager for declaration.
bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
@@ -202,6 +242,8 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const
const std::unordered_map<int64_t, int>& oldConditionTrackerMap,
const std::vector<sp<MetricProducer>>& oldMetricProducers,
const std::unordered_map<int64_t, int>& oldMetricProducerMap,
+ const std::vector<sp<AnomalyTracker>>& oldAnomalyTrackers,
+ const std::unordered_map<int64_t, int>& oldAlertTrackerMap,
const std::map<int64_t, uint64_t>& oldStateProtoHashes,
std::set<int>& allTagIds,
std::vector<sp<AtomMatchingTracker>>& newAtomMatchingTrackers,
@@ -210,6 +252,9 @@ bool updateStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const
std::unordered_map<int64_t, int>& newConditionTrackerMap,
std::vector<sp<MetricProducer>>& newMetricProducers,
std::unordered_map<int64_t, int>& newMetricProducerMap,
+ std::vector<sp<AnomalyTracker>>& newAlertTrackers,
+ std::unordered_map<int64_t, int>& newAlertTrackerMap,
+ std::vector<sp<AlarmTracker>>& newPeriodicAlarmTrackers,
std::unordered_map<int, std::vector<int>>& conditionToMetricMap,
std::unordered_map<int, std::vector<int>>& trackerToMetricMap,
std::unordered_map<int, std::vector<int>>& trackerToConditionMap,
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
index 8fc039a7d6b3..4474df4346cf 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.cpp
@@ -814,6 +814,35 @@ optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata(
pullerManager, eventActivationMap, eventDeactivationMap)};
}
+optional<sp<AnomalyTracker>> createAnomalyTracker(
+ const Alert& alert, const sp<AlarmMonitor>& anomalyAlarmMonitor,
+ const unordered_map<int64_t, int>& metricProducerMap,
+ vector<sp<MetricProducer>>& allMetricProducers) {
+ const auto& itr = metricProducerMap.find(alert.metric_id());
+ if (itr == metricProducerMap.end()) {
+ ALOGW("alert \"%lld\" has unknown metric id: \"%lld\"", (long long)alert.id(),
+ (long long)alert.metric_id());
+ return nullopt;
+ }
+ if (!alert.has_trigger_if_sum_gt()) {
+ ALOGW("invalid alert: missing threshold");
+ return nullopt;
+ }
+ if (alert.trigger_if_sum_gt() < 0 || alert.num_buckets() <= 0) {
+ ALOGW("invalid alert: threshold=%f num_buckets= %d", alert.trigger_if_sum_gt(),
+ alert.num_buckets());
+ return nullopt;
+ }
+ const int metricIndex = itr->second;
+ sp<MetricProducer> metric = allMetricProducers[metricIndex];
+ sp<AnomalyTracker> anomalyTracker = metric->addAnomalyTracker(alert, anomalyAlarmMonitor);
+ if (anomalyTracker == nullptr) {
+ // The ALOGW for this invalid alert was already displayed in addAnomalyTracker().
+ return nullopt;
+ }
+ return {anomalyTracker};
+}
+
bool initAtomMatchingTrackers(const StatsdConfig& config, const sp<UidMap>& uidMap,
unordered_map<int64_t, int>& atomMatchingTrackerMap,
vector<sp<AtomMatchingTracker>>& allAtomMatchingTrackers,
@@ -1079,49 +1108,17 @@ bool initAlerts(const StatsdConfig& config, const unordered_map<int64_t, int>& m
vector<sp<AnomalyTracker>>& allAnomalyTrackers) {
for (int i = 0; i < config.alert_size(); i++) {
const Alert& alert = config.alert(i);
- const auto& itr = metricProducerMap.find(alert.metric_id());
- if (itr == metricProducerMap.end()) {
- ALOGW("alert \"%lld\" has unknown metric id: \"%lld\"", (long long)alert.id(),
- (long long)alert.metric_id());
- return false;
- }
- if (!alert.has_trigger_if_sum_gt()) {
- ALOGW("invalid alert: missing threshold");
- return false;
- }
- if (alert.trigger_if_sum_gt() < 0 || alert.num_buckets() <= 0) {
- ALOGW("invalid alert: threshold=%f num_buckets= %d", alert.trigger_if_sum_gt(),
- alert.num_buckets());
- return false;
- }
- const int metricIndex = itr->second;
- sp<MetricProducer> metric = allMetricProducers[metricIndex];
- sp<AnomalyTracker> anomalyTracker = metric->addAnomalyTracker(alert, anomalyAlarmMonitor);
- if (anomalyTracker == nullptr) {
- // The ALOGW for this invalid alert was already displayed in addAnomalyTracker().
- return false;
- }
alertTrackerMap.insert(std::make_pair(alert.id(), allAnomalyTrackers.size()));
- allAnomalyTrackers.push_back(anomalyTracker);
- }
- for (int i = 0; i < config.subscription_size(); ++i) {
- const Subscription& subscription = config.subscription(i);
- if (subscription.rule_type() != Subscription::ALERT) {
- continue;
- }
- if (subscription.subscriber_information_case() ==
- Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
- ALOGW("subscription \"%lld\" has no subscriber info.\"", (long long)subscription.id());
- return false;
- }
- const auto& itr = alertTrackerMap.find(subscription.rule_id());
- if (itr == alertTrackerMap.end()) {
- ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
- (long long)subscription.id(), (long long)subscription.rule_id());
+ optional<sp<AnomalyTracker>> anomalyTracker = createAnomalyTracker(
+ alert, anomalyAlarmMonitor, metricProducerMap, allMetricProducers);
+ if (!anomalyTracker) {
return false;
}
- const int anomalyTrackerIndex = itr->second;
- allAnomalyTrackers[anomalyTrackerIndex]->addSubscription(subscription);
+ allAnomalyTrackers.push_back(anomalyTracker.value());
+ }
+ if (!initSubscribersForSubscriptionType(config, Subscription::ALERT, alertTrackerMap,
+ allAnomalyTrackers)) {
+ return false;
}
return true;
}
@@ -1146,24 +1143,9 @@ bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
allAlarmTrackers.push_back(
new AlarmTracker(startMillis, currentTimeMillis, alarm, key, periodicAlarmMonitor));
}
- for (int i = 0; i < config.subscription_size(); ++i) {
- const Subscription& subscription = config.subscription(i);
- if (subscription.rule_type() != Subscription::ALARM) {
- continue;
- }
- if (subscription.subscriber_information_case() ==
- Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
- ALOGW("subscription \"%lld\" has no subscriber info.\"", (long long)subscription.id());
- return false;
- }
- const auto& itr = alarmTrackerMap.find(subscription.rule_id());
- if (itr == alarmTrackerMap.end()) {
- ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
- (long long)subscription.id(), (long long)subscription.rule_id());
- return false;
- }
- const int trackerIndex = itr->second;
- allAlarmTrackers[trackerIndex]->addSubscription(subscription);
+ if (!initSubscribersForSubscriptionType(config, Subscription::ALARM, alarmTrackerMap,
+ allAlarmTrackers)) {
+ return false;
}
return true;
}
diff --git a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
index e4585cd578f8..84e1e4e04339 100644
--- a/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
+++ b/cmds/statsd/src/metrics/parsing_utils/metrics_manager_util.h
@@ -188,6 +188,41 @@ optional<sp<MetricProducer>> createGaugeMetricProducerAndUpdateMetadata(
std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
std::vector<int>& metricsWithActivation);
+// Creates an AnomalyTracker and adds it to the appropriate metric.
+// Returns an sp to the AnomalyTracker, or nullopt if there was an error.
+optional<sp<AnomalyTracker>> createAnomalyTracker(
+ const Alert& alert, const sp<AlarmMonitor>& anomalyAlarmMonitor,
+ const std::unordered_map<int64_t, int>& metricProducerMap,
+ std::vector<sp<MetricProducer>>& allMetricProducers);
+
+// Templated function for adding subscriptions to alarms or alerts. Returns true if successful.
+template <typename T>
+bool initSubscribersForSubscriptionType(const StatsdConfig& config,
+ const Subscription_RuleType ruleType,
+ const std::unordered_map<int64_t, int>& ruleMap,
+ std::vector<T>& allRules) {
+ for (int i = 0; i < config.subscription_size(); ++i) {
+ const Subscription& subscription = config.subscription(i);
+ if (subscription.rule_type() != ruleType) {
+ continue;
+ }
+ if (subscription.subscriber_information_case() ==
+ Subscription::SubscriberInformationCase::SUBSCRIBER_INFORMATION_NOT_SET) {
+ ALOGW("subscription \"%lld\" has no subscriber info.\"", (long long)subscription.id());
+ return false;
+ }
+ const auto& itr = ruleMap.find(subscription.rule_id());
+ if (itr == ruleMap.end()) {
+ ALOGW("subscription \"%lld\" has unknown rule id: \"%lld\"",
+ (long long)subscription.id(), (long long)subscription.rule_id());
+ return false;
+ }
+ const int ruleIndex = itr->second;
+ allRules[ruleIndex]->addSubscription(subscription);
+ }
+ return true;
+}
+
// Helper functions for MetricsManager to initialize from StatsdConfig.
// *Note*: only initStatsdConfig() should be called from outside.
// All other functions are intermediate
@@ -271,6 +306,12 @@ bool initMetrics(
std::unordered_map<int, std::vector<int>>& deactivationAtomTrackerToMetricMap,
std::vector<int>& metricsWithActivation);
+// Initialize alarms
+// Is called both on initialize new configs and config updates since alarms do not have any state.
+bool initAlarms(const StatsdConfig& config, const ConfigKey& key,
+ const sp<AlarmMonitor>& periodicAlarmMonitor, const int64_t timeBaseNs,
+ const int64_t currentTimeNs, std::vector<sp<AlarmTracker>>& allAlarmTrackers);
+
// Initialize MetricsManager from StatsdConfig.
// Parameters are the members of MetricsManager. See MetricsManager for declaration.
bool initStatsdConfig(const ConfigKey& key, const StatsdConfig& config, const sp<UidMap>& uidMap,
diff --git a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
index 4fa9bf6ffc01..66bab4ea70da 100644
--- a/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
+++ b/cmds/statsd/tests/metrics/parsing_utils/config_update_utils_test.cpp
@@ -52,11 +52,15 @@ namespace statsd {
namespace {
ConfigKey key(123, 456);
-const int64_t timeBaseNs = 1000;
+const int64_t timeBaseNs = 1000 * NS_PER_SEC;
+
sp<UidMap> uidMap = new UidMap();
sp<StatsPullerManager> pullerManager = new StatsPullerManager();
sp<AlarmMonitor> anomalyAlarmMonitor;
-sp<AlarmMonitor> periodicAlarmMonitor;
+sp<AlarmMonitor> periodicAlarmMonitor = new AlarmMonitor(
+ /*minDiffToUpdateRegisteredAlarmTimeSec=*/0,
+ [](const shared_ptr<IStatsCompanionService>&, int64_t) {},
+ [](const shared_ptr<IStatsCompanionService>&) {});
set<int> allTagIds;
vector<sp<AtomMatchingTracker>> oldAtomMatchingTrackers;
unordered_map<int64_t, int> oldAtomMatchingTrackerMap;
@@ -65,13 +69,13 @@ unordered_map<int64_t, int> oldConditionTrackerMap;
vector<sp<MetricProducer>> oldMetricProducers;
unordered_map<int64_t, int> oldMetricProducerMap;
std::vector<sp<AnomalyTracker>> oldAnomalyTrackers;
+unordered_map<int64_t, int> oldAlertTrackerMap;
std::vector<sp<AlarmTracker>> oldAlarmTrackers;
unordered_map<int, std::vector<int>> tmpConditionToMetricMap;
unordered_map<int, std::vector<int>> tmpTrackerToMetricMap;
unordered_map<int, std::vector<int>> tmpTrackerToConditionMap;
unordered_map<int, std::vector<int>> tmpActivationAtomTrackerToMetricMap;
unordered_map<int, std::vector<int>> tmpDeactivationAtomTrackerToMetricMap;
-unordered_map<int64_t, int> alertTrackerMap;
vector<int> metricsWithActivation;
map<int64_t, uint64_t> oldStateHashes;
std::set<int64_t> noReportMetricIds;
@@ -96,7 +100,7 @@ public:
tmpTrackerToConditionMap.clear();
tmpActivationAtomTrackerToMetricMap.clear();
tmpDeactivationAtomTrackerToMetricMap.clear();
- alertTrackerMap.clear();
+ oldAlertTrackerMap.clear();
metricsWithActivation.clear();
oldStateHashes.clear();
noReportMetricIds.clear();
@@ -111,7 +115,7 @@ bool initConfig(const StatsdConfig& config) {
oldConditionTrackers, oldConditionTrackerMap, oldMetricProducers, oldMetricProducerMap,
oldAnomalyTrackers, oldAlarmTrackers, tmpConditionToMetricMap, tmpTrackerToMetricMap,
tmpTrackerToConditionMap, tmpActivationAtomTrackerToMetricMap,
- tmpDeactivationAtomTrackerToMetricMap, alertTrackerMap, metricsWithActivation,
+ tmpDeactivationAtomTrackerToMetricMap, oldAlertTrackerMap, metricsWithActivation,
oldStateHashes, noReportMetricIds);
}
@@ -188,6 +192,32 @@ ValueMetric createValueMetric(string name, const AtomMatcher& what, optional<int
}
return metric;
}
+
+Alert createAlert(string name, int64_t metricId, int buckets, int64_t triggerSum) {
+ Alert alert;
+ alert.set_id(StringToId(name));
+ alert.set_metric_id(metricId);
+ alert.set_num_buckets(buckets);
+ alert.set_trigger_if_sum_gt(triggerSum);
+ return alert;
+}
+
+Subscription createSubscription(string name, Subscription_RuleType type, int64_t ruleId) {
+ Subscription subscription;
+ subscription.set_id(StringToId(name));
+ subscription.set_rule_type(type);
+ subscription.set_rule_id(ruleId);
+ subscription.mutable_broadcast_subscriber_details();
+ return subscription;
+}
+
+Alarm createAlarm(string name, int64_t offsetMillis, int64_t periodMillis) {
+ Alarm alarm;
+ alarm.set_id(StringToId(name));
+ alarm.set_offset_millis(offsetMillis);
+ alarm.set_period_millis(periodMillis);
+ return alarm;
+}
} // anonymous namespace
TEST_F(ConfigUpdateTest, TestSimpleMatcherPreserve) {
@@ -3243,6 +3273,305 @@ TEST_F(ConfigUpdateTest, TestUpdateMetricsMultipleTypes) {
// Only reference to the old wizard should be the one in the test.
EXPECT_EQ(oldConditionWizard->getStrongCount(), 1);
}
+
+TEST_F(ConfigUpdateTest, TestAlertPreserve) {
+ StatsdConfig config;
+ AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+ *config.add_atom_matcher() = whatMatcher;
+
+ *config.add_count_metric() = createCountMetric("VALUE1", whatMatcher.id(), nullopt, {});
+
+ Alert alert = createAlert("Alert1", config.count_metric(0).id(), 1, 1);
+ *config.add_alert() = alert;
+ EXPECT_TRUE(initConfig(config));
+
+ UpdateStatus updateStatus = UPDATE_UNKNOWN;
+ EXPECT_TRUE(determineAlertUpdateStatus(alert, oldAlertTrackerMap, oldAnomalyTrackers,
+ /*replacedMetrics*/ {}, updateStatus));
+ EXPECT_EQ(updateStatus, UPDATE_PRESERVE);
+}
+
+TEST_F(ConfigUpdateTest, TestAlertMetricChanged) {
+ StatsdConfig config;
+ AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+ *config.add_atom_matcher() = whatMatcher;
+
+ CountMetric metric = createCountMetric("VALUE1", whatMatcher.id(), nullopt, {});
+ *config.add_count_metric() = metric;
+
+ Alert alert = createAlert("Alert1", config.count_metric(0).id(), 1, 1);
+ *config.add_alert() = alert;
+ EXPECT_TRUE(initConfig(config));
+
+ UpdateStatus updateStatus = UPDATE_UNKNOWN;
+ EXPECT_TRUE(determineAlertUpdateStatus(alert, oldAlertTrackerMap, oldAnomalyTrackers,
+ /*replacedMetrics*/ {metric.id()}, updateStatus));
+ EXPECT_EQ(updateStatus, UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestAlertDefinitionChanged) {
+ StatsdConfig config;
+ AtomMatcher whatMatcher = CreateScreenBrightnessChangedAtomMatcher();
+ *config.add_atom_matcher() = whatMatcher;
+
+ *config.add_count_metric() = createCountMetric("VALUE1", whatMatcher.id(), nullopt, {});
+
+ Alert alert = createAlert("Alert1", config.count_metric(0).id(), 1, 1);
+ *config.add_alert() = alert;
+ EXPECT_TRUE(initConfig(config));
+
+ alert.set_num_buckets(2);
+
+ UpdateStatus updateStatus = UPDATE_UNKNOWN;
+ EXPECT_TRUE(determineAlertUpdateStatus(alert, oldAlertTrackerMap, oldAnomalyTrackers,
+ /*replacedMetrics*/ {}, updateStatus));
+ EXPECT_EQ(updateStatus, UPDATE_REPLACE);
+}
+
+TEST_F(ConfigUpdateTest, TestUpdateAlerts) {
+ StatsdConfig config;
+ // Add atom matchers/predicates/metrics. These are mostly needed for initStatsdConfig
+ *config.add_atom_matcher() = CreateScreenTurnedOnAtomMatcher();
+ *config.add_atom_matcher() = CreateScreenTurnedOffAtomMatcher();
+ *config.add_predicate() = CreateScreenIsOnPredicate();
+
+ CountMetric countMetric = createCountMetric("COUNT1", config.atom_matcher(0).id(), nullopt, {});
+ int64_t countMetricId = countMetric.id();
+ *config.add_count_metric() = countMetric;
+
+ DurationMetric durationMetric =
+ createDurationMetric("DURATION1", config.predicate(0).id(), nullopt, {});
+ int64_t durationMetricId = durationMetric.id();
+ *config.add_duration_metric() = durationMetric;
+
+ // Add alerts.
+ // Preserved.
+ Alert alert1 = createAlert("Alert1", durationMetricId, /*buckets*/ 1, /*triggerSum*/ 5000);
+ int64_t alert1Id = alert1.id();
+ *config.add_alert() = alert1;
+
+ // Replaced.
+ Alert alert2 = createAlert("Alert2", countMetricId, /*buckets*/ 1, /*triggerSum*/ 2);
+ int64_t alert2Id = alert2.id();
+ *config.add_alert() = alert2;
+
+ // Replaced.
+ Alert alert3 = createAlert("Alert3", durationMetricId, /*buckets*/ 3, /*triggerSum*/ 5000);
+ int64_t alert3Id = alert3.id();
+ *config.add_alert() = alert3;
+
+ // Add Subscriptions.
+ Subscription subscription1 = createSubscription("S1", Subscription::ALERT, alert1Id);
+ *config.add_subscription() = subscription1;
+ Subscription subscription2 = createSubscription("S2", Subscription::ALERT, alert1Id);
+ *config.add_subscription() = subscription2;
+ Subscription subscription3 = createSubscription("S3", Subscription::ALERT, alert2Id);
+ *config.add_subscription() = subscription3;
+
+ EXPECT_TRUE(initConfig(config));
+
+ // Add a duration tracker to the duration metric to ensure durationTrackers are updated
+ // with the proper anomalyTrackers.
+ unique_ptr<LogEvent> event = CreateScreenStateChangedEvent(
+ timeBaseNs + 1, android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+ oldMetricProducers[1]->onMatchedLogEvent(0, *event.get());
+
+ // Change the count metric. Causes alert2 to be replaced.
+ config.mutable_count_metric(0)->set_bucket(ONE_DAY);
+ // Change num buckets on alert3, causing replacement.
+ alert3.set_num_buckets(5);
+
+ // New alert.
+ Alert alert4 = createAlert("Alert4", durationMetricId, /*buckets*/ 3, /*triggerSum*/ 10000);
+ int64_t alert4Id = alert4.id();
+
+ // Move subscription2 to be on alert2 and make a new subscription.
+ subscription2.set_rule_id(alert2Id);
+ Subscription subscription4 = createSubscription("S4", Subscription::ALERT, alert2Id);
+
+ // Create the new config. Modify the old one to avoid adding the matchers/predicates.
+ // Add alerts in different order so the map is changed.
+ config.clear_alert();
+ *config.add_alert() = alert4;
+ const int alert4Index = 0;
+ *config.add_alert() = alert3;
+ const int alert3Index = 1;
+ *config.add_alert() = alert1;
+ const int alert1Index = 2;
+ *config.add_alert() = alert2;
+ const int alert2Index = 3;
+
+ // Subscription3 is removed.
+ config.clear_subscription();
+ *config.add_subscription() = subscription4;
+ *config.add_subscription() = subscription2;
+ *config.add_subscription() = subscription1;
+
+ // Output data structures from update metrics. Don't care about the outputs besides
+ // replacedMetrics, but need to do this so that the metrics clear their anomaly trackers.
+ unordered_map<int64_t, int> newMetricProducerMap;
+ vector<sp<MetricProducer>> newMetricProducers;
+ unordered_map<int, vector<int>> conditionToMetricMap;
+ unordered_map<int, vector<int>> trackerToMetricMap;
+ set<int64_t> noReportMetricIds;
+ unordered_map<int, vector<int>> activationAtomTrackerToMetricMap;
+ unordered_map<int, vector<int>> deactivationAtomTrackerToMetricMap;
+ vector<int> metricsWithActivation;
+ set<int64_t> replacedMetrics;
+ EXPECT_TRUE(updateMetrics(
+ key, config, /*timeBaseNs=*/123, /*currentTimeNs=*/12345, new StatsPullerManager(),
+ oldAtomMatchingTrackerMap, oldAtomMatchingTrackerMap, /*replacedMatchers*/ {},
+ oldAtomMatchingTrackers, oldConditionTrackerMap, /*replacedConditions=*/{},
+ oldConditionTrackers, {ConditionState::kUnknown}, /*stateAtomIdMap*/ {},
+ /*allStateGroupMaps=*/{},
+ /*replacedStates=*/{}, oldMetricProducerMap, oldMetricProducers, newMetricProducerMap,
+ newMetricProducers, conditionToMetricMap, trackerToMetricMap, noReportMetricIds,
+ activationAtomTrackerToMetricMap, deactivationAtomTrackerToMetricMap,
+ metricsWithActivation, replacedMetrics));
+
+ EXPECT_EQ(replacedMetrics, set<int64_t>({countMetricId}));
+
+ unordered_map<int64_t, int> newAlertTrackerMap;
+ vector<sp<AnomalyTracker>> newAnomalyTrackers;
+ EXPECT_TRUE(updateAlerts(config, newMetricProducerMap, replacedMetrics, oldAlertTrackerMap,
+ oldAnomalyTrackers, anomalyAlarmMonitor, newMetricProducers,
+ newAlertTrackerMap, newAnomalyTrackers));
+
+ unordered_map<int64_t, int> expectedAlertMap = {
+ {alert1Id, alert1Index},
+ {alert2Id, alert2Index},
+ {alert3Id, alert3Index},
+ {alert4Id, alert4Index},
+ };
+ EXPECT_THAT(newAlertTrackerMap, ContainerEq(expectedAlertMap));
+
+ // Make sure preserved alerts are the same.
+ ASSERT_EQ(newAnomalyTrackers.size(), 4);
+ EXPECT_EQ(oldAnomalyTrackers[oldAlertTrackerMap.at(alert1Id)],
+ newAnomalyTrackers[newAlertTrackerMap.at(alert1Id)]);
+
+ // Make sure replaced alerts are different.
+ EXPECT_NE(oldAnomalyTrackers[oldAlertTrackerMap.at(alert2Id)],
+ newAnomalyTrackers[newAlertTrackerMap.at(alert2Id)]);
+ EXPECT_NE(oldAnomalyTrackers[oldAlertTrackerMap.at(alert3Id)],
+ newAnomalyTrackers[newAlertTrackerMap.at(alert3Id)]);
+
+ // Verify the alerts have the correct anomaly trackers.
+ ASSERT_EQ(newMetricProducers.size(), 2);
+ EXPECT_THAT(newMetricProducers[0]->mAnomalyTrackers,
+ UnorderedElementsAre(newAnomalyTrackers[alert2Index]));
+ // For durationMetric, make sure the duration trackers get the updated anomalyTrackers.
+ DurationMetricProducer* durationProducer =
+ static_cast<DurationMetricProducer*>(newMetricProducers[1].get());
+ EXPECT_THAT(
+ durationProducer->mAnomalyTrackers,
+ UnorderedElementsAre(newAnomalyTrackers[alert1Index], newAnomalyTrackers[alert3Index],
+ newAnomalyTrackers[alert4Index]));
+ ASSERT_EQ(durationProducer->mCurrentSlicedDurationTrackerMap.size(), 1);
+ for (const auto& durationTrackerIt : durationProducer->mCurrentSlicedDurationTrackerMap) {
+ EXPECT_EQ(durationTrackerIt.second->mAnomalyTrackers, durationProducer->mAnomalyTrackers);
+ }
+
+ // Verify alerts have the correct subscriptions. Use subscription id as proxy for equivalency.
+ vector<int64_t> alert1Subscriptions;
+ for (const Subscription& subscription : newAnomalyTrackers[alert1Index]->mSubscriptions) {
+ alert1Subscriptions.push_back(subscription.id());
+ }
+ EXPECT_THAT(alert1Subscriptions, UnorderedElementsAre(subscription1.id()));
+ vector<int64_t> alert2Subscriptions;
+ for (const Subscription& subscription : newAnomalyTrackers[alert2Index]->mSubscriptions) {
+ alert2Subscriptions.push_back(subscription.id());
+ }
+ EXPECT_THAT(alert2Subscriptions, UnorderedElementsAre(subscription2.id(), subscription4.id()));
+ EXPECT_THAT(newAnomalyTrackers[alert3Index]->mSubscriptions, IsEmpty());
+ EXPECT_THAT(newAnomalyTrackers[alert4Index]->mSubscriptions, IsEmpty());
+}
+
+TEST_F(ConfigUpdateTest, TestUpdateAlarms) {
+ StatsdConfig config;
+ // Add alarms.
+ Alarm alarm1 = createAlarm("Alarm1", /*offset*/ 1 * MS_PER_SEC, /*period*/ 50 * MS_PER_SEC);
+ int64_t alarm1Id = alarm1.id();
+ *config.add_alarm() = alarm1;
+
+ Alarm alarm2 = createAlarm("Alarm2", /*offset*/ 1 * MS_PER_SEC, /*period*/ 2000 * MS_PER_SEC);
+ int64_t alarm2Id = alarm2.id();
+ *config.add_alarm() = alarm2;
+
+ Alarm alarm3 = createAlarm("Alarm3", /*offset*/ 10 * MS_PER_SEC, /*period*/ 5000 * MS_PER_SEC);
+ int64_t alarm3Id = alarm3.id();
+ *config.add_alarm() = alarm3;
+
+ // Add Subscriptions.
+ Subscription subscription1 = createSubscription("S1", Subscription::ALARM, alarm1Id);
+ *config.add_subscription() = subscription1;
+ Subscription subscription2 = createSubscription("S2", Subscription::ALARM, alarm1Id);
+ *config.add_subscription() = subscription2;
+ Subscription subscription3 = createSubscription("S3", Subscription::ALARM, alarm2Id);
+ *config.add_subscription() = subscription3;
+
+ EXPECT_TRUE(initConfig(config));
+
+ ASSERT_EQ(oldAlarmTrackers.size(), 3);
+ // Config is created at statsd start time, so just add the offsets.
+ EXPECT_EQ(oldAlarmTrackers[0]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 1);
+ EXPECT_EQ(oldAlarmTrackers[1]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 1);
+ EXPECT_EQ(oldAlarmTrackers[2]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 10);
+
+ // Change alarm2/alarm3.
+ config.mutable_alarm(1)->set_offset_millis(5 * MS_PER_SEC);
+ config.mutable_alarm(2)->set_period_millis(10000 * MS_PER_SEC);
+
+ // Move subscription2 to be on alarm2 and make a new subscription.
+ config.mutable_subscription(1)->set_rule_id(alarm2Id);
+ Subscription subscription4 = createSubscription("S4", Subscription::ALARM, alarm1Id);
+ *config.add_subscription() = subscription4;
+
+ // Update time is 2 seconds after the base time.
+ int64_t currentTimeNs = timeBaseNs + 2 * NS_PER_SEC;
+ vector<sp<AlarmTracker>> newAlarmTrackers;
+ EXPECT_TRUE(initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
+ newAlarmTrackers));
+
+ ASSERT_EQ(newAlarmTrackers.size(), 3);
+ // Config is updated 2 seconds after statsd start
+ // The offset has passed for alarm1, but not for alarms 2/3.
+ EXPECT_EQ(newAlarmTrackers[0]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 1 + 50);
+ EXPECT_EQ(newAlarmTrackers[1]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 5);
+ EXPECT_EQ(newAlarmTrackers[2]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 10);
+
+ // Verify alarms have the correct subscriptions. Use subscription id as proxy for equivalency.
+ vector<int64_t> alarm1Subscriptions;
+ for (const Subscription& subscription : newAlarmTrackers[0]->mSubscriptions) {
+ alarm1Subscriptions.push_back(subscription.id());
+ }
+ EXPECT_THAT(alarm1Subscriptions, UnorderedElementsAre(subscription1.id(), subscription4.id()));
+ vector<int64_t> alarm2Subscriptions;
+ for (const Subscription& subscription : newAlarmTrackers[1]->mSubscriptions) {
+ alarm2Subscriptions.push_back(subscription.id());
+ }
+ EXPECT_THAT(alarm2Subscriptions, UnorderedElementsAre(subscription2.id(), subscription3.id()));
+ EXPECT_THAT(newAlarmTrackers[2]->mSubscriptions, IsEmpty());
+
+ // Verify the alarm monitor is updated accordingly once the old alarms are removed.
+ // Alarm2 fires the earliest.
+ oldAlarmTrackers.clear();
+ EXPECT_EQ(periodicAlarmMonitor->getRegisteredAlarmTimeSec(), timeBaseNs / NS_PER_SEC + 5);
+
+ // Do another update 60 seconds after config creation time, after the offsets of each alarm.
+ currentTimeNs = timeBaseNs + 60 * NS_PER_SEC;
+ newAlarmTrackers.clear();
+ EXPECT_TRUE(initAlarms(config, key, periodicAlarmMonitor, timeBaseNs, currentTimeNs,
+ newAlarmTrackers));
+
+ ASSERT_EQ(newAlarmTrackers.size(), 3);
+ // Config is updated one minute after statsd start.
+ // Two periods have passed for alarm 1, one has passed for alarms2/3.
+ EXPECT_EQ(newAlarmTrackers[0]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 1 + 2 * 50);
+ EXPECT_EQ(newAlarmTrackers[1]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 5 + 2000);
+ EXPECT_EQ(newAlarmTrackers[2]->getAlarmTimestampSec(), timeBaseNs / NS_PER_SEC + 10 + 10000);
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
index 0d0a8960043e..9e2350b33018 100644
--- a/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
+++ b/cmds/statsd/tests/metrics/parsing_utils/metrics_manager_util_test.cpp
@@ -27,6 +27,7 @@
#include "src/condition/ConditionTracker.h"
#include "src/matchers/AtomMatchingTracker.h"
#include "src/metrics/CountMetricProducer.h"
+#include "src/metrics/DurationMetricProducer.h"
#include "src/metrics/GaugeMetricProducer.h"
#include "src/metrics/MetricProducer.h"
#include "src/metrics/ValueMetricProducer.h"
@@ -793,6 +794,93 @@ TEST(MetricsManagerTest, TestCreateConditionTrackerCombination) {
EXPECT_FALSE(tracker->IsSimpleCondition());
}
+TEST(MetricsManagerTest, TestCreateAnomalyTrackerInvalidMetric) {
+ Alert alert;
+ alert.set_id(123);
+ alert.set_metric_id(1);
+ alert.set_trigger_if_sum_gt(1);
+ alert.set_num_buckets(1);
+
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ vector<sp<MetricProducer>> metricProducers;
+ // Pass in empty metric producers, causing an error.
+ EXPECT_EQ(createAnomalyTracker(alert, anomalyAlarmMonitor, {}, metricProducers), nullopt);
+}
+
+TEST(MetricsManagerTest, TestCreateAnomalyTrackerNoThreshold) {
+ int64_t metricId = 1;
+ Alert alert;
+ alert.set_id(123);
+ alert.set_metric_id(metricId);
+ alert.set_num_buckets(1);
+
+ CountMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(ONE_MINUTE);
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ vector<sp<MetricProducer>> metricProducers({new CountMetricProducer(
+ kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard, 0x0123456789, 0, 0)});
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ EXPECT_EQ(createAnomalyTracker(alert, anomalyAlarmMonitor, {{1, 0}}, metricProducers), nullopt);
+}
+
+TEST(MetricsManagerTest, TestCreateAnomalyTrackerMissingBuckets) {
+ int64_t metricId = 1;
+ Alert alert;
+ alert.set_id(123);
+ alert.set_metric_id(metricId);
+ alert.set_trigger_if_sum_gt(1);
+
+ CountMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(ONE_MINUTE);
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ vector<sp<MetricProducer>> metricProducers({new CountMetricProducer(
+ kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard, 0x0123456789, 0, 0)});
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ EXPECT_EQ(createAnomalyTracker(alert, anomalyAlarmMonitor, {{1, 0}}, metricProducers), nullopt);
+}
+
+TEST(MetricsManagerTest, TestCreateAnomalyTrackerGood) {
+ int64_t metricId = 1;
+ Alert alert;
+ alert.set_id(123);
+ alert.set_metric_id(metricId);
+ alert.set_trigger_if_sum_gt(1);
+ alert.set_num_buckets(1);
+
+ CountMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(ONE_MINUTE);
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ vector<sp<MetricProducer>> metricProducers({new CountMetricProducer(
+ kConfigKey, metric, 0, {ConditionState::kUnknown}, wizard, 0x0123456789, 0, 0)});
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ EXPECT_NE(createAnomalyTracker(alert, anomalyAlarmMonitor, {{1, 0}}, metricProducers), nullopt);
+}
+
+TEST(MetricsManagerTest, TestCreateAnomalyTrackerDurationTooLong) {
+ int64_t metricId = 1;
+ Alert alert;
+ alert.set_id(123);
+ alert.set_metric_id(metricId);
+ // Impossible for alert to fire since the time is bigger than bucketSize * numBuckets
+ alert.set_trigger_if_sum_gt(MillisToNano(TimeUnitToBucketSizeInMillis(ONE_MINUTE)) + 1);
+ alert.set_num_buckets(1);
+
+ DurationMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(ONE_MINUTE);
+ metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+ FieldMatcher dimensions;
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ vector<sp<MetricProducer>> metricProducers({new DurationMetricProducer(
+ kConfigKey, metric, -1 /*no condition*/, {}, 1 /* start index */, 2 /* stop index */,
+ 3 /* stop_all index */, false /*nesting*/, wizard, 0x0123456789, dimensions, 0, 0)});
+ sp<AlarmMonitor> anomalyAlarmMonitor;
+ EXPECT_EQ(createAnomalyTracker(alert, anomalyAlarmMonitor, {{1, 0}}, metricProducers), nullopt);
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/core/api/current.txt b/core/api/current.txt
index 16a5f5e82f21..2cd01a6e60a2 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -5528,6 +5528,7 @@ package android.app {
field @Deprecated public static final String EXTRA_PEOPLE = "android.people";
field public static final String EXTRA_PEOPLE_LIST = "android.people.list";
field public static final String EXTRA_PICTURE = "android.picture";
+ field public static final String EXTRA_PICTURE_CONTENT_DESCRIPTION = "android.pictureContentDescription";
field public static final String EXTRA_PROGRESS = "android.progress";
field public static final String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
field public static final String EXTRA_PROGRESS_MAX = "android.progressMax";
@@ -5673,6 +5674,7 @@ package android.app {
method public android.app.Notification.BigPictureStyle bigLargeIcon(android.graphics.Bitmap);
method public android.app.Notification.BigPictureStyle bigLargeIcon(android.graphics.drawable.Icon);
method public android.app.Notification.BigPictureStyle bigPicture(android.graphics.Bitmap);
+ method @NonNull public android.app.Notification.BigPictureStyle bigPictureContentDescription(@Nullable CharSequence);
method public android.app.Notification.BigPictureStyle setBigContentTitle(CharSequence);
method public android.app.Notification.BigPictureStyle setSummaryText(CharSequence);
}
@@ -6138,6 +6140,7 @@ package android.app {
method public android.content.IntentSender getIntentSender();
method public static android.app.PendingIntent getService(android.content.Context, int, @NonNull android.content.Intent, int);
method @Deprecated public String getTargetPackage();
+ method public boolean isImmutable();
method @Nullable public static android.app.PendingIntent readPendingIntentOrNullFromParcel(@NonNull android.os.Parcel);
method public void send() throws android.app.PendingIntent.CanceledException;
method public void send(int) throws android.app.PendingIntent.CanceledException;
@@ -11718,10 +11721,9 @@ package android.content.pm {
method public long getFirstInstallTime();
method public android.graphics.drawable.Drawable getIcon(int);
method public CharSequence getLabel();
+ method public float getLoadingProgress();
method public String getName();
- method public float getProgress();
method public android.os.UserHandle getUser();
- method public boolean isLoading();
method public boolean isStartable();
}
@@ -11762,7 +11764,7 @@ package android.content.pm {
ctor public LauncherApps.Callback();
method public abstract void onPackageAdded(String, android.os.UserHandle);
method public abstract void onPackageChanged(String, android.os.UserHandle);
- method public void onPackageProgressChanged(@NonNull String, @NonNull android.os.UserHandle, float);
+ method public void onPackageLoadingProgressChanged(@NonNull String, @NonNull android.os.UserHandle, float);
method public abstract void onPackageRemoved(String, android.os.UserHandle);
method public abstract void onPackagesAvailable(String[], android.os.UserHandle, boolean);
method public void onPackagesSuspended(String[], android.os.UserHandle);
@@ -16410,6 +16412,7 @@ package android.graphics.fonts {
method public void getMetrics(@NonNull android.graphics.Paint, @Nullable android.graphics.Paint.FontMetrics);
method @NonNull public android.graphics.fonts.FontStyle getStyle();
method @IntRange(from=0) public int getTtcIndex();
+ method public boolean isSameSource(@NonNull android.graphics.fonts.Font);
}
public static final class Font.Builder {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index eea50be6da1d..2bb477e0837f 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -4363,11 +4363,11 @@ package android.media {
}
public class MediaPlayer implements android.media.AudioRouting android.media.VolumeAutomation {
- method @RequiresPermission("android.permission.BIND_IMS_SERVICE") public void setOnImsRxNoticeListener(@Nullable android.media.MediaPlayer.OnImsRxNoticeListener, @Nullable android.os.Handler);
+ method @RequiresPermission("android.permission.BIND_IMS_SERVICE") public void setOnRtpRxNoticeListener(@NonNull android.content.Context, @NonNull android.media.MediaPlayer.OnRtpRxNoticeListener, @Nullable android.os.Handler);
}
- public static interface MediaPlayer.OnImsRxNoticeListener {
- method public void onImsRxNotice(@NonNull android.media.MediaPlayer, @NonNull byte[]);
+ public static interface MediaPlayer.OnRtpRxNoticeListener {
+ method public void onRtpRxNotice(@NonNull android.media.MediaPlayer, int, @NonNull int[]);
}
public final class MediaRecorder.AudioSource {
@@ -5665,7 +5665,7 @@ package android.media.tv.tuner.frontend {
method @NonNull public android.media.tv.tuner.frontend.AtscFrontendSettings.Builder setModulation(int);
}
- public class DtmbFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
+ public final class DtmbFrontendCapabilities extends android.media.tv.tuner.frontend.FrontendCapabilities {
method public int getBandwidthCapability();
method public int getCodeRateCapability();
method public int getGuardIntervalCapability();
@@ -5674,7 +5674,7 @@ package android.media.tv.tuner.frontend {
method public int getTransmissionModeCapability();
}
- public class DtmbFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
+ public final class DtmbFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
method @NonNull public static android.media.tv.tuner.frontend.DtmbFrontendSettings.Builder builder();
method public int getBandwidth();
method public int getCodeRate();
@@ -5737,6 +5737,7 @@ package android.media.tv.tuner.frontend {
public class DvbcFrontendSettings extends android.media.tv.tuner.frontend.FrontendSettings {
method @NonNull public static android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder builder();
method public int getAnnex();
+ method public int getBandwidth();
method public long getInnerFec();
method public int getModulation();
method public int getOuterFec();
@@ -5748,6 +5749,11 @@ package android.media.tv.tuner.frontend {
field public static final int ANNEX_B = 2; // 0x2
field public static final int ANNEX_C = 4; // 0x4
field public static final int ANNEX_UNDEFINED = 0; // 0x0
+ field public static final int BANDWIDTH_5MHZ = 1; // 0x1
+ field public static final int BANDWIDTH_6MHZ = 2; // 0x2
+ field public static final int BANDWIDTH_7MHZ = 4; // 0x4
+ field public static final int BANDWIDTH_8MHZ = 8; // 0x8
+ field public static final int BANDWIDTH_UNDEFINED = 0; // 0x0
field public static final int MODULATION_AUTO = 1; // 0x1
field public static final int MODULATION_MOD_128QAM = 16; // 0x10
field public static final int MODULATION_MOD_16QAM = 2; // 0x2
@@ -5777,6 +5783,7 @@ package android.media.tv.tuner.frontend {
public static class DvbcFrontendSettings.Builder {
method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings build();
method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setAnnex(int);
+ method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setBandwidth(int);
method @IntRange(from=1) @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setFrequency(int);
method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setInnerFec(long);
method @NonNull public android.media.tv.tuner.frontend.DvbcFrontendSettings.Builder setModulation(int);
@@ -6070,17 +6077,17 @@ package android.media.tv.tuner.frontend {
method public int getBer();
method @NonNull public int[] getBers();
method @NonNull public int[] getCodeRates();
+ method @NonNull public int[] getExtendedModulations();
method public int getFreqOffset();
method public int getGuardInterval();
method public int getHierarchy();
method public long getInnerFec();
method @NonNull public int[] getInterleaving();
- method @NonNull public int[] getIsdbtSegment();
+ method @IntRange(from=0, to=255) @NonNull public int[] getIsdbtSegment();
method @NonNull public boolean[] getLayerErrors();
method public int getLnbVoltage();
method public int getMer();
method public int getModulation();
- method @NonNull public int[] getModulationsExt();
method public int getPer();
method public int getPerBer();
method public int getPlpId();
@@ -6089,7 +6096,7 @@ package android.media.tv.tuner.frontend {
method public int getSnr();
method public int getSpectralInversion();
method public int getSymbolRate();
- method public int getSystemId();
+ method @IntRange(from=0, to=65535) public int getSystemId();
method public int getTransmissionMode();
method @NonNull public int[] getTsDataRate();
method public int getUec();
@@ -8329,6 +8336,7 @@ package android.provider {
field public static final String NAMESPACE_PACKAGE_MANAGER_SERVICE = "package_manager_service";
field public static final String NAMESPACE_PERMISSIONS = "permissions";
field public static final String NAMESPACE_PRIVACY = "privacy";
+ field public static final String NAMESPACE_PROFCOLLECT_NATIVE_BOOT = "profcollect_native_boot";
field public static final String NAMESPACE_ROLLBACK = "rollback";
field public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot";
field public static final String NAMESPACE_RUNTIME = "runtime";
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index 4db55e7e07eb..a3fb06cbd92f 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -6,7 +6,8 @@ ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions():
BuilderSetStyle: android.net.IpSecTransform.Builder#buildTunnelModeTransform(java.net.InetAddress, android.net.IpSecManager.SecurityParameterIndex):
Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.net.IpSecTransform.Builder.buildTunnelModeTransform(java.net.InetAddress,android.net.IpSecManager.SecurityParameterIndex)
-ExecutorRegistration: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler):
+ExecutorRegistration: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler):
+ Registration methods should have overload that accepts delivery Executor: `setOnRtpRxNoticeListener`
GenericException: android.app.prediction.AppPredictor#finalize():
@@ -182,7 +183,8 @@ SamShouldBeLast: android.media.AudioRecordingMonitor#registerAudioRecordingCallb
SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
-SamShouldBeLast: android.media.MediaPlayer#setOnImsRxNoticeListener(android.media.MediaPlayer.OnImsRxNoticeListener, android.os.Handler):
+SamShouldBeLast: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler):
+ SAM-compatible parameters (such as parameter 2, "listener", in android.media.MediaPlayer.setOnRtpRxNoticeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index ec287fe10634..b2a039f4d1b3 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -1693,6 +1693,13 @@ public class ActivityManager {
@Deprecated
public int affiliatedTaskId;
+ /**
+ * Information of organized child tasks.
+ *
+ * @hide
+ */
+ public ArrayList<RecentTaskInfo> childrenTaskInfos = new ArrayList<>();
+
public RecentTaskInfo() {
}
@@ -1708,6 +1715,7 @@ public class ActivityManager {
public void readFromParcel(Parcel source) {
id = source.readInt();
persistentId = source.readInt();
+ childrenTaskInfos = source.readArrayList(RecentTaskInfo.class.getClassLoader());
super.readFromParcel(source);
}
@@ -1715,6 +1723,7 @@ public class ActivityManager {
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(id);
dest.writeInt(persistentId);
+ dest.writeList(childrenTaskInfos);
super.writeToParcel(dest, flags);
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index e20ef7f70954..c89f16e596b5 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -31,6 +31,7 @@ import android.compat.Compatibility;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -52,6 +53,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserManager;
+import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.LongSparseArray;
@@ -7590,8 +7592,9 @@ public class AppOpsManager {
collectNotedOpForSelf(op, proxiedAttributionTag);
} else if (collectionMode == COLLECT_SYNC
// Only collect app-ops when the proxy is trusted
- && mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
- myUid) == PackageManager.PERMISSION_GRANTED) {
+ && (mContext.checkPermission(Manifest.permission.UPDATE_APP_OPS_STATS, -1,
+ myUid) == PackageManager.PERMISSION_GRANTED
+ || isTrustedVoiceServiceProxy(mContext.getOpPackageName(), op))) {
collectNotedOpSync(op, proxiedAttributionTag);
}
}
@@ -7602,6 +7605,28 @@ public class AppOpsManager {
}
}
+ private boolean isTrustedVoiceServiceProxy(String packageName, int code) {
+ // This is a workaround for R QPR, new API change is not allowed. We only allow the current
+ // voice recognizer is also the voice interactor to noteproxy op.
+ if (code != OP_RECORD_AUDIO) {
+ return false;
+ }
+ final String voiceRecognitionComponent = Settings.Secure.getString(
+ mContext.getContentResolver(), Settings.Secure.VOICE_RECOGNITION_SERVICE);
+ final String voiceInteractionComponent = Settings.Secure.getString(
+ mContext.getContentResolver(), Settings.Secure.VOICE_INTERACTION_SERVICE);
+
+ final String voiceRecognitionServicePackageName =
+ voiceRecognitionComponent != null ? ComponentName.unflattenFromString(
+ voiceRecognitionComponent).getPackageName() : "";
+ final String voiceInteractionServicePackageName =
+ voiceInteractionComponent != null ? ComponentName.unflattenFromString(
+ voiceInteractionComponent).getPackageName() : "";
+
+ return Objects.equals(packageName, voiceRecognitionServicePackageName) && Objects.equals(
+ voiceRecognitionServicePackageName, voiceInteractionServicePackageName);
+ }
+
/**
* Do a quick check for whether an application might be able to perform an operation.
* This is <em>not</em> a security check; you must use {@link #noteOp(String, int, String,
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 879d4373f964..560b5be264d6 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -342,6 +342,7 @@ interface IActivityManager {
@UnsupportedAppUsage
void unregisterProcessObserver(in IProcessObserver observer);
boolean isIntentSenderTargetedToPackage(in IIntentSender sender);
+ boolean isIntentSenderImmutable(in IIntentSender sender);
@UnsupportedAppUsage
void updatePersistentConfiguration(in Configuration values);
void updatePersistentConfigurationWithAttribution(in Configuration values,
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index d798f22a6af9..a8ce73d9bd27 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -96,6 +96,8 @@ interface INotificationManager
NotificationChannelGroup getPopulatedNotificationChannelGroupForPackage(String pkg, int uid, String groupId, boolean includeDeleted);
void updateNotificationChannelGroupForPackage(String pkg, int uid, in NotificationChannelGroup group);
void updateNotificationChannelForPackage(String pkg, int uid, in NotificationChannel channel);
+ void unlockNotificationChannel(String pkg, int uid, String channelId);
+ void unlockAllNotificationChannels();
NotificationChannel getNotificationChannel(String callingPkg, int userId, String pkg, String channelId);
NotificationChannel getConversationNotificationChannel(String callingPkg, int userId, String pkg, String channelId, boolean returnParentIfNoConversationChannel, String conversationId);
void createConversationNotificationChannelForPackage(String pkg, int uid, in NotificationChannel parentChannel, String conversationId);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index a1abe3d8190b..8cafaa897ad8 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1147,6 +1147,14 @@ public class Notification implements Parcelable
public static final String EXTRA_PICTURE = "android.picture";
/**
+ * {@link #extras} key: this is a content description of the big picture supplied from
+ * {@link BigPictureStyle#bigPicture(Bitmap)}, supplied to
+ * {@link BigPictureStyle#bigPictureContentDescription(CharSequence)}.
+ */
+ public static final String EXTRA_PICTURE_CONTENT_DESCRIPTION =
+ "android.pictureContentDescription";
+
+ /**
* {@link #extras} key: An array of CharSequences to show in {@link InboxStyle} expanded
* notifications, each of which was supplied to {@link InboxStyle#addLine(CharSequence)}.
*/
@@ -6728,6 +6736,7 @@ public class Notification implements Parcelable
private Bitmap mPicture;
private Icon mBigLargeIcon;
private boolean mBigLargeIconSet = false;
+ private CharSequence mPictureContentDescription;
public BigPictureStyle() {
}
@@ -6758,6 +6767,16 @@ public class Notification implements Parcelable
}
/**
+ * Set the content description of the big picture.
+ */
+ @NonNull
+ public BigPictureStyle bigPictureContentDescription(
+ @Nullable CharSequence contentDescription) {
+ mPictureContentDescription = contentDescription;
+ return this;
+ }
+
+ /**
* @hide
*/
public Bitmap getBigPicture() {
@@ -6870,6 +6889,11 @@ public class Notification implements Parcelable
}
contentView.setImageViewBitmap(R.id.big_picture, mPicture);
+
+ if (mPictureContentDescription != null) {
+ contentView.setContentDescription(R.id.big_picture, mPictureContentDescription);
+ }
+
return contentView;
}
@@ -6882,6 +6906,10 @@ public class Notification implements Parcelable
if (mBigLargeIconSet) {
extras.putParcelable(EXTRA_LARGE_ICON_BIG, mBigLargeIcon);
}
+ if (mPictureContentDescription != null) {
+ extras.putCharSequence(EXTRA_PICTURE_CONTENT_DESCRIPTION,
+ mPictureContentDescription);
+ }
extras.putParcelable(EXTRA_PICTURE, mPicture);
}
@@ -6896,6 +6924,12 @@ public class Notification implements Parcelable
mBigLargeIconSet = true;
mBigLargeIcon = extras.getParcelable(EXTRA_LARGE_ICON_BIG);
}
+
+ if (extras.containsKey(EXTRA_PICTURE_CONTENT_DESCRIPTION)) {
+ mPictureContentDescription =
+ extras.getCharSequence(EXTRA_PICTURE_CONTENT_DESCRIPTION);
+ }
+
mPicture = extras.getParcelable(EXTRA_PICTURE);
}
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 21dfbbd6f15d..f76a75749480 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -1145,6 +1145,18 @@ public final class PendingIntent implements Parcelable {
}
/**
+ * Check if this PendingIntent is marked with {@link #FLAG_IMMUTABLE}.
+ */
+ public boolean isImmutable() {
+ try {
+ return ActivityManager.getService()
+ .isIntentSenderImmutable(mTarget);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* @hide
* Check whether this PendingIntent will launch an Activity.
*/
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index 45e9c49c5322..43b7722c0864 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -16,6 +16,8 @@
package android.app;
+import static android.app.ActivityTaskManager.INVALID_TASK_ID;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
@@ -204,6 +206,13 @@ public class TaskInfo {
*/
public ArrayList<IBinder> launchCookies = new ArrayList<>();
+ /**
+ * The identifier of the parent task that is created by organizer, otherwise
+ * {@link ActivityTaskManager#INVALID_TASK_ID}.
+ * @hide
+ */
+ public int parentTaskId;
+
TaskInfo() {
// Do nothing
}
@@ -253,6 +262,12 @@ public class TaskInfo {
launchCookies.add(cookie);
}
+ /** @hide */
+ @TestApi
+ public boolean hasParentTask() {
+ return parentTaskId != INVALID_TASK_ID;
+ }
+
/**
* Reads the TaskInfo from a parcel.
*/
@@ -283,6 +298,7 @@ public class TaskInfo {
source.readBinderList(launchCookies);
letterboxActivityBounds = source.readTypedObject(Rect.CREATOR);
positionInParent = source.readTypedObject(Point.CREATOR);
+ parentTaskId = source.readInt();
}
/**
@@ -316,6 +332,7 @@ public class TaskInfo {
dest.writeBinderList(launchCookies);
dest.writeTypedObject(letterboxActivityBounds, flags);
dest.writeTypedObject(positionInParent, flags);
+ dest.writeInt(parentTaskId);
}
@Override
@@ -338,6 +355,7 @@ public class TaskInfo {
+ " launchCookies" + launchCookies
+ " letterboxActivityBounds=" + letterboxActivityBounds
+ " positionInParent=" + positionInParent
+ + " parentTaskId: " + parentTaskId
+ "}";
}
}
diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java
index 05313592faa5..44a4b78e1afa 100644
--- a/core/java/android/app/backup/BackupManager.java
+++ b/core/java/android/app/backup/BackupManager.java
@@ -21,10 +21,14 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.app.compat.CompatChanges;
+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.Intent;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -435,6 +439,17 @@ public class BackupManager {
return false;
}
+
+ /**
+ * If this change is enabled, the {@code BACKUP} permission needed for
+ * {@code isBackupServiceActive()} will be enforced on the service end
+ * rather than client-side in {@link BackupManager}.
+ * @hide
+ */
+ @ChangeId
+ @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.R)
+ public static final long IS_BACKUP_SERVICE_ACTIVE_ENFORCE_PERMISSION_IN_SERVICE = 158482162;
+
/**
* Report whether the backup mechanism is currently active.
* When it is inactive, the device will not perform any backup operations, nor will it
@@ -445,8 +460,11 @@ public class BackupManager {
@SystemApi
@RequiresPermission(android.Manifest.permission.BACKUP)
public boolean isBackupServiceActive(UserHandle user) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
- "isBackupServiceActive");
+ if (!CompatChanges.isChangeEnabled(
+ IS_BACKUP_SERVICE_ACTIVE_ENFORCE_PERMISSION_IN_SERVICE)) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
+ "isBackupServiceActive");
+ }
checkServiceBinder();
if (sService != null) {
try {
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index c854abac291e..587e883edaf2 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -20,7 +20,6 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.XmlResourceParser;
-import android.os.Build;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.storage.StorageManager;
@@ -92,7 +91,7 @@ public class FullBackup {
/**
* @hide
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @UnsupportedAppUsage
static public native int backupToTar(String packageName, String domain,
String linkdomain, String rootpath, String path, FullBackupDataOutput output);
diff --git a/core/java/android/content/pm/IOnAppsChangedListener.aidl b/core/java/android/content/pm/IOnAppsChangedListener.aidl
index f24ed80983f8..830cbe0e0dd0 100644
--- a/core/java/android/content/pm/IOnAppsChangedListener.aidl
+++ b/core/java/android/content/pm/IOnAppsChangedListener.aidl
@@ -33,5 +33,5 @@ oneway interface IOnAppsChangedListener {
in Bundle launcherExtras);
void onPackagesUnsuspended(in UserHandle user, in String[] packageNames);
void onShortcutChanged(in UserHandle user, String packageName, in ParceledListSlice shortcuts);
- void onPackageProgressChanged(in UserHandle user, String packageName, float progress);
+ void onPackageLoadingProgressChanged(in UserHandle user, String packageName, float progress);
}
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
index ead80d022542..fd96e85db3de 100644
--- a/core/java/android/content/pm/LauncherActivityInfo.java
+++ b/core/java/android/content/pm/LauncherActivityInfo.java
@@ -91,16 +91,9 @@ public class LauncherActivityInfo {
}
/**
- * @return whether the package is still loading.
+ * @return Package loading progress, range between [0, 1].
*/
- public boolean isLoading() {
- return mInternal.getIncrementalStatesInfo().isLoading();
- }
-
- /**
- * @return Package loading progress
- */
- public float getProgress() {
+ public float getLoadingProgress() {
return mInternal.getIncrementalStatesInfo().getProgress();
}
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 2909d66d72ff..c964b4b9bb53 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -17,7 +17,6 @@
package android.content.pm;
import static android.Manifest.permission;
-import static android.app.PendingIntent.FLAG_IMMUTABLE;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
@@ -333,7 +332,7 @@ public class LauncherApps {
* @param user The UserHandle of the profile that generated the change.
* @param progress The new progress value, between [0, 1].
*/
- public void onPackageProgressChanged(@NonNull String packageName,
+ public void onPackageLoadingProgressChanged(@NonNull String packageName,
@NonNull UserHandle user, float progress) {}
}
@@ -1702,15 +1701,15 @@ public class LauncherApps {
}
}
- public void onPackageProgressChanged(UserHandle user, String packageName,
+ public void onPackageLoadingProgressChanged(UserHandle user, String packageName,
float progress) {
if (DEBUG) {
- Log.d(TAG, "onPackageProgressChanged " + user.getIdentifier() + ","
+ Log.d(TAG, "onPackageLoadingProgressChanged " + user.getIdentifier() + ","
+ packageName + "," + progress);
}
synchronized (LauncherApps.this) {
for (CallbackMessageHandler callback : mCallbacks) {
- callback.postOnPackageProgressChanged(user, packageName, progress);
+ callback.postOnPackageLoadingProgressChanged(user, packageName, progress);
}
}
}
@@ -1777,7 +1776,7 @@ public class LauncherApps {
mCallback.onShortcutsChanged(info.packageName, info.shortcuts, info.user);
break;
case MSG_LOADING_PROGRESS_CHANGED:
- mCallback.onPackageProgressChanged(info.packageName, info.user,
+ mCallback.onPackageLoadingProgressChanged(info.packageName, info.user,
info.mLoadingProgress);
break;
}
@@ -1847,7 +1846,7 @@ public class LauncherApps {
obtainMessage(MSG_SHORTCUT_CHANGED, info).sendToTarget();
}
- public void postOnPackageProgressChanged(UserHandle user, String packageName,
+ public void postOnPackageLoadingProgressChanged(UserHandle user, String packageName,
float progress) {
CallbackInfo info = new CallbackInfo();
info.packageName = packageName;
diff --git a/core/java/android/content/pm/OWNERS b/core/java/android/content/pm/OWNERS
new file mode 100644
index 000000000000..a16bb4ff3b1d
--- /dev/null
+++ b/core/java/android/content/pm/OWNERS
@@ -0,0 +1 @@
+per-file PackageParser.java = chiuwinson@google.com
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 596d39b50848..0fc9fad4d635 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1356,7 +1356,9 @@ public class PackageInstaller {
* Completely abandon this session, destroying all staged data and
* rendering it invalid. Abandoned sessions will be reported to
* {@link SessionCallback} listeners as failures. This is equivalent to
- * opening the session and calling {@link Session#abandon()}.
+ * {@link #abandonSession(int)}.
+ * <p>If the parent is abandoned, all children will also be abandoned. Any written data
+ * would be destroyed and the created {@link Session} information will be discarded.</p>
*/
public void abandon() {
try {
@@ -1419,7 +1421,8 @@ public class PackageInstaller {
* when this session is committed.
*
* <p>If the parent is staged or has rollback enabled, all children must have
- * the same properties.
+ * the same properties.</p>
+ * <p>If the parent is abandoned, all children will also be abandoned.</p>
*
* @param sessionId the session ID to add to this multi-package session.
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 118524d494de..1c90d234921e 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -141,8 +141,14 @@ import java.util.UUID;
* <li>All installations must contain a single base APK.
* </ul>
*
+ * @deprecated This class is mostly unused and no new changes should be added to it. Use
+ * {@link android.content.pm.parsing.ParsingPackageUtils} and related parsing v2 infrastructure in
+ * the core/services parsing subpackages. Or for a quick parse of a provided APK, use
+ * {@link PackageManager#getPackageArchiveInfo(String, int)}.
+ *
* @hide
*/
+@Deprecated
public class PackageParser {
public static final boolean DEBUG_JAR = false;
diff --git a/core/java/android/content/pm/parsing/OWNERS b/core/java/android/content/pm/parsing/OWNERS
new file mode 100644
index 000000000000..8049d5cb7fa2
--- /dev/null
+++ b/core/java/android/content/pm/parsing/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 36137
+
+chiuwinson@google.com
+patb@google.com
+toddke@google.com
diff --git a/core/java/android/content/rollback/IRollbackManager.aidl b/core/java/android/content/rollback/IRollbackManager.aidl
index cda0e9865054..c818e939035d 100644
--- a/core/java/android/content/rollback/IRollbackManager.aidl
+++ b/core/java/android/content/rollback/IRollbackManager.aidl
@@ -49,10 +49,6 @@ interface IRollbackManager {
// NOTE: This call is synchronous.
int notifyStagedSession(int sessionId);
- // Used by the staging manager to notify the RollbackManager of the apk
- // session for a staged session.
- void notifyStagedApkSession(int originalSessionId, int apkSessionId);
-
// For test purposes only.
void blockRollbackManager(long millis);
}
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index e65d7b5965d5..9f322fbad51d 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -419,6 +419,8 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
*
* @see com.android.server.locksettings.LockSettingsService
*
+ * TODO(b/171335732): should take userId
+ *
* @hide
*/
@RequiresPermission(MANAGE_BIOMETRIC)
@@ -426,7 +428,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
if (mService != null) {
try {
mGenerateChallengeCallback = callback;
- mService.generateChallenge(mToken, sensorId, mServiceReceiver,
+ mService.generateChallenge(mToken, sensorId, 0 /* userId */, mServiceReceiver,
mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -470,13 +472,16 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
/**
* Invalidates the current challenge.
*
+ * TODO(b/171335732): should take userId and challenge
+ *
* @hide
*/
@RequiresPermission(MANAGE_BIOMETRIC)
public void revokeChallenge(int sensorId) {
if (mService != null) {
try {
- mService.revokeChallenge(mToken, sensorId, mContext.getOpPackageName());
+ mService.revokeChallenge(mToken, sensorId, 0 /* userId */,
+ mContext.getOpPackageName(), 0 /* challenge */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index b85b6f7d8174..490c95bfe1bb 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -32,7 +32,7 @@ interface IFaceService {
List<FaceSensorPropertiesInternal> getSensorPropertiesInternal(String opPackageName);
// Authenticate the given sessionId with a face
- void authenticate(IBinder token, long operationId, int userid, IFaceServiceReceiver receiver,
+ void authenticate(IBinder token, long operationId, int userId, IFaceServiceReceiver receiver,
String opPackageName);
// Uses the face hardware to detect for the presence of a face, without giving details
@@ -83,10 +83,10 @@ interface IFaceService {
boolean isHardwareDetected(String opPackageName);
// Get a pre-enrollment authentication token
- void generateChallenge(IBinder token, int sensorId, IFaceServiceReceiver receiver, String opPackageName);
+ void generateChallenge(IBinder token, int sensorId, int userId, IFaceServiceReceiver receiver, String opPackageName);
// Finish an enrollment sequence and invalidate the authentication token
- void revokeChallenge(IBinder token, int sensorId, String opPackageName);
+ void revokeChallenge(IBinder token, int sensorId, int userId, String opPackageName, long challenge);
// Determine if a user has at least one enrolled face
boolean hasEnrolledFaces(int userId, String opPackageName);
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index d2c74e963689..4afe4b3d126b 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -766,6 +766,26 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
}
/**
+ * Checks if the specified user has enrollments in any of the specified sensors.
+ * @hide
+ */
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+ public boolean hasEnrolledTemplatesForAnySensor(int userId,
+ @NonNull List<FingerprintSensorPropertiesInternal> sensors) {
+ if (mService == null) {
+ Slog.w(TAG, "hasEnrolledTemplatesForAnySensor: no fingerprint service");
+ return false;
+ }
+
+ try {
+ return mService.hasEnrolledTemplatesForAnySensor(userId, sensors,
+ mContext.getOpPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
@@ -778,7 +798,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
try {
mService.setUdfpsOverlayController(controller);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw e.rethrowFromSystemServer();
}
}
@@ -795,7 +815,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
try {
mService.onPointerDown(sensorId, x, y, minor, major);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw e.rethrowFromSystemServer();
}
}
@@ -812,7 +832,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
try {
mService.onPointerUp(sensorId);
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw e.rethrowFromSystemServer();
}
}
@@ -885,9 +905,8 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
}
return mService.getSensorPropertiesInternal(mContext.getOpPackageName());
} catch (RemoteException e) {
- e.rethrowFromSystemServer();
+ throw e.rethrowFromSystemServer();
}
- return new ArrayList<>();
}
/**
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 547de9d3c86a..5b14ef796616 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -100,6 +100,9 @@ interface IFingerprintService {
// Determine if a user has at least one enrolled fingerprint
boolean hasEnrolledFingerprints(int userId, String opPackageName);
+ // Determine if a user has at least one enrolled fingerprint in any of the specified sensors
+ boolean hasEnrolledTemplatesForAnySensor(int userId, in List<FingerprintSensorPropertiesInternal> sensors, String opPackageName);
+
// Return the LockoutTracker status for the specified user
int getLockoutModeForUser(int userId);
diff --git a/core/java/android/hardware/usb/AccessoryFilter.java b/core/java/android/hardware/usb/AccessoryFilter.java
index 8345ff3f5342..98e8c92b09c6 100644
--- a/core/java/android/hardware/usb/AccessoryFilter.java
+++ b/core/java/android/hardware/usb/AccessoryFilter.java
@@ -102,7 +102,7 @@ public class AccessoryFilter {
public boolean matches(UsbAccessory acc) {
if (mManufacturer != null && !acc.getManufacturer().equals(mManufacturer)) return false;
if (mModel != null && !acc.getModel().equals(mModel)) return false;
- return !(mVersion != null && !acc.getVersion().equals(mVersion));
+ return !(mVersion != null && !mVersion.equals(acc.getVersion()));
}
/**
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index bb2357e24617..3d1755e9b017 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -213,8 +213,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
ic,
info,
moreArgs.argi1 == 1 /* restarting */,
- startInputToken,
- moreArgs.argi2 == 1 /* shouldPreRenderIme */);
+ startInputToken);
args.recycle();
moreArgs.recycle();
return;
@@ -340,14 +339,13 @@ class IInputMethodWrapper extends IInputMethod.Stub
@Override
public void startInput(IBinder startInputToken, IInputContext inputContext,
@InputConnectionInspector.MissingMethodFlags final int missingMethods,
- EditorInfo attribute, boolean restarting, boolean shouldPreRenderIme) {
+ EditorInfo attribute, boolean restarting) {
if (mCancellationGroup == null) {
Log.e(TAG, "startInput must be called after bindInput.");
mCancellationGroup = new CancellationGroup();
}
SomeArgs args = SomeArgs.obtain();
args.argi1 = restarting ? 1 : 0;
- args.argi2 = shouldPreRenderIme ? 1 : 0;
args.argi3 = missingMethods;
mCaller.executeOrSendMessage(mCaller.obtainMessageOOOOO(DO_START_INPUT, startInputToken,
inputContext, attribute, mCancellationGroup, args));
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index d290465816b6..44640c44332e 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -19,7 +19,6 @@ package android.inputmethodservice;
import static android.graphics.Color.TRANSPARENT;
import static android.inputmethodservice.InputMethodServiceProto.CANDIDATES_VIEW_STARTED;
import static android.inputmethodservice.InputMethodServiceProto.CANDIDATES_VISIBILITY;
-import static android.inputmethodservice.InputMethodServiceProto.CAN_PRE_RENDER;
import static android.inputmethodservice.InputMethodServiceProto.CONFIGURATION;
import static android.inputmethodservice.InputMethodServiceProto.DECOR_VIEW_VISIBLE;
import static android.inputmethodservice.InputMethodServiceProto.DECOR_VIEW_WAS_VISIBLE;
@@ -33,7 +32,6 @@ import static android.inputmethodservice.InputMethodServiceProto.INPUT_VIEW_STAR
import static android.inputmethodservice.InputMethodServiceProto.IN_SHOW_WINDOW;
import static android.inputmethodservice.InputMethodServiceProto.IS_FULLSCREEN;
import static android.inputmethodservice.InputMethodServiceProto.IS_INPUT_VIEW_SHOWN;
-import static android.inputmethodservice.InputMethodServiceProto.IS_PRE_RENDERED;
import static android.inputmethodservice.InputMethodServiceProto.InsetsProto.CONTENT_TOP_INSETS;
import static android.inputmethodservice.InputMethodServiceProto.InsetsProto.TOUCHABLE_INSETS;
import static android.inputmethodservice.InputMethodServiceProto.InsetsProto.TOUCHABLE_REGION;
@@ -48,6 +46,7 @@ import static android.inputmethodservice.InputMethodServiceProto.STATUS_ICON;
import static android.inputmethodservice.InputMethodServiceProto.TOKEN;
import static android.inputmethodservice.InputMethodServiceProto.VIEWS_CREATED;
import static android.inputmethodservice.InputMethodServiceProto.WINDOW_VISIBLE;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.WindowInsets.Type.navigationBars;
@@ -82,6 +81,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.ResultReceiver;
import android.os.SystemClock;
+import android.os.Trace;
import android.provider.Settings;
import android.text.InputType;
import android.text.Layout;
@@ -421,10 +421,6 @@ public class InputMethodService extends AbstractInputMethodService {
boolean mDecorViewVisible;
boolean mDecorViewWasVisible;
boolean mInShowWindow;
- // True if pre-rendering of IME views/window is supported.
- boolean mCanPreRender;
- // If IME is pre-rendered.
- boolean mIsPreRendered;
// IME window visibility.
// Use (mDecorViewVisible && mWindowVisible) to check if IME is visible to the user.
boolean mWindowVisible;
@@ -651,7 +647,9 @@ public class InputMethodService extends AbstractInputMethodService {
@Override
public void startInput(InputConnection ic, EditorInfo attribute) {
if (DEBUG) Log.v(TAG, "startInput(): editor=" + attribute);
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.startInput");
doStartInput(ic, attribute, false);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
/**
@@ -672,10 +670,8 @@ public class InputMethodService extends AbstractInputMethodService {
@Override
public final void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
@NonNull EditorInfo editorInfo, boolean restarting,
- @NonNull IBinder startInputToken, boolean shouldPreRenderIme) {
+ @NonNull IBinder startInputToken) {
mPrivOps.reportStartInput(startInputToken);
- mCanPreRender = shouldPreRenderIme;
- if (DEBUG) Log.v(TAG, "Will Pre-render IME: " + mCanPreRender);
if (restarting) {
restartInput(inputConnection, editorInfo);
@@ -712,22 +708,14 @@ public class InputMethodService extends AbstractInputMethodService {
+ " Use requestHideSelf(int) itself");
return;
}
- final boolean wasVisible = mIsPreRendered
- ? mDecorViewVisible && mWindowVisible : isInputViewShown();
+ final boolean wasVisible = isInputViewShown();
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.hideSoftInput");
+
applyVisibilityInInsetsConsumerIfNecessary(false /* setVisible */);
- if (mIsPreRendered) {
- if (DEBUG) {
- Log.v(TAG, "Making IME window invisible");
- }
- setImeWindowStatus(IME_ACTIVE | IME_INVISIBLE, mBackDisposition);
- onPreRenderedWindowVisibilityChanged(false /* setVisible */);
- } else {
- mShowInputFlags = 0;
- mShowInputRequested = false;
- doHideWindow();
- }
- final boolean isVisible = mIsPreRendered
- ? mDecorViewVisible && mWindowVisible : isInputViewShown();
+ mShowInputFlags = 0;
+ mShowInputRequested = false;
+ doHideWindow();
+ final boolean isVisible = isInputViewShown();
final boolean visibilityChanged = isVisible != wasVisible;
if (resultReceiver != null) {
resultReceiver.send(visibilityChanged
@@ -735,6 +723,7 @@ public class InputMethodService extends AbstractInputMethodService {
: (wasVisible ? InputMethodManager.RESULT_UNCHANGED_SHOWN
: InputMethodManager.RESULT_UNCHANGED_HIDDEN), null);
}
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
/**
@@ -766,23 +755,22 @@ public class InputMethodService extends AbstractInputMethodService {
+ " Use requestShowSelf(int) itself");
return;
}
- final boolean wasVisible = mIsPreRendered
- ? mDecorViewVisible && mWindowVisible : isInputViewShown();
+
+ if (Trace.isEnabled()) {
+ Binder.enableTracing();
+ } else {
+ Binder.disableTracing();
+ }
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.showSoftInput");
+ final boolean wasVisible = isInputViewShown();
if (dispatchOnShowInputRequested(flags, false)) {
- if (mIsPreRendered) {
- if (DEBUG) {
- Log.v(TAG, "Making IME window visible");
- }
- onPreRenderedWindowVisibilityChanged(true /* setVisible */);
- } else {
- showWindow(true);
- }
+
+ showWindow(true);
applyVisibilityInInsetsConsumerIfNecessary(true /* setVisible */);
}
// If user uses hard keyboard, IME button should always be shown.
setImeWindowStatus(mapToImeWindowStatus(), mBackDisposition);
- final boolean isVisible = mIsPreRendered
- ? mDecorViewVisible && mWindowVisible : isInputViewShown();
+ final boolean isVisible = isInputViewShown();
final boolean visibilityChanged = isVisible != wasVisible;
if (resultReceiver != null) {
resultReceiver.send(visibilityChanged
@@ -790,6 +778,7 @@ public class InputMethodService extends AbstractInputMethodService {
: (wasVisible ? InputMethodManager.RESULT_UNCHANGED_SHOWN
: InputMethodManager.RESULT_UNCHANGED_HIDDEN), null);
}
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
/**
@@ -1798,7 +1787,7 @@ public class InputMethodService extends AbstractInputMethodService {
* applied by {@link #updateInputViewShown()}.
*/
public boolean isInputViewShown() {
- return mCanPreRender ? mWindowVisible : mIsInputViewShown && mDecorViewVisible;
+ return mDecorViewVisible;
}
/**
@@ -2151,10 +2140,9 @@ public class InputMethodService extends AbstractInputMethodService {
mDecorViewWasVisible = mDecorViewVisible;
mInShowWindow = true;
- boolean isPreRenderedAndInvisible = mIsPreRendered && !mWindowVisible;
final int previousImeWindowStatus =
(mDecorViewVisible ? IME_ACTIVE : 0) | (isInputViewShown()
- ? (isPreRenderedAndInvisible ? IME_INVISIBLE : IME_VISIBLE) : 0);
+ ? (!mWindowVisible ? IME_INVISIBLE : IME_VISIBLE) : 0);
startViews(prepareWindow(showInput));
final int nextImeWindowStatus = mapToImeWindowStatus();
if (previousImeWindowStatus != nextImeWindowStatus) {
@@ -2163,14 +2151,7 @@ public class InputMethodService extends AbstractInputMethodService {
// compute visibility
onWindowShown();
- mIsPreRendered = mCanPreRender;
- if (mIsPreRendered) {
- onPreRenderedWindowVisibilityChanged(true /* setVisible */);
- } else {
- // Pre-rendering not supported.
- if (DEBUG) Log.d(TAG, "No pre-rendering supported");
- mWindowVisible = true;
- }
+ mWindowVisible = true;
// request draw for the IME surface.
// When IME is not pre-rendered, this will actually show the IME.
@@ -2178,22 +2159,10 @@ public class InputMethodService extends AbstractInputMethodService {
if (DEBUG) Log.v(TAG, "showWindow: draw decorView!");
mWindow.show();
}
- maybeNotifyPreRendered();
mDecorViewWasVisible = true;
mInShowWindow = false;
}
- /**
- * Notify {@link android.view.ImeInsetsSourceConsumer} if IME has been pre-rendered
- * for current EditorInfo, when pre-rendering is enabled.
- */
- private void maybeNotifyPreRendered() {
- if (!mCanPreRender || !mIsPreRendered) {
- return;
- }
- mPrivOps.reportPreRendered(getCurrentInputEditorInfo());
- }
-
private boolean prepareWindow(boolean showInput) {
boolean doShowInput = false;
@@ -2237,16 +2206,6 @@ public class InputMethodService extends AbstractInputMethodService {
if (doShowInput) startExtractingText(false);
}
- private void onPreRenderedWindowVisibilityChanged(boolean setVisible) {
- mWindowVisible = setVisible;
- mShowInputFlags = setVisible ? mShowInputFlags : 0;
- mShowInputRequested = setVisible;
- mDecorViewVisible = setVisible;
- if (setVisible) {
- onWindowShown();
- }
- }
-
/**
* Applies the IME visibility in {@link android.view.ImeInsetsSourceConsumer}.
*
@@ -2277,7 +2236,6 @@ public class InputMethodService extends AbstractInputMethodService {
public void hideWindow() {
if (DEBUG) Log.v(TAG, "CALL: hideWindow");
- mIsPreRendered = false;
mWindowVisible = false;
finishViews(false /* finishingInput */);
if (mDecorViewVisible) {
@@ -2384,32 +2342,6 @@ public class InputMethodService extends AbstractInputMethodService {
mCandidatesViewStarted = true;
onStartCandidatesView(mInputEditorInfo, restarting);
}
- } else if (mCanPreRender && mInputEditorInfo != null && mStartedInputConnection != null) {
- // Pre-render IME views and window when real EditorInfo is available.
- // pre-render IME window and keep it invisible.
- if (DEBUG) Log.v(TAG, "Pre-Render IME for " + mInputEditorInfo.fieldName);
- if (mInShowWindow) {
- Log.w(TAG, "Re-entrance in to showWindow");
- return;
- }
-
- mDecorViewWasVisible = mDecorViewVisible;
- mInShowWindow = true;
- startViews(prepareWindow(true /* showInput */));
-
- // compute visibility
- mIsPreRendered = true;
- onPreRenderedWindowVisibilityChanged(false /* setVisible */);
-
- // request draw for the IME surface.
- // When IME is not pre-rendered, this will actually show the IME.
- if (DEBUG) Log.v(TAG, "showWindow: draw decorView!");
- mWindow.show();
- maybeNotifyPreRendered();
- mDecorViewWasVisible = true;
- mInShowWindow = false;
- } else {
- mIsPreRendered = false;
}
}
@@ -3309,9 +3241,7 @@ public class InputMethodService extends AbstractInputMethodService {
private int mapToImeWindowStatus() {
return IME_ACTIVE
- | (isInputViewShown()
- ? (mCanPreRender ? (mWindowVisible ? IME_VISIBLE : IME_INVISIBLE)
- : IME_VISIBLE) : 0);
+ | (isInputViewShown() ? IME_VISIBLE : 0);
}
private boolean isAutomotive() {
@@ -3349,8 +3279,6 @@ public class InputMethodService extends AbstractInputMethodService {
p.println(" mShowInputRequested=" + mShowInputRequested
+ " mLastShowInputRequested=" + mLastShowInputRequested
- + " mCanPreRender=" + mCanPreRender
- + " mIsPreRendered=" + mIsPreRendered
+ " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags));
p.println(" mCandidatesVisibility=" + mCandidatesVisibility
+ " mFullscreenApplied=" + mFullscreenApplied
@@ -3401,8 +3329,6 @@ public class InputMethodService extends AbstractInputMethodService {
}
proto.write(SHOW_INPUT_REQUESTED, mShowInputRequested);
proto.write(LAST_SHOW_INPUT_REQUESTED, mLastShowInputRequested);
- proto.write(CAN_PRE_RENDER, mCanPreRender);
- proto.write(IS_PRE_RENDERED, mIsPreRendered);
proto.write(SHOW_INPUT_FLAGS, mShowInputFlags);
proto.write(CANDIDATES_VISIBILITY, mCandidatesVisibility);
proto.write(FULLSCREEN_APPLIED, mFullscreenApplied);
diff --git a/core/java/android/os/CombinedVibrationEffect.java b/core/java/android/os/CombinedVibrationEffect.java
index 77bfa577babd..f552aaa55796 100644
--- a/core/java/android/os/CombinedVibrationEffect.java
+++ b/core/java/android/os/CombinedVibrationEffect.java
@@ -17,7 +17,12 @@
package android.os;
import android.annotation.NonNull;
+import android.util.SparseArray;
+import com.android.internal.util.Preconditions;
+
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
/**
@@ -31,6 +36,8 @@ import java.util.Objects;
*/
public abstract class CombinedVibrationEffect implements Parcelable {
private static final int PARCEL_TOKEN_MONO = 1;
+ private static final int PARCEL_TOKEN_STEREO = 2;
+ private static final int PARCEL_TOKEN_SEQUENTIAL = 3;
/** @hide to prevent subclassing from outside of the framework */
public CombinedVibrationEffect() {
@@ -41,8 +48,8 @@ public abstract class CombinedVibrationEffect implements Parcelable {
*
* A synced vibration effect should be performed by multiple vibrators at the same time.
*
- * @param effect The {@link VibrationEffect} to perform
- * @return The desired combined effect.
+ * @param effect The {@link VibrationEffect} to perform.
+ * @return The synced effect.
*/
@NonNull
public static CombinedVibrationEffect createSynced(@NonNull VibrationEffect effect) {
@@ -51,6 +58,30 @@ public abstract class CombinedVibrationEffect implements Parcelable {
return combined;
}
+ /**
+ * Start creating a synced vibration effect.
+ *
+ * A synced vibration effect should be performed by multiple vibrators at the same time.
+ *
+ * @see CombinedVibrationEffect.SyncedCombination
+ */
+ @NonNull
+ public static SyncedCombination startSynced() {
+ return new SyncedCombination();
+ }
+
+ /**
+ * Start creating a sequential vibration effect.
+ *
+ * A sequential vibration effect should be performed by multiple vibrators in order.
+ *
+ * @see CombinedVibrationEffect.SequentialCombination
+ */
+ @NonNull
+ public static SequentialCombination startSequential() {
+ return new SequentialCombination();
+ }
+
@Override
public int describeContents() {
return 0;
@@ -60,6 +91,164 @@ public abstract class CombinedVibrationEffect implements Parcelable {
public abstract void validate();
/**
+ * A combination of haptic effects that should be played in multiple vibrators in sync.
+ *
+ * @hide
+ * @see CombinedVibrationEffect#startSynced()
+ */
+ public static final class SyncedCombination {
+
+ private final SparseArray<VibrationEffect> mEffects = new SparseArray<>();
+
+ SyncedCombination() {
+ }
+
+ /**
+ * Add or replace a one shot vibration effect to be performed by the specified vibrator.
+ *
+ * @param vibratorId The id of the vibrator that should perform this effect.
+ * @param effect The effect this vibrator should play.
+ * @return The {@link CombinedVibrationEffect.SyncedCombination} object to enable adding
+ * multiple effects in one chain.
+ * @see VibrationEffect#createOneShot(long, int)
+ */
+ @NonNull
+ public SyncedCombination addVibrator(int vibratorId, VibrationEffect effect) {
+ mEffects.put(vibratorId, effect);
+ return this;
+ }
+
+ /**
+ * Combine all of the added effects into a combined effect.
+ *
+ * The {@link CombinedVibrationEffect.SyncedCombination} object is still valid after this
+ * call, so you can continue adding more effects to it and generating more
+ * {@link CombinedVibrationEffect}s by calling this method again.
+ *
+ * @return The {@link CombinedVibrationEffect} resulting from combining the added effects to
+ * be played in sync.
+ */
+ @NonNull
+ public CombinedVibrationEffect combine() {
+ if (mEffects.size() == 0) {
+ throw new IllegalStateException(
+ "Combination must have at least one element to combine.");
+ }
+ CombinedVibrationEffect combined = new Stereo(mEffects);
+ combined.validate();
+ return combined;
+ }
+ }
+
+ /**
+ * A combination of haptic effects that should be played in multiple vibrators in sequence.
+ *
+ * @hide
+ * @see CombinedVibrationEffect#startSequential()
+ */
+ public static final class SequentialCombination {
+
+ private final ArrayList<CombinedVibrationEffect> mEffects = new ArrayList<>();
+ private final ArrayList<Integer> mDelays = new ArrayList<>();
+
+ SequentialCombination() {
+ }
+
+ /**
+ * Add a single vibration effect to be performed next.
+ *
+ * Similar to {@link #addNext(int, VibrationEffect, int)}, but with no delay.
+ *
+ * @param vibratorId The id of the vibrator that should perform this effect.
+ * @param effect The effect this vibrator should play.
+ * @return The {@link CombinedVibrationEffect.SequentialCombination} object to enable adding
+ * multiple effects in one chain.
+ */
+ @NonNull
+ public SequentialCombination addNext(int vibratorId, @NonNull VibrationEffect effect) {
+ return addNext(vibratorId, effect, /* delay= */ 0);
+ }
+
+ /**
+ * Add a single vibration effect to be performed next.
+ *
+ * @param vibratorId The id of the vibrator that should perform this effect.
+ * @param effect The effect this vibrator should play.
+ * @param delay The amount of time, in milliseconds, to wait between playing the prior
+ * effect and this one.
+ * @return The {@link CombinedVibrationEffect.SequentialCombination} object to enable adding
+ * multiple effects in one chain.
+ */
+ @NonNull
+ public SequentialCombination addNext(int vibratorId, @NonNull VibrationEffect effect,
+ int delay) {
+ return addNext(
+ CombinedVibrationEffect.startSynced().addVibrator(vibratorId, effect).combine(),
+ delay);
+ }
+
+ /**
+ * Add a combined vibration effect to be performed next.
+ *
+ * Similar to {@link #addNext(CombinedVibrationEffect, int)}, but with no delay.
+ *
+ * @param effect The combined effect to be performed next.
+ * @return The {@link CombinedVibrationEffect.SequentialCombination} object to enable adding
+ * multiple effects in one chain.
+ * @see VibrationEffect#createOneShot(long, int)
+ */
+ @NonNull
+ public SequentialCombination addNext(@NonNull CombinedVibrationEffect effect) {
+ return addNext(effect, /* delay= */ 0);
+ }
+
+ /**
+ * Add a one shot vibration effect to be performed by the specified vibrator.
+ *
+ * @param effect The combined effect to be performed next.
+ * @param delay The amount of time, in milliseconds, to wait between playing the prior
+ * effect and this one.
+ * @return The {@link CombinedVibrationEffect.SequentialCombination} object to enable adding
+ * multiple effects in one chain.
+ */
+ @NonNull
+ public SequentialCombination addNext(@NonNull CombinedVibrationEffect effect, int delay) {
+ if (effect instanceof Sequential) {
+ Sequential sequentialEffect = (Sequential) effect;
+ int firstEffectIndex = mDelays.size();
+ mEffects.addAll(sequentialEffect.getEffects());
+ mDelays.addAll(sequentialEffect.getDelays());
+ mDelays.set(firstEffectIndex, delay + mDelays.get(firstEffectIndex));
+ } else {
+ mEffects.add(effect);
+ mDelays.add(delay);
+ }
+ return this;
+ }
+
+ /**
+ * Combine all of the added effects in sequence.
+ *
+ * The {@link CombinedVibrationEffect.SequentialCombination} object is still valid after
+ * this call, so you can continue adding more effects to it and generating more {@link
+ * CombinedVibrationEffect}s by calling this method again.
+ *
+ * @return The {@link CombinedVibrationEffect} resulting from combining the added effects to
+ * be played in sequence.
+ */
+ @NonNull
+ public CombinedVibrationEffect combine() {
+ if (mEffects.size() == 0) {
+ throw new IllegalStateException(
+ "Combination must have at least one element to combine.");
+ }
+ CombinedVibrationEffect combined = new Sequential(mEffects, mDelays);
+ combined.validate();
+ return combined;
+ }
+ }
+
+ /**
* Represents a single {@link VibrationEffect} that should be executed in all vibrators in sync.
*
* @hide
@@ -87,10 +276,10 @@ public abstract class CombinedVibrationEffect implements Parcelable {
@Override
public boolean equals(Object o) {
- if (!(o instanceof CombinedVibrationEffect.Mono)) {
+ if (!(o instanceof Mono)) {
return false;
}
- CombinedVibrationEffect.Mono other = (CombinedVibrationEffect.Mono) o;
+ Mono other = (Mono) o;
return other.mEffect.equals(other.mEffect);
}
@@ -128,6 +317,206 @@ public abstract class CombinedVibrationEffect implements Parcelable {
};
}
+ /**
+ * Represents a list of {@link VibrationEffect}s that should be executed in sync.
+ *
+ * @hide
+ */
+ public static final class Stereo extends CombinedVibrationEffect {
+
+ /** Mapping vibrator ids to effects. */
+ private final SparseArray<VibrationEffect> mEffects;
+
+ public Stereo(Parcel in) {
+ int size = in.readInt();
+ mEffects = new SparseArray<>(size);
+ for (int i = 0; i < size; i++) {
+ int vibratorId = in.readInt();
+ mEffects.put(vibratorId, VibrationEffect.CREATOR.createFromParcel(in));
+ }
+ }
+
+ public Stereo(@NonNull SparseArray<VibrationEffect> effects) {
+ mEffects = new SparseArray<>(effects.size());
+ for (int i = 0; i < effects.size(); i++) {
+ mEffects.put(effects.keyAt(i), effects.valueAt(i));
+ }
+ }
+
+ /** Effects to be performed in sync, where each key represents the vibrator id. */
+ public SparseArray<VibrationEffect> getEffects() {
+ return mEffects;
+ }
+
+ /** @hide */
+ @Override
+ public void validate() {
+ Preconditions.checkArgument(mEffects.size() > 0,
+ "There should be at least one effect set for a combined effect");
+ for (int i = 0; i < mEffects.size(); i++) {
+ mEffects.valueAt(i).validate();
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Stereo)) {
+ return false;
+ }
+ Stereo other = (Stereo) o;
+ if (mEffects.size() != other.mEffects.size()) {
+ return false;
+ }
+ for (int i = 0; i < mEffects.size(); i++) {
+ if (!mEffects.valueAt(i).equals(other.mEffects.get(mEffects.keyAt(i)))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mEffects);
+ }
+
+ @Override
+ public String toString() {
+ return "Stereo{mEffects=" + mEffects + '}';
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(PARCEL_TOKEN_STEREO);
+ out.writeInt(mEffects.size());
+ for (int i = 0; i < mEffects.size(); i++) {
+ out.writeInt(mEffects.keyAt(i));
+ mEffects.valueAt(i).writeToParcel(out, flags);
+ }
+ }
+
+ @NonNull
+ public static final Parcelable.Creator<Stereo> CREATOR =
+ new Parcelable.Creator<Stereo>() {
+ @Override
+ public Stereo createFromParcel(@NonNull Parcel in) {
+ // Skip the type token
+ in.readInt();
+ return new Stereo(in);
+ }
+
+ @Override
+ @NonNull
+ public Stereo[] newArray(int size) {
+ return new Stereo[size];
+ }
+ };
+ }
+
+ /**
+ * Represents a list of {@link VibrationEffect}s that should be executed in sequence.
+ *
+ * @hide
+ */
+ public static final class Sequential extends CombinedVibrationEffect {
+ private final List<CombinedVibrationEffect> mEffects;
+ private final List<Integer> mDelays;
+
+ public Sequential(Parcel in) {
+ int size = in.readInt();
+ mEffects = new ArrayList<>(size);
+ mDelays = new ArrayList<>(size);
+ for (int i = 0; i < size; i++) {
+ mDelays.add(in.readInt());
+ mEffects.add(CombinedVibrationEffect.CREATOR.createFromParcel(in));
+ }
+ }
+
+ public Sequential(@NonNull List<CombinedVibrationEffect> effects,
+ @NonNull List<Integer> delays) {
+ mEffects = new ArrayList<>(effects);
+ mDelays = new ArrayList<>(delays);
+ }
+
+ /** Effects to be performed in sequence. */
+ public List<CombinedVibrationEffect> getEffects() {
+ return mEffects;
+ }
+
+ /** Delay to be applied before each effect in {@link #getEffects()}. */
+ public List<Integer> getDelays() {
+ return mDelays;
+ }
+
+ /** @hide */
+ @Override
+ public void validate() {
+ Preconditions.checkArgument(mEffects.size() > 0,
+ "There should be at least one effect set for a combined effect");
+ Preconditions.checkArgument(mEffects.size() == mDelays.size(),
+ "Effect and delays should have equal length");
+ for (long delay : mDelays) {
+ if (delay < 0) {
+ throw new IllegalArgumentException("Delays must all be >= 0"
+ + " (delays=" + mDelays + ")");
+ }
+ }
+ for (CombinedVibrationEffect effect : mEffects) {
+ if (effect instanceof Sequential) {
+ throw new IllegalArgumentException(
+ "There should be no nested sequential effects in a combined effect");
+ }
+ effect.validate();
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Sequential)) {
+ return false;
+ }
+ Sequential other = (Sequential) o;
+ return mDelays.equals(other.mDelays) && mEffects.equals(other.mEffects);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mEffects);
+ }
+
+ @Override
+ public String toString() {
+ return "Sequential{mEffects=" + mEffects + ", mDelays=" + mDelays + '}';
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(PARCEL_TOKEN_SEQUENTIAL);
+ out.writeInt(mEffects.size());
+ for (int i = 0; i < mEffects.size(); i++) {
+ out.writeInt(mDelays.get(i));
+ mEffects.get(i).writeToParcel(out, flags);
+ }
+ }
+
+ @NonNull
+ public static final Parcelable.Creator<Sequential> CREATOR =
+ new Parcelable.Creator<Sequential>() {
+ @Override
+ public Sequential createFromParcel(@NonNull Parcel in) {
+ // Skip the type token
+ in.readInt();
+ return new Sequential(in);
+ }
+
+ @Override
+ @NonNull
+ public Sequential[] newArray(int size) {
+ return new Sequential[size];
+ }
+ };
+ }
+
@NonNull
public static final Parcelable.Creator<CombinedVibrationEffect> CREATOR =
new Parcelable.Creator<CombinedVibrationEffect>() {
@@ -135,7 +524,11 @@ public abstract class CombinedVibrationEffect implements Parcelable {
public CombinedVibrationEffect createFromParcel(Parcel in) {
int token = in.readInt();
if (token == PARCEL_TOKEN_MONO) {
- return new CombinedVibrationEffect.Mono(in);
+ return new Mono(in);
+ } else if (token == PARCEL_TOKEN_STEREO) {
+ return new Stereo(in);
+ } else if (token == PARCEL_TOKEN_SEQUENTIAL) {
+ return new Sequential(in);
} else {
throw new IllegalStateException(
"Unexpected combined vibration event type token in parcel.");
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 2edd3227cf36..aba1f281c583 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -4033,7 +4033,8 @@ public class UserManager {
* @return the {@link RemoveResult} code
* @hide
*/
- @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
+ Manifest.permission.CREATE_USERS})
public @RemoveResult int removeUserOrSetEphemeral(@UserIdInt int userId) {
try {
return mService.removeUserOrSetEphemeral(userId);
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 0a4e867458e0..97c9f4bbb4ba 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -251,6 +251,15 @@ public final class DeviceConfig {
public static final String NAMESPACE_PACKAGE_MANAGER_SERVICE = "package_manager_service";
/**
+ * Namespace for features related to the Profcollect native Service.
+ * These features are applied at reboot.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String NAMESPACE_PROFCOLLECT_NATIVE_BOOT = "profcollect_native_boot";
+
+ /**
* Namespace for Rollback flags that are applied immediately.
*
* @hide
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 780c4fa66d26..f31e70a87169 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -9758,6 +9758,14 @@ public final class Settings {
"render_shadows_in_compositor";
/**
+ * If true, submit buffers using blast in ViewRootImpl.
+ * (0 = false, 1 = true)
+ * @hide
+ */
+ public static final String DEVELOPMENT_USE_BLAST_ADAPTER_VR =
+ "use_blast_adapter_vr";
+
+ /**
* If true, submit buffers using blast in SurfaceView.
* (0 = false, 1 = true)
* @hide
@@ -9765,6 +9773,14 @@ public final class Settings {
public static final String DEVELOPMENT_USE_BLAST_ADAPTER_SV =
"use_blast_adapter_sv";
+ /**
+ * If {@code true}, vendor provided window manager display settings will be ignored.
+ * (0 = false, 1 = true)
+ * @hide
+ */
+ public static final String DEVELOPMENT_IGNORE_VENDOR_DISPLAY_SETTINGS =
+ "ignore_vendor_display_settings";
+
/**
* Whether user has enabled development settings.
*/
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index e4ba87c14626..f08756a015b2 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -218,6 +218,7 @@ public final class KeymasterDefs {
public static final int KM_ERROR_MISSING_MIN_MAC_LENGTH = -58;
public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = -59;
public static final int KM_ERROR_CANNOT_ATTEST_IDS = -66;
+ public static final int KM_ERROR_HARDWARE_TYPE_UNAVAILABLE = -68;
public static final int KM_ERROR_DEVICE_LOCKED = -72;
public static final int KM_ERROR_UNIMPLEMENTED = -100;
public static final int KM_ERROR_VERSION_MISMATCH = -101;
@@ -265,6 +266,8 @@ public final class KeymasterDefs {
sErrorCodeToString.put(KM_ERROR_INVALID_MAC_LENGTH,
"Invalid MAC or authentication tag length");
sErrorCodeToString.put(KM_ERROR_CANNOT_ATTEST_IDS, "Unable to attest device ids");
+ sErrorCodeToString.put(KM_ERROR_HARDWARE_TYPE_UNAVAILABLE, "Requested security level "
+ + "(likely Strongbox) is not available.");
sErrorCodeToString.put(KM_ERROR_DEVICE_LOCKED, "Device locked");
sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented");
sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error");
diff --git a/core/java/android/uwb/AngleMeasurement.java b/core/java/android/uwb/AngleMeasurement.java
index c3e2ecc9e0f3..cf32b922078e 100644
--- a/core/java/android/uwb/AngleMeasurement.java
+++ b/core/java/android/uwb/AngleMeasurement.java
@@ -17,6 +17,8 @@
package android.uwb;
import android.annotation.FloatRange;
+import android.os.Parcel;
+import android.os.Parcelable;
/**
* Angle measurement
@@ -26,7 +28,7 @@ import android.annotation.FloatRange;
*
* @hide
*/
-public final class AngleMeasurement {
+public final class AngleMeasurement implements Parcelable {
private final double mRadians;
private final double mErrorRadians;
private final double mConfidenceLevel;
@@ -39,7 +41,7 @@ public final class AngleMeasurement {
/**
* Angle measurement in radians
- *
+ *
* @return angle in radians
*/
@FloatRange(from = -Math.PI, to = +Math.PI)
@@ -73,6 +75,35 @@ public final class AngleMeasurement {
return mConfidenceLevel;
}
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeDouble(mRadians);
+ dest.writeDouble(mErrorRadians);
+ dest.writeDouble(mConfidenceLevel);
+ }
+
+ public static final @android.annotation.NonNull Creator<AngleMeasurement> CREATOR =
+ new Creator<AngleMeasurement>() {
+ @Override
+ public AngleMeasurement createFromParcel(Parcel in) {
+ Builder builder = new Builder();
+ builder.setRadians(in.readDouble());
+ builder.setErrorRadians(in.readDouble());
+ builder.setConfidenceLevel(in.readDouble());
+ return builder.build();
+ }
+
+ @Override
+ public AngleMeasurement[] newArray(int size) {
+ return new AngleMeasurement[size];
+ }
+ };
+
/**
* Builder class for {@link AngleMeasurement}.
*/
diff --git a/core/java/android/uwb/AngleOfArrivalMeasurement.java b/core/java/android/uwb/AngleOfArrivalMeasurement.java
index a7b5eae728cb..646bd42cef2a 100644
--- a/core/java/android/uwb/AngleOfArrivalMeasurement.java
+++ b/core/java/android/uwb/AngleOfArrivalMeasurement.java
@@ -18,13 +18,15 @@ package android.uwb;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
/**
* Represents an angle of arrival measurement between two devices using Ultra Wideband
*
* @hide
*/
-public final class AngleOfArrivalMeasurement {
+public final class AngleOfArrivalMeasurement implements Parcelable {
private final AngleMeasurement mAzimuthAngleMeasurement;
private final AngleMeasurement mAltitudeAngleMeasurement;
@@ -70,6 +72,38 @@ public final class AngleOfArrivalMeasurement {
return mAltitudeAngleMeasurement;
}
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mAzimuthAngleMeasurement, flags);
+ dest.writeParcelable(mAltitudeAngleMeasurement, flags);
+ }
+
+ public static final @android.annotation.NonNull Creator<AngleOfArrivalMeasurement> CREATOR =
+ new Creator<AngleOfArrivalMeasurement>() {
+ @Override
+ public AngleOfArrivalMeasurement createFromParcel(Parcel in) {
+ Builder builder = new Builder();
+
+ builder.setAzimuthAngleMeasurement(
+ in.readParcelable(AngleMeasurement.class.getClassLoader()));
+
+ builder.setAltitudeAngleMeasurement(
+ in.readParcelable(AngleMeasurement.class.getClassLoader()));
+
+ return builder.build();
+ }
+
+ @Override
+ public AngleOfArrivalMeasurement[] newArray(int size) {
+ return new AngleOfArrivalMeasurement[size];
+ }
+ };
+
/**
* Builder class for {@link AngleOfArrivalMeasurement}.
*/
diff --git a/core/java/android/uwb/DistanceMeasurement.java b/core/java/android/uwb/DistanceMeasurement.java
index 4cd5d83f4efc..9561be449a19 100644
--- a/core/java/android/uwb/DistanceMeasurement.java
+++ b/core/java/android/uwb/DistanceMeasurement.java
@@ -17,6 +17,8 @@
package android.uwb;
import android.annotation.FloatRange;
+import android.os.Parcel;
+import android.os.Parcelable;
/**
* A data point for the distance measurement
@@ -26,7 +28,7 @@ import android.annotation.FloatRange;
*
* @hide
*/
-public final class DistanceMeasurement {
+public final class DistanceMeasurement implements Parcelable {
private final double mMeters;
private final double mErrorMeters;
private final double mConfidenceLevel;
@@ -69,6 +71,35 @@ public final class DistanceMeasurement {
return mConfidenceLevel;
}
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeDouble(mMeters);
+ dest.writeDouble(mErrorMeters);
+ dest.writeDouble(mConfidenceLevel);
+ }
+
+ public static final @android.annotation.NonNull Creator<DistanceMeasurement> CREATOR =
+ new Creator<DistanceMeasurement>() {
+ @Override
+ public DistanceMeasurement createFromParcel(Parcel in) {
+ Builder builder = new Builder();
+ builder.setMeters(in.readDouble());
+ builder.setErrorMeters(in.readDouble());
+ builder.setConfidenceLevel(in.readDouble());
+ return builder.build();
+ }
+
+ @Override
+ public DistanceMeasurement[] newArray(int size) {
+ return new DistanceMeasurement[size];
+ }
+ };
+
/**
* Builder to get a {@link DistanceMeasurement} object.
*/
diff --git a/core/java/android/uwb/RangingMeasurement.java b/core/java/android/uwb/RangingMeasurement.java
index 33a34e3954c2..d4d7fb23959a 100644
--- a/core/java/android/uwb/RangingMeasurement.java
+++ b/core/java/android/uwb/RangingMeasurement.java
@@ -20,6 +20,8 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.SystemClock;
import java.lang.annotation.Retention;
@@ -30,7 +32,7 @@ import java.lang.annotation.RetentionPolicy;
*
* @hide
*/
-public final class RangingMeasurement {
+public final class RangingMeasurement implements Parcelable {
private final UwbAddress mRemoteDeviceAddress;
private final @Status int mStatus;
private final long mElapsedRealtimeNanos;
@@ -127,6 +129,42 @@ public final class RangingMeasurement {
return mAngleOfArrivalMeasurement;
}
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mRemoteDeviceAddress, flags);
+ dest.writeInt(mStatus);
+ dest.writeLong(mElapsedRealtimeNanos);
+ dest.writeParcelable(mDistanceMeasurement, flags);
+ dest.writeParcelable(mAngleOfArrivalMeasurement, flags);
+ }
+
+ public static final @android.annotation.NonNull Creator<RangingMeasurement> CREATOR =
+ new Creator<RangingMeasurement>() {
+ @Override
+ public RangingMeasurement createFromParcel(Parcel in) {
+ Builder builder = new Builder();
+ builder.setRemoteDeviceAddress(
+ in.readParcelable(UwbAddress.class.getClassLoader()));
+ builder.setStatus(in.readInt());
+ builder.setElapsedRealtimeNanos(in.readLong());
+ builder.setDistanceMeasurement(
+ in.readParcelable(DistanceMeasurement.class.getClassLoader()));
+ builder.setAngleOfArrivalMeasurement(
+ in.readParcelable(AngleOfArrivalMeasurement.class.getClassLoader()));
+ return builder.build();
+ }
+
+ @Override
+ public RangingMeasurement[] newArray(int size) {
+ return new RangingMeasurement[size];
+ }
+ };
+
/**
* Builder for a {@link RangingMeasurement} object.
*/
diff --git a/core/java/android/uwb/RangingParams.java b/core/java/android/uwb/RangingParams.java
index a50de3e61425..c5d4807859b5 100644
--- a/core/java/android/uwb/RangingParams.java
+++ b/core/java/android/uwb/RangingParams.java
@@ -19,11 +19,13 @@ package android.uwb;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.os.PersistableBundle;
-import android.util.Duration;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@@ -36,7 +38,7 @@ import java.util.Set;
*
* @hide
*/
-public final class RangingParams {
+public final class RangingParams implements Parcelable {
private final boolean mIsInitiator;
private final boolean mIsController;
private final Duration mSamplePeriod;
@@ -199,6 +201,62 @@ public final class RangingParams {
return new PersistableBundle(mSpecificationParameters);
}
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeBoolean(mIsInitiator);
+ dest.writeBoolean(mIsController);
+ dest.writeLong(mSamplePeriod.getSeconds());
+ dest.writeInt(mSamplePeriod.getNano());
+ dest.writeParcelable(mLocalDeviceAddress, flags);
+
+ UwbAddress[] remoteAddresses = new UwbAddress[mRemoteDeviceAddresses.size()];
+ mRemoteDeviceAddresses.toArray(remoteAddresses);
+ dest.writeParcelableArray(remoteAddresses, flags);
+
+ dest.writeInt(mChannelNumber);
+ dest.writeInt(mTransmitPreambleCodeIndex);
+ dest.writeInt(mReceivePreambleCodeIndex);
+ dest.writeInt(mStsPhyPacketType);
+ dest.writePersistableBundle(mSpecificationParameters);
+ }
+
+ public static final @android.annotation.NonNull Creator<RangingParams> CREATOR =
+ new Creator<RangingParams>() {
+ @Override
+ public RangingParams createFromParcel(Parcel in) {
+ Builder builder = new Builder();
+ builder.setIsInitiator(in.readBoolean());
+ builder.setIsController(in.readBoolean());
+ builder.setSamplePeriod(Duration.ofSeconds(in.readLong(), in.readInt()));
+ builder.setLocalDeviceAddress(
+ in.readParcelable(UwbAddress.class.getClassLoader()));
+
+ UwbAddress[] remoteAddresses =
+ in.readParcelableArray(null, UwbAddress.class);
+ for (UwbAddress remoteAddress : remoteAddresses) {
+ builder.addRemoteDeviceAddress(remoteAddress);
+ }
+
+ builder.setChannelNumber(in.readInt());
+ builder.setTransmitPreambleCodeIndex(in.readInt());
+ builder.setReceivePreambleCodeIndex(in.readInt());
+ builder.setStsPhPacketType(in.readInt());
+ builder.setSpecificationParameters(in.readPersistableBundle());
+
+ return builder.build();
+ }
+
+ @Override
+ public RangingParams[] newArray(int size) {
+ return new RangingParams[size];
+ }
+ };
+
/**
* Builder class for {@link RangingParams}.
*/
diff --git a/core/java/android/uwb/RangingReport.java b/core/java/android/uwb/RangingReport.java
index 5aca12aaf2cf..1d340b4b0358 100644
--- a/core/java/android/uwb/RangingReport.java
+++ b/core/java/android/uwb/RangingReport.java
@@ -17,6 +17,8 @@
package android.uwb;
import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
import java.util.ArrayList;
import java.util.List;
@@ -26,7 +28,7 @@ import java.util.List;
*
* @hide
*/
-public final class RangingReport {
+public final class RangingReport implements Parcelable {
private final List<RangingMeasurement> mRangingMeasurements;
private RangingReport(@NonNull List<RangingMeasurement> rangingMeasurements) {
@@ -48,6 +50,31 @@ public final class RangingReport {
return mRangingMeasurements;
}
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeTypedList(mRangingMeasurements);
+ }
+
+ public static final @android.annotation.NonNull Creator<RangingReport> CREATOR =
+ new Creator<RangingReport>() {
+ @Override
+ public RangingReport createFromParcel(Parcel in) {
+ Builder builder = new Builder();
+ builder.addMeasurements(in.createTypedArrayList(RangingMeasurement.CREATOR));
+ return builder.build();
+ }
+
+ @Override
+ public RangingReport[] newArray(int size) {
+ return new RangingReport[size];
+ }
+ };
+
/**
* Builder for {@link RangingReport} object
*/
diff --git a/core/java/android/uwb/UwbAddress.java b/core/java/android/uwb/UwbAddress.java
index 48fcb10e1a1a..828324c54c5a 100644
--- a/core/java/android/uwb/UwbAddress.java
+++ b/core/java/android/uwb/UwbAddress.java
@@ -18,16 +18,26 @@ package android.uwb;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
/**
* A class representing a UWB address
*
* @hide
*/
-public final class UwbAddress {
+public final class UwbAddress implements Parcelable {
public static final int SHORT_ADDRESS_BYTE_LENGTH = 2;
public static final int EXTENDED_ADDRESS_BYTE_LENGTH = 8;
+ private final byte[] mAddressBytes;
+
+ private UwbAddress(byte[] address) {
+ mAddressBytes = address;
+ }
+
/**
* Create a {@link UwbAddress} from a byte array.
*
@@ -37,12 +47,16 @@ public final class UwbAddress {
*
* @param address a byte array to convert to a {@link UwbAddress}
* @return a {@link UwbAddress} created from the input byte array
- * @throw IllegableArumentException when the length is not one of
+ * @throws IllegalArgumentException when the length is not one of
* {@link #SHORT_ADDRESS_BYTE_LENGTH} or {@link #EXTENDED_ADDRESS_BYTE_LENGTH} bytes
*/
@NonNull
- public static UwbAddress fromBytes(byte[] address) throws IllegalArgumentException {
- throw new UnsupportedOperationException();
+ public static UwbAddress fromBytes(@NonNull byte[] address) throws IllegalArgumentException {
+ if (address.length != SHORT_ADDRESS_BYTE_LENGTH
+ && address.length != EXTENDED_ADDRESS_BYTE_LENGTH) {
+ throw new IllegalArgumentException("Invalid UwbAddress length " + address.length);
+ }
+ return new UwbAddress(address);
}
/**
@@ -52,7 +66,7 @@ public final class UwbAddress {
*/
@NonNull
public byte[] toBytes() {
- throw new UnsupportedOperationException();
+ return mAddressBytes;
}
/**
@@ -61,22 +75,55 @@ public final class UwbAddress {
* {@link #EXTENDED_ADDRESS_BYTE_LENGTH}.
*/
public int size() {
- throw new UnsupportedOperationException();
+ return mAddressBytes.length;
}
@NonNull
@Override
public String toString() {
- throw new UnsupportedOperationException();
+ StringBuilder builder = new StringBuilder("0x");
+ for (byte addressByte : mAddressBytes) {
+ builder.append(String.format("%02X", addressByte));
+ }
+ return builder.toString();
}
@Override
public boolean equals(@Nullable Object obj) {
- throw new UnsupportedOperationException();
+ if (obj instanceof UwbAddress) {
+ return Arrays.equals(mAddressBytes, ((UwbAddress) obj).toBytes());
+ }
+ return false;
}
@Override
public int hashCode() {
- throw new UnsupportedOperationException();
+ return Arrays.hashCode(mAddressBytes);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mAddressBytes.length);
+ dest.writeByteArray(mAddressBytes);
}
+
+ public static final @android.annotation.NonNull Creator<UwbAddress> CREATOR =
+ new Creator<UwbAddress>() {
+ @Override
+ public UwbAddress createFromParcel(Parcel in) {
+ byte[] address = new byte[in.readInt()];
+ in.readByteArray(address);
+ return UwbAddress.fromBytes(address);
+ }
+
+ @Override
+ public UwbAddress[] newArray(int size) {
+ return new UwbAddress[size];
+ }
+ };
}
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index dd1a19458e1d..f4d5a7b695eb 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -16,7 +16,7 @@
package android.view;
-import static android.view.ImeInsetsSourceConsumerProto.FOCUSED_EDITOR;
+import static android.os.Trace.TRACE_TAG_VIEW;
import static android.view.ImeInsetsSourceConsumerProto.INSETS_SOURCE_CONSUMER;
import static android.view.ImeInsetsSourceConsumerProto.IS_REQUESTED_VISIBLE_AWAITING_CONTROL;
import static android.view.InsetsController.AnimationType;
@@ -25,16 +25,11 @@ import static android.view.InsetsState.ITYPE_IME;
import android.annotation.Nullable;
import android.inputmethodservice.InputMethodService;
import android.os.IBinder;
-import android.os.Parcel;
-import android.text.TextUtils;
+import android.os.Trace;
import android.util.proto.ProtoOutputStream;
import android.view.SurfaceControl.Transaction;
-import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.Arrays;
import java.util.function.Supplier;
/**
@@ -42,13 +37,6 @@ import java.util.function.Supplier;
* @hide
*/
public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
- private EditorInfo mFocusedEditor;
- private EditorInfo mPreRenderedEditor;
- /**
- * Determines if IME would be shown next time IME is pre-rendered for currently focused
- * editor {@link #mFocusedEditor} if {@link #isServedEditorRendered} is {@code true}.
- */
- private boolean mShowOnNextImeRender;
/**
* Tracks whether we have an outstanding request from the IME to show, but weren't able to
@@ -62,23 +50,6 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
super(ITYPE_IME, state, transactionSupplier, controller);
}
- public void onPreRendered(EditorInfo info) {
- mPreRenderedEditor = info;
- if (mShowOnNextImeRender) {
- mShowOnNextImeRender = false;
- if (isServedEditorRendered()) {
- applyImeVisibility(true /* setVisible */);
- }
- }
- }
-
- public void onServedEditorChanged(EditorInfo info) {
- if (isFallbackOrEmptyEditor(info)) {
- mShowOnNextImeRender = false;
- }
- mFocusedEditor = info;
- }
-
public void applyImeVisibility(boolean setVisible) {
mController.applyImeVisibility(setVisible);
}
@@ -136,6 +107,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
@Override
void notifyHidden() {
getImm().notifyImeHidden(mController.getHost().getWindowToken());
+ Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0);
}
@Override
@@ -170,73 +142,10 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
}
}
- private boolean isFallbackOrEmptyEditor(EditorInfo info) {
- // TODO(b/123044812): Handle fallback input gracefully in IME Insets API
- return info == null || (info.fieldId <= 0 && info.inputType <= 0);
- }
-
- private boolean isServedEditorRendered() {
- if (mFocusedEditor == null || mPreRenderedEditor == null
- || isFallbackOrEmptyEditor(mFocusedEditor)
- || isFallbackOrEmptyEditor(mPreRenderedEditor)) {
- // No view is focused or ready.
- return false;
- }
- return areEditorsSimilar(mFocusedEditor, mPreRenderedEditor);
- }
-
- @VisibleForTesting
- public static boolean areEditorsSimilar(EditorInfo info1, EditorInfo info2) {
- // We don't need to compare EditorInfo.fieldId (View#id) since that shouldn't change
- // IME views.
- boolean areOptionsSimilar =
- info1.imeOptions == info2.imeOptions
- && info1.inputType == info2.inputType
- && TextUtils.equals(info1.packageName, info2.packageName);
- areOptionsSimilar &= info1.privateImeOptions != null
- ? info1.privateImeOptions.equals(info2.privateImeOptions) : true;
-
- if (!areOptionsSimilar) {
- return false;
- }
-
- // compare bundle extras.
- if ((info1.extras == null && info2.extras == null) || info1.extras == info2.extras) {
- return true;
- }
- if ((info1.extras == null && info2.extras != null)
- || (info1.extras == null && info2.extras != null)) {
- return false;
- }
- if (info1.extras.hashCode() == info2.extras.hashCode()
- || info1.extras.equals(info1)) {
- return true;
- }
- if (info1.extras.size() != info2.extras.size()) {
- return false;
- }
- if (info1.extras.toString().equals(info2.extras.toString())) {
- return true;
- }
-
- // Compare bytes
- Parcel parcel1 = Parcel.obtain();
- info1.extras.writeToParcel(parcel1, 0);
- parcel1.setDataPosition(0);
- Parcel parcel2 = Parcel.obtain();
- info2.extras.writeToParcel(parcel2, 0);
- parcel2.setDataPosition(0);
-
- return Arrays.equals(parcel1.createByteArray(), parcel2.createByteArray());
- }
-
@Override
public void dumpDebug(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
super.dumpDebug(proto, INSETS_SOURCE_CONSUMER);
- if (mFocusedEditor != null) {
- mFocusedEditor.dumpDebug(proto, FOCUSED_EDITOR);
- }
proto.write(IS_REQUESTED_VISIBLE_AWAITING_CONTROL, mIsRequestedVisibleAwaitingControl);
proto.end(token);
}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index b5bf08443a6c..fbee83389d8a 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.os.Trace.TRACE_TAG_VIEW;
import static android.view.InsetsControllerProto.CONTROL;
import static android.view.InsetsControllerProto.STATE;
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
@@ -829,6 +830,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
public void show(@InsetsType int types, boolean fromIme) {
if (fromIme) {
ImeTracing.getInstance().triggerDump();
+ Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromApiToImeReady", 0);
+ Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.showRequestFromIme", 0);
+ } else {
+ Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.showRequestFromApi", 0);
+ Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.showRequestFromApiToImeReady", 0);
}
// Handle pending request ready in case there was one set.
if (fromIme && mPendingImeControlRequest != null) {
@@ -880,6 +886,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
void hide(@InsetsType int types, boolean fromIme) {
if (fromIme) {
ImeTracing.getInstance().triggerDump();
+ Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.hideRequestFromIme", 0);
+ } else {
+ Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0);
}
int typesReady = 0;
final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types);
@@ -989,6 +998,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
});
}
updateRequestedVisibility();
+ Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromApi", 0);
return;
}
@@ -1014,11 +1024,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
cancellationSignal.setOnCancelListener(() -> {
cancelAnimation(runner, true /* invokeCallback */);
});
+ } else {
+ Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.pendingAnim", 0);
}
if (layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN) {
- showDirectly(types);
+ showDirectly(types, fromIme);
} else {
- hideDirectly(types, false /* animationFinished */, animationType);
+ hideDirectly(types, false /* animationFinished */, animationType, fromIme);
}
updateRequestedVisibility();
}
@@ -1141,10 +1153,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
cancelAnimation(runner, false /* invokeCallback */);
if (DEBUG) Log.d(TAG, "notifyFinished. shown: " + shown);
if (shown) {
- showDirectly(runner.getTypes());
+ showDirectly(runner.getTypes(), true /* fromIme */);
} else {
hideDirectly(runner.getTypes(), true /* animationFinished */,
- runner.getAnimationType());
+ runner.getAnimationType(), true /* fromIme */);
}
}
@@ -1314,11 +1326,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE,
show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN : LAYOUT_INSETS_DURING_ANIMATION_HIDDEN,
!hasAnimationCallbacks /* useInsetsAnimationThread */);
-
}
private void hideDirectly(
- @InsetsType int types, boolean animationFinished, @AnimationType int animationType) {
+ @InsetsType int types, boolean animationFinished, @AnimationType int animationType,
+ boolean fromIme) {
if ((types & ime()) != 0) {
ImeTracing.getInstance().triggerDump();
}
@@ -1327,9 +1339,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
getSourceConsumer(internalTypes.valueAt(i)).hide(animationFinished, animationType);
}
updateRequestedVisibility();
+
+ if (fromIme) {
+ Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.hideRequestFromIme", 0);
+ }
}
- private void showDirectly(@InsetsType int types) {
+ private void showDirectly(@InsetsType int types, boolean fromIme) {
if ((types & ime()) != 0) {
ImeTracing.getInstance().triggerDump();
}
@@ -1338,6 +1354,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
getSourceConsumer(internalTypes.valueAt(i)).show(false /* fromIme */);
}
updateRequestedVisibility();
+
+ if (fromIme) {
+ Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromIme", 0);
+ }
}
/**
@@ -1374,7 +1394,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
if (WARN) Log.w(TAG, "startAnimation canceled before preDraw");
return;
}
- Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW,
+ Trace.asyncTraceBegin(TRACE_TAG_VIEW,
"InsetsAnimation: " + WindowInsets.Type.toString(types), types);
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
RunningAnimation runningAnimation = mRunningAnimations.get(i);
@@ -1382,6 +1402,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
runningAnimation.startDispatched = true;
}
}
+ Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.pendingAnim", 0);
mHost.dispatchWindowInsetsAnimationStart(animation, bounds);
mStartingAnimation = true;
controller.mReadyDispatched = true;
@@ -1392,7 +1413,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
@VisibleForTesting
public void dispatchAnimationEnd(WindowInsetsAnimation animation) {
- Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW,
+ Trace.asyncTraceEnd(TRACE_TAG_VIEW,
"InsetsAnimation: " + WindowInsets.Type.toString(animation.getTypeMask()),
animation.getTypeMask());
mHost.dispatchWindowInsetsAnimationEnd(animation);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 9ea4c93b75c7..af31b817d520 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -135,6 +135,8 @@ public final class SurfaceControl implements Parcelable {
int blurRadius);
private static native void nativeSetLayerStack(long transactionObj, long nativeObject,
int layerStack);
+ private static native void nativeSetBlurRegions(long transactionObj, long nativeObj,
+ float[][] regions, int length);
private static native boolean nativeClearContentFrameStats(long nativeObject);
private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats);
@@ -546,6 +548,12 @@ public final class SurfaceControl implements Parcelable {
public static final int METADATA_ACCESSIBILITY_ID = 5;
/**
+ * owner PID.
+ * @hide
+ */
+ public static final int METADATA_OWNER_PID = 6;
+
+ /**
* A wrapper around HardwareBuffer that contains extra information about how to
* interpret the screenshot HardwareBuffer.
*
@@ -2954,6 +2962,21 @@ public final class SurfaceControl implements Parcelable {
}
/**
+ * Specify what regions should be blurred on the {@link SurfaceControl}.
+ *
+ * @param sc SurfaceControl.
+ * @param regions List of regions that will have blurs.
+ * @return itself.
+ * @see BlurRegion#toFloatArray()
+ * @hide
+ */
+ public Transaction setBlurRegions(SurfaceControl sc, float[][] regions) {
+ checkPreconditions(sc);
+ nativeSetBlurRegions(mNativeObject, sc.mNativeObject, regions, regions.length);
+ return this;
+ }
+
+ /**
* @hide
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.O)
@@ -3482,4 +3505,64 @@ public final class SurfaceControl implements Parcelable {
public static Transaction getGlobalTransaction() {
return sGlobalTransaction;
}
+
+ /**
+ * Wrapper for sending blur data to SurfaceFlinger.
+ * @hide
+ */
+ public static final class BlurRegion {
+ public int blurRadius;
+ public float cornerRadiusTL;
+ public float cornerRadiusTR;
+ public float cornerRadiusBL;
+ public float cornerRadiusBR;
+ public float alpha = 1;
+ public boolean visible = true;
+ public final Rect rect = new Rect();
+
+ private final float[] mFloatArray = new float[10];
+
+ public BlurRegion() {
+ }
+
+ public BlurRegion(BlurRegion other) {
+ rect.set(other.rect);
+ blurRadius = other.blurRadius;
+ alpha = other.alpha;
+ cornerRadiusTL = other.cornerRadiusTL;
+ cornerRadiusTR = other.cornerRadiusTR;
+ cornerRadiusBL = other.cornerRadiusBL;
+ cornerRadiusBR = other.cornerRadiusBR;
+ }
+
+ /**
+ * Serializes this class into a float array that's more JNI friendly.
+ */
+ public float[] toFloatArray() {
+ mFloatArray[0] = blurRadius;
+ mFloatArray[1] = alpha;
+ mFloatArray[2] = rect.left;
+ mFloatArray[3] = rect.top;
+ mFloatArray[4] = rect.right;
+ mFloatArray[5] = rect.bottom;
+ mFloatArray[6] = cornerRadiusTL;
+ mFloatArray[7] = cornerRadiusTR;
+ mFloatArray[8] = cornerRadiusBL;
+ mFloatArray[9] = cornerRadiusBR;
+ return mFloatArray;
+ }
+
+ @Override
+ public String toString() {
+ return "BlurRegion{"
+ + "blurRadius=" + blurRadius
+ + ", corners={" + cornerRadiusTL
+ + "," + cornerRadiusTR
+ + "," + cornerRadiusBL
+ + "," + cornerRadiusBR
+ + "}, alpha=" + alpha
+ + ", rect=" + rect
+ + "}";
+ }
+ }
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 14ba699933f0..9d24dff13175 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -187,6 +187,7 @@ import android.window.ClientWindowFrames;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.graphics.drawable.BackgroundBlurDrawable;
import com.android.internal.inputmethod.InputMethodDebug;
import com.android.internal.os.IResultReceiver;
import com.android.internal.os.SomeArgs;
@@ -654,6 +655,9 @@ public final class ViewRootImpl implements ViewParent,
private ScrollCaptureConnection mScrollCaptureConnection;
+ private final BackgroundBlurDrawable.Aggregator mBlurRegionAggregator =
+ new BackgroundBlurDrawable.Aggregator(this);
+
/**
* @return {@link ImeFocusController} for this instance.
*/
@@ -1886,8 +1890,10 @@ public final class ViewRootImpl implements ViewParent,
mSurface.release();
mSurfaceControl.release();
- // We should probably add an explicit dispose.
- mBlastBufferQueue = null;
+ if (mBlastBufferQueue != null) {
+ mBlastBufferQueue.destroy();
+ mBlastBufferQueue = null;
+ }
}
/**
@@ -3819,6 +3825,8 @@ public final class ViewRootImpl implements ViewParent,
private HardwareRenderer.FrameCompleteCallback createFrameCompleteCallback(Handler handler,
boolean reportNextDraw, ArrayList<Runnable> commitCallbacks) {
return frameNr -> {
+ mBlurRegionAggregator.dispatchBlurTransactionIfNeeded(frameNr);
+
// Use a new transaction here since mRtBLASTSyncTransaction can only be accessed by
// the render thread and mSurfaceChangedTransaction can only be accessed by the UI
// thread. The temporary transaction is used so mRtBLASTSyncTransaction can be merged
@@ -3849,7 +3857,8 @@ public final class ViewRootImpl implements ViewParent,
.captureFrameCommitCallbacks();
final boolean needFrameCompleteCallback =
mNextDrawUseBLASTSyncTransaction || mReportNextDraw
- || (commitCallbacks != null && commitCallbacks.size() > 0);
+ || (commitCallbacks != null && commitCallbacks.size() > 0)
+ || mBlurRegionAggregator.hasRegions();
if (needFrameCompleteCallback) {
mAttachInfo.mThreadedRenderer.setFrameCompleteCallback(
createFrameCompleteCallback(mAttachInfo.mHandler, mReportNextDraw,
@@ -9915,6 +9924,36 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ /**
+ * Sends a list of blur regions to SurfaceFlinger, tagged with a frame.
+ *
+ * @param regionCopy List of regions
+ * @param frameNumber Frame where it should be applied (or current when using BLAST)
+ */
+ public void dispatchBlurRegions(float[][] regionCopy, long frameNumber) {
+ final SurfaceControl surfaceControl = getSurfaceControl();
+ if (!surfaceControl.isValid()) {
+ return;
+ }
+ if (useBLAST()) {
+ synchronized (getBlastTransactionLock()) {
+ getBLASTSyncTransaction().setBlurRegions(surfaceControl, regionCopy);
+ }
+ } else {
+ SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
+ transaction.setBlurRegions(surfaceControl, regionCopy);
+ transaction.deferTransactionUntil(surfaceControl, getSurfaceControl(), frameNumber);
+ transaction.apply();
+ }
+ }
+
+ /**
+ * Creates a background blur drawable for the backing {@link Surface}.
+ */
+ public BackgroundBlurDrawable createBackgroundBlurDrawable() {
+ return mBlurRegionAggregator.createBackgroundBlurDrawable(mContext);
+ }
+
SurfaceControl.Transaction getBLASTSyncTransaction() {
return mRtBLASTSyncTransaction;
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index f7578abfe4f0..b4a841f8fdb0 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -17,6 +17,27 @@
package android.view;
import static android.content.pm.ActivityInfo.COLOR_MODE_DEFAULT;
+import static android.view.View.STATUS_BAR_DISABLE_BACK;
+import static android.view.View.STATUS_BAR_DISABLE_CLOCK;
+import static android.view.View.STATUS_BAR_DISABLE_EXPAND;
+import static android.view.View.STATUS_BAR_DISABLE_HOME;
+import static android.view.View.STATUS_BAR_DISABLE_NOTIFICATION_ALERTS;
+import static android.view.View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS;
+import static android.view.View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER;
+import static android.view.View.STATUS_BAR_DISABLE_RECENT;
+import static android.view.View.STATUS_BAR_DISABLE_SEARCH;
+import static android.view.View.STATUS_BAR_DISABLE_SYSTEM_INFO;
+import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
+import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE;
+import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
+import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
+import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
+import static android.view.View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR;
+import static android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+import static android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE;
+import static android.view.View.SYSTEM_UI_FLAG_VISIBLE;
import static android.view.WindowInsets.Side.BOTTOM;
import static android.view.WindowInsets.Side.LEFT;
import static android.view.WindowInsets.Side.RIGHT;
@@ -2725,6 +2746,38 @@ public interface WindowManager extends ViewManager {
public int preferredDisplayModeId;
/**
+ * An internal annotation for flags that can be specified to {@link #systemUiVisibility}
+ * and {@link #subtreeSystemUiVisibility}.
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "" }, value = {
+ SYSTEM_UI_FLAG_VISIBLE,
+ SYSTEM_UI_FLAG_LOW_PROFILE,
+ SYSTEM_UI_FLAG_HIDE_NAVIGATION,
+ SYSTEM_UI_FLAG_FULLSCREEN,
+ SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR,
+ SYSTEM_UI_FLAG_LAYOUT_STABLE,
+ SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION,
+ SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN,
+ SYSTEM_UI_FLAG_IMMERSIVE,
+ SYSTEM_UI_FLAG_IMMERSIVE_STICKY,
+ SYSTEM_UI_FLAG_LIGHT_STATUS_BAR,
+ STATUS_BAR_DISABLE_EXPAND,
+ STATUS_BAR_DISABLE_NOTIFICATION_ICONS,
+ STATUS_BAR_DISABLE_NOTIFICATION_ALERTS,
+ STATUS_BAR_DISABLE_NOTIFICATION_TICKER,
+ STATUS_BAR_DISABLE_SYSTEM_INFO,
+ STATUS_BAR_DISABLE_HOME,
+ STATUS_BAR_DISABLE_BACK,
+ STATUS_BAR_DISABLE_CLOCK,
+ STATUS_BAR_DISABLE_RECENT,
+ STATUS_BAR_DISABLE_SEARCH,
+ })
+ public @interface SystemUiVisibilityFlags {}
+
+ /**
* Control the visibility of the status bar.
*
* @see View#STATUS_BAR_VISIBLE
@@ -2733,6 +2786,7 @@ public interface WindowManager extends ViewManager {
* @deprecated SystemUiVisibility flags are deprecated. Use {@link WindowInsetsController}
* instead.
*/
+ @SystemUiVisibilityFlags
@Deprecated
public int systemUiVisibility;
@@ -2741,6 +2795,7 @@ public interface WindowManager extends ViewManager {
* The ui visibility as requested by the views in this hierarchy.
* the combined value should be systemUiVisibility | subtreeSystemUiVisibility.
*/
+ @SystemUiVisibilityFlags
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int subtreeSystemUiVisibility;
@@ -2754,7 +2809,6 @@ public interface WindowManager extends ViewManager {
@UnsupportedAppUsage
public boolean hasSystemUiListeners;
-
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(
@@ -2921,6 +2975,19 @@ public interface WindowManager extends ViewManager {
public static final int INPUT_FEATURE_DISABLE_USER_ACTIVITY = 0x00000004;
/**
+ * An internal annotation for flags that can be specified to {@link #inputFeatures}.
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "INPUT_FEATURE_" }, value = {
+ INPUT_FEATURE_DISABLE_POINTER_GESTURES,
+ INPUT_FEATURE_NO_INPUT_CHANNEL,
+ INPUT_FEATURE_DISABLE_USER_ACTIVITY,
+ })
+ public @interface InputFeatureFlags {}
+
+ /**
* Control special features of the input subsystem.
*
* @see #INPUT_FEATURE_DISABLE_POINTER_GESTURES
@@ -2928,6 +2995,7 @@ public interface WindowManager extends ViewManager {
* @see #INPUT_FEATURE_DISABLE_USER_ACTIVITY
* @hide
*/
+ @InputFeatureFlags
@UnsupportedAppUsage
public int inputFeatures;
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index f44ab3ac2ed1..de4554b9e624 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -243,7 +243,7 @@ public interface InputMethod {
@MainThread
default void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
@NonNull EditorInfo editorInfo, boolean restarting,
- @NonNull IBinder startInputToken, boolean shouldPreRenderIme) {
+ @NonNull IBinder startInputToken) {
if (restarting) {
restartInput(inputConnection, editorInfo);
} else {
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 1931174d4bb8..6243c63531eb 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -489,7 +489,6 @@ public final class InputMethodManager {
static final int MSG_TIMEOUT_INPUT_EVENT = 6;
static final int MSG_FLUSH_INPUT_EVENT = 7;
static final int MSG_REPORT_FULLSCREEN_MODE = 10;
- static final int MSG_REPORT_PRE_RENDERED = 15;
static final int MSG_APPLY_IME_VISIBILITY = 20;
static final int MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX = 30;
@@ -584,17 +583,6 @@ public final class InputMethodManager {
mServedConnecting = true;
servedView = getServedViewLocked();
}
- if (servedView != null && servedView.getHandler() != null) {
- // Make sure View checks should be on the UI thread.
- servedView.getHandler().post(() -> {
- if (!servedView.onCheckIsTextEditor()) {
- // servedView has changed and it's not editable.
- synchronized (mH) {
- maybeCallServedViewChangedLocked(null);
- }
- }
- });
- }
return startInputInner(startInputReason,
focusedView != null ? focusedView.getWindowToken() : null, startInputFlags,
softInputMode, windowFlags);
@@ -919,15 +907,6 @@ public final class InputMethodManager {
}
return;
}
- case MSG_REPORT_PRE_RENDERED: {
- synchronized (mH) {
- if (mImeInsetsConsumer != null) {
- mImeInsetsConsumer.onPreRendered((EditorInfo) msg.obj);
- }
- }
- return;
-
- }
case MSG_APPLY_IME_VISIBILITY: {
synchronized (mH) {
if (mImeInsetsConsumer != null) {
@@ -1100,12 +1079,6 @@ public final class InputMethodManager {
}
@Override
- public void reportPreRendered(EditorInfo info) {
- mH.obtainMessage(MSG_REPORT_PRE_RENDERED, 0, 0, info)
- .sendToTarget();
- }
-
- @Override
public void applyImeVisibility(boolean setVisible) {
mH.obtainMessage(MSG_APPLY_IME_VISIBILITY, setVisible ? 1 : 0, 0)
.sendToTarget();
@@ -1981,7 +1954,7 @@ public final class InputMethodManager {
// Hook 'em up and let 'er rip.
mCurrentTextBoxAttribute = tba;
- maybeCallServedViewChangedLocked(tba);
+
mServedConnecting = false;
if (mServedInputConnectionWrapper != null) {
mServedInputConnectionWrapper.deactivate();
@@ -3141,12 +3114,6 @@ public final class InputMethodManager {
}
}
- private void maybeCallServedViewChangedLocked(EditorInfo tba) {
- if (mImeInsetsConsumer != null) {
- mImeInsetsConsumer.onServedEditorChanged(tba);
- }
- }
-
/**
* <p>This is used for CTS test only. Do not use this method outside of CTS package.<p/>
* @return the ID of this display which this {@link InputMethodManager} resides
diff --git a/core/java/android/window/DisplayAreaOrganizer.java b/core/java/android/window/DisplayAreaOrganizer.java
index 6ec093e045fa..bc3e35ccb8a9 100644
--- a/core/java/android/window/DisplayAreaOrganizer.java
+++ b/core/java/android/window/DisplayAreaOrganizer.java
@@ -88,9 +88,11 @@ public class DisplayAreaOrganizer extends WindowOrganizer {
public static final int FEATURE_VENDOR_FIRST = FEATURE_SYSTEM_LAST + 1;
/**
- * Registers a DisplayAreaOrganizer to manage display areas for a given feature.
+ * Registers a DisplayAreaOrganizer to manage display areas for a given feature. A feature can
+ * not be registered by multiple organizers at the same time.
*
* @return a list of display areas that should be managed by the organizer.
+ * @throws IllegalStateException if the feature has already been registered.
*/
@RequiresPermission(android.Manifest.permission.MANAGE_ACTIVITY_TASKS)
@CallSuper
diff --git a/core/java/android/window/IDisplayAreaOrganizerController.aidl b/core/java/android/window/IDisplayAreaOrganizerController.aidl
index 8943847073c7..edabcf8ad0de 100644
--- a/core/java/android/window/IDisplayAreaOrganizerController.aidl
+++ b/core/java/android/window/IDisplayAreaOrganizerController.aidl
@@ -24,9 +24,11 @@ import android.window.IDisplayAreaOrganizer;
interface IDisplayAreaOrganizerController {
/**
- * Registers a DisplayAreaOrganizer to manage display areas for a given feature.
+ * Registers a DisplayAreaOrganizer to manage display areas for a given feature. A feature can
+ * not be registered by multiple organizers at the same time.
*
* @return a list of display areas that should be managed by the organizer.
+ * @throws IllegalStateException if the feature has already been registered.
*/
ParceledListSlice<DisplayAreaAppearedInfo> registerOrganizer(in IDisplayAreaOrganizer organizer,
int displayAreaFeature);
diff --git a/core/java/com/android/internal/BrightnessSynchronizer.java b/core/java/com/android/internal/BrightnessSynchronizer.java
index c98477e8c343..15463cb34157 100644
--- a/core/java/com/android/internal/BrightnessSynchronizer.java
+++ b/core/java/com/android/internal/BrightnessSynchronizer.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.UserHandle;
@@ -55,7 +56,7 @@ public class BrightnessSynchronizer {
private final Queue<Object> mWriteHistory = new LinkedList<>();
- private final Handler mHandler = new Handler() {
+ private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
@@ -72,7 +73,6 @@ public class BrightnessSynchronizer {
}
};
-
public BrightnessSynchronizer(Context context) {
final BrightnessSyncObserver mBrightnessSyncObserver;
mContext = context;
diff --git a/core/java/com/android/internal/app/ChooserFlags.java b/core/java/com/android/internal/app/ChooserFlags.java
index 3e26679e28a4..1a93f1bc947f 100644
--- a/core/java/com/android/internal/app/ChooserFlags.java
+++ b/core/java/com/android/internal/app/ChooserFlags.java
@@ -33,7 +33,7 @@ public class ChooserFlags {
*/
public static final boolean USE_SERVICE_TARGETS_FOR_DIRECT_TARGETS =
DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.SHARE_USE_SERVICE_TARGETS, true);
+ SystemUiDeviceConfigFlags.SHARE_USE_SERVICE_TARGETS, false);
/**
* Whether to use {@link AppPredictionManager} to query for direct share targets (as opposed to
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index a2af4d6cf456..777534e72d73 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -430,6 +430,11 @@ public final class SystemUiDeviceConfigFlags {
public static final String USE_BACK_GESTURE_ML_MODEL = "use_back_gesture_ml_model";
/**
+ * (string) The name of the ML model for Back Gesture.
+ */
+ public static final String BACK_GESTURE_ML_MODEL_NAME = "back_gesture_ml_model_name";
+
+ /**
* (float) Threshold for Back Gesture ML model prediction.
*/
public static final String BACK_GESTURE_ML_MODEL_THRESHOLD = "back_gesture_ml_model_threshold";
diff --git a/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java b/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java
new file mode 100644
index 000000000000..6ea9e665c009
--- /dev/null
+++ b/core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.graphics.drawable;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
+import android.graphics.Rect;
+import android.graphics.RenderNode;
+import android.graphics.drawable.Drawable;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.view.SurfaceControl;
+import android.view.ViewRootImpl;
+
+import com.android.internal.R;
+
+/**
+ * A drawable that keeps track of a blur region, pokes a hole under it, and propagates its state
+ * to SurfaceFlinger.
+ */
+public final class BackgroundBlurDrawable extends Drawable {
+
+ private static final String TAG = BackgroundBlurDrawable.class.getSimpleName();
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private final Aggregator mAggregator;
+ private final RenderNode mRenderNode;
+ private final Paint mPaint = new Paint();
+ private final Path mRectPath = new Path();
+ private final float[] mTmpRadii = new float[8];
+ private final SurfaceControl.BlurRegion mBlurRegion = new SurfaceControl.BlurRegion();
+
+ // This will be called from a thread pool.
+ private final RenderNode.PositionUpdateListener mPositionUpdateListener =
+ new RenderNode.PositionUpdateListener() {
+ @Override
+ public void positionChanged(long frameNumber, int left, int top, int right,
+ int bottom) {
+ synchronized (mAggregator) {
+ mBlurRegion.rect.set(left, top, right, bottom);
+ mAggregator.onBlurRegionUpdated(BackgroundBlurDrawable.this, mBlurRegion);
+ }
+ }
+
+ @Override
+ public void positionLost(long frameNumber) {
+ synchronized (mAggregator) {
+ mBlurRegion.rect.setEmpty();
+ mAggregator.onBlurRegionUpdated(BackgroundBlurDrawable.this, mBlurRegion);
+ }
+ }
+ };
+
+ private BackgroundBlurDrawable(Aggregator aggregator) {
+ mAggregator = aggregator;
+ mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
+ mRenderNode = new RenderNode("BackgroundBlurDrawable");
+ mRenderNode.addPositionUpdateListener(mPositionUpdateListener);
+ }
+
+ @Override
+ public void draw(@NonNull Canvas canvas) {
+ if (mRectPath.isEmpty() || !isVisible() || getAlpha() == 0) {
+ return;
+ }
+ canvas.drawPath(mRectPath, mPaint);
+ canvas.drawRenderNode(mRenderNode);
+ }
+
+ @Override
+ public boolean setVisible(boolean visible, boolean restart) {
+ boolean changed = super.setVisible(visible, restart);
+ if (changed) {
+ mBlurRegion.visible = visible;
+ }
+ return changed;
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ mBlurRegion.alpha = alpha / 255f;
+ invalidateSelf();
+ }
+
+ /**
+ * Blur radius in pixels.
+ */
+ public void setBlurRadius(int blurRadius) {
+ mBlurRegion.blurRadius = blurRadius;
+ invalidateSelf();
+ }
+
+ /**
+ * Sets the corner radius, in degrees.
+ */
+ public void setCornerRadius(float cornerRadius) {
+ setCornerRadius(cornerRadius, cornerRadius, cornerRadius, cornerRadius);
+ }
+
+ /**
+ * Sets the corner radius in degrees.
+ * @param cornerRadiusTL top left radius.
+ * @param cornerRadiusTR top right radius.
+ * @param cornerRadiusBL bottom left radius.
+ * @param cornerRadiusBR bottom right radius.
+ */
+ public void setCornerRadius(float cornerRadiusTL, float cornerRadiusTR, float cornerRadiusBL,
+ float cornerRadiusBR) {
+ synchronized (mAggregator) {
+ mBlurRegion.cornerRadiusTL = cornerRadiusTL;
+ mBlurRegion.cornerRadiusTR = cornerRadiusTR;
+ mBlurRegion.cornerRadiusBL = cornerRadiusBL;
+ mBlurRegion.cornerRadiusBR = cornerRadiusBR;
+ }
+ updatePath();
+ invalidateSelf();
+ }
+
+ @Override
+ public void setBounds(int left, int top, int right, int bottom) {
+ super.setBounds(left, top, right, bottom);
+ mRenderNode.setPosition(left, top, right, bottom);
+ updatePath();
+ }
+
+ private void updatePath() {
+ synchronized (mAggregator) {
+ mTmpRadii[0] = mTmpRadii[1] = mBlurRegion.cornerRadiusTL;
+ mTmpRadii[2] = mTmpRadii[3] = mBlurRegion.cornerRadiusTR;
+ mTmpRadii[4] = mTmpRadii[5] = mBlurRegion.cornerRadiusBL;
+ mTmpRadii[6] = mTmpRadii[7] = mBlurRegion.cornerRadiusBR;
+ }
+ mRectPath.reset();
+ if (getAlpha() == 0 || !isVisible()) {
+ return;
+ }
+ Rect bounds = getBounds();
+ mRectPath.addRoundRect(bounds.left, bounds.top, bounds.right, bounds.bottom, mTmpRadii,
+ Path.Direction.CW);
+ }
+
+ @Override
+ public void setColorFilter(@Nullable ColorFilter colorFilter) {
+ throw new IllegalArgumentException("not implemented");
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ /**
+ * Responsible for keeping track of all blur regions of a {@link ViewRootImpl} and posting a
+ * message when it's time to propagate them.
+ */
+ public static final class Aggregator {
+
+ private final ArrayMap<BackgroundBlurDrawable, SurfaceControl.BlurRegion> mBlurRegions =
+ new ArrayMap<>();
+ private final ViewRootImpl mViewRoot;
+ private float[][] mTmpBlurRegionsArray;
+ private boolean mNeedsUpdate;
+
+ public Aggregator(ViewRootImpl viewRoot) {
+ mViewRoot = viewRoot;
+ }
+
+ /**
+ * Creates a blur region with default radius.
+ */
+ public BackgroundBlurDrawable createBackgroundBlurDrawable(Context context) {
+ BackgroundBlurDrawable drawable = new BackgroundBlurDrawable(this);
+ drawable.setBlurRadius(context.getResources().getDimensionPixelSize(
+ R.dimen.default_background_blur_radius));
+ return drawable;
+ }
+
+ /**
+ * Called from RenderThread only, already locked.
+ * @param drawable
+ * @param blurRegion
+ */
+ void onBlurRegionUpdated(BackgroundBlurDrawable drawable,
+ SurfaceControl.BlurRegion blurRegion) {
+ if (blurRegion.rect.isEmpty() || blurRegion.alpha == 0 || blurRegion.blurRadius == 0
+ || !blurRegion.visible) {
+ mBlurRegions.remove(drawable);
+ mNeedsUpdate = true;
+ if (DEBUG) {
+ Log.d(TAG, "Remove " + blurRegion);
+ }
+ } else {
+ mBlurRegions.put(drawable, blurRegion);
+ mNeedsUpdate = true;
+ if (DEBUG) {
+ Log.d(TAG, "Update " + blurRegion);
+ }
+ }
+ }
+
+ /**
+ * If there are any blur regions visible on the screen at the moment.
+ */
+ public boolean hasRegions() {
+ return mBlurRegions.size() > 0;
+ }
+
+ /**
+ * Dispatch blur updates, if there were any.
+ * @param frameNumber Frame where the update should happen.
+ */
+ public void dispatchBlurTransactionIfNeeded(long frameNumber) {
+ synchronized (this) {
+ if (!mNeedsUpdate) {
+ return;
+ }
+ mNeedsUpdate = false;
+
+ if (mTmpBlurRegionsArray == null
+ || mTmpBlurRegionsArray.length != mBlurRegions.size()) {
+ mTmpBlurRegionsArray = new float[mBlurRegions.size()][];
+ }
+ if (DEBUG) {
+ Log.d(TAG, "onBlurRegionUpdated will dispatch " + mTmpBlurRegionsArray.length
+ + " regions for frame " + frameNumber);
+ }
+ for (int i = 0; i < mTmpBlurRegionsArray.length; i++) {
+ mTmpBlurRegionsArray[i] = mBlurRegions.valueAt(i).toFloatArray();
+ }
+
+ mViewRoot.dispatchBlurRegions(mTmpBlurRegionsArray, frameNumber);
+ }
+ }
+ }
+}
diff --git a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
index 9a226860831a..f0e26cf4bbcf 100644
--- a/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
+++ b/core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl
@@ -17,7 +17,6 @@
package com.android.internal.inputmethod;
import android.net.Uri;
-import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.inputmethod.IInputContentUriToken;
@@ -40,6 +39,5 @@ interface IInputMethodPrivilegedOperations {
boolean switchToNextInputMethod(boolean onlyCurrentIme);
boolean shouldOfferSwitchingToNextInputMethod();
void notifyUserAction();
- void reportPreRendered(in EditorInfo info);
void applyImeVisibility(IBinder showOrHideInputToken, boolean setVisible);
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
index 9b1299ebe54c..d6730e8b0bdb 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperations.java
@@ -24,7 +24,6 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
-import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.annotations.GuardedBy;
@@ -351,24 +350,6 @@ public final class InputMethodPrivilegedOperations {
}
/**
- * Calls {@link IInputMethodPrivilegedOperations#reportPreRendered(info)}.
- *
- * @param info {@link EditorInfo} of the currently rendered {@link TextView}.
- */
- @AnyThread
- public void reportPreRendered(EditorInfo info) {
- final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
- if (ops == null) {
- return;
- }
- try {
- ops.reportPreRendered(info);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Calls {@link IInputMethodPrivilegedOperations#applyImeVisibility(IBinder, boolean)}.
*
* @param showOrHideInputToken placeholder token that maps to window requesting
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index 85dc2aea4b1c..c0d46f632500 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -176,7 +176,7 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
* Trigger the prefetto daemon.
*/
public void triggerPerfetto() {
- InteractionJankMonitor.getInstance().trigger();
+ InteractionJankMonitor.getInstance().trigger(mSession);
}
/**
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 3624f0d34725..ba07863a292d 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -319,11 +319,11 @@ public class InteractionJankMonitor {
* Trigger the perfetto daemon to collect and upload data.
*/
@VisibleForTesting
- public void trigger() {
+ public void trigger(Session session) {
synchronized (this) {
if (!mInitialized) return;
mWorker.getThreadHandler().post(
- () -> PerfettoTrigger.trigger(PerfettoTrigger.TRIGGER_TYPE_JANK));
+ () -> PerfettoTrigger.trigger(session.getPerfettoTrigger()));
}
}
@@ -350,9 +350,12 @@ public class InteractionJankMonitor {
return getStatsdInteractionType() != NO_STATSD_LOGGING;
}
+ public String getPerfettoTrigger() {
+ return String.format("interaction-jank-monitor-%d", mCujType);
+ }
+
public String getName() {
return "Cuj<" + getCuj() + ">";
}
}
-
}
diff --git a/core/java/com/android/internal/jank/PerfettoTrigger.java b/core/java/com/android/internal/jank/PerfettoTrigger.java
index 6c8d3cdcf5ae..643d24a51b58 100644
--- a/core/java/com/android/internal/jank/PerfettoTrigger.java
+++ b/core/java/com/android/internal/jank/PerfettoTrigger.java
@@ -17,15 +17,12 @@
//TODO (165884885): Make PerfettoTrigger more generic and move it to another package.
package com.android.internal.jank;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.util.Log;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
/**
* A trigger implementation with perfetto backend.
@@ -35,23 +32,14 @@ public class PerfettoTrigger {
private static final String TAG = PerfettoTrigger.class.getSimpleName();
private static final boolean DEBUG = false;
private static final String TRIGGER_COMMAND = "/system/bin/trigger_perfetto";
- private static final String[] TRIGGER_TYPE_NAMES = new String[] { "jank-tracker" };
- public static final int TRIGGER_TYPE_JANK = 0;
-
- /** @hide */
- @IntDef({
- TRIGGER_TYPE_JANK
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface TriggerType {}
/**
- * @param type the trigger type
+ * @param triggerName The name of the trigger. Must match the value defined in the AOT
+ * Perfetto config.
*/
- public static void trigger(@NonNull @TriggerType int type) {
+ public static void trigger(String triggerName) {
try {
- Token token = new Token(type, TRIGGER_TYPE_NAMES[type]);
- ProcessBuilder pb = new ProcessBuilder(TRIGGER_COMMAND, token.getName());
+ ProcessBuilder pb = new ProcessBuilder(TRIGGER_COMMAND, triggerName);
if (DEBUG) {
StringBuilder sb = new StringBuilder();
for (String arg : pb.command()) {
@@ -64,7 +52,7 @@ public class PerfettoTrigger {
readConsoleOutput(process);
}
} catch (IOException | InterruptedException e) {
- Log.w(TAG, "Failed to trigger " + type, e);
+ Log.w(TAG, "Failed to trigger " + triggerName, e);
}
}
@@ -82,34 +70,4 @@ public class PerfettoTrigger {
Log.d(TAG, "err message=" + errLine.toString());
}
}
-
- /**
- * Token which is used to trigger perfetto.
- */
- public static class Token {
- private int mType;
- private String mName;
-
- Token(@TriggerType int type, String name) {
- mType = type;
- mName = name;
- }
-
- /**
- * Get trigger type.
- * @return trigger type, should be @TriggerType
- */
- public int getType() {
- return mType;
- }
-
- /**
- * Get name of this token as the argument while triggering perfetto.
- * @return name
- */
- public String getName() {
- return mName;
- }
- }
-
}
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index 40e4f4d6ad12..c33637353984 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -45,7 +45,7 @@ oneway interface IInputMethod {
void unbindInput();
void startInput(in IBinder startInputToken, in IInputContext inputContext, int missingMethods,
- in EditorInfo attribute, boolean restarting, boolean preRenderImeViews);
+ in EditorInfo attribute, boolean restarting);
void createSession(in InputChannel channel, IInputSessionCallback callback);
diff --git a/core/java/com/android/internal/view/IInputMethodClient.aidl b/core/java/com/android/internal/view/IInputMethodClient.aidl
index c9443b002133..1145f5183206 100644
--- a/core/java/com/android/internal/view/IInputMethodClient.aidl
+++ b/core/java/com/android/internal/view/IInputMethodClient.aidl
@@ -16,8 +16,6 @@
package com.android.internal.view;
-import android.view.inputmethod.EditorInfo;
-
import com.android.internal.view.InputBindResult;
/**
@@ -30,7 +28,6 @@ oneway interface IInputMethodClient {
void setActive(boolean active, boolean fullscreen);
void scheduleStartInputIfNecessary(boolean fullscreen);
void reportFullscreenMode(boolean fullscreen);
- void reportPreRendered(in EditorInfo info);
void applyImeVisibility(boolean setVisible);
void updateActivityViewToScreenMatrix(int bindSequence, in float[] matrixValues);
void setImeTraceEnabled(boolean enabled);
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index ce8b59941a5a..832c0665488e 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -256,11 +256,13 @@ static jfloatArray obtainPackedAxisValuesArray(JNIEnv* env, uint32_t minSize,
}
static void pointerCoordsFromNative(JNIEnv* env, const PointerCoords* rawPointerCoords,
- float xOffset, float yOffset, jobject outPointerCoordsObj) {
- env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.x,
- rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_X) + xOffset);
- env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.y,
- rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_Y) + yOffset);
+ ui::Transform transform, jobject outPointerCoordsObj) {
+ float rawX = rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_X);
+ float rawY = rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_Y);
+ vec2 transformed = transform.transform(rawX, rawY);
+
+ env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.x, transformed.x);
+ env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.y, transformed.y);
env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.pressure,
rawPointerCoords->getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
env->SetFloatField(outPointerCoordsObj, gPointerCoordsClassInfo.size,
@@ -433,8 +435,7 @@ static void android_view_MotionEvent_nativeGetPointerCoords(JNIEnv* env, jclass
}
rawPointerCoords = event->getHistoricalRawPointerCoords(pointerIndex, historyPos);
}
- pointerCoordsFromNative(env, rawPointerCoords, event->getXOffset(), event->getYOffset(),
- outPointerCoordsObj);
+ pointerCoordsFromNative(env, rawPointerCoords, event->getTransform(), outPointerCoordsObj);
}
static void android_view_MotionEvent_nativeGetPointerProperties(JNIEnv* env, jclass clazz,
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 17ced9f78f25..f1ec85a8570f 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -40,6 +40,7 @@
#include <private/gui/ComposerService.h>
#include <stdio.h>
#include <system/graphics.h>
+#include <ui/BlurRegion.h>
#include <ui/ConfigStoreTypes.h>
#include <ui/DeviceProductInfo.h>
#include <ui/DisplayConfig.h>
@@ -522,6 +523,43 @@ static void nativeSetGeometry(JNIEnv* env, jclass clazz, jlong transactionObj, j
transaction->setGeometry(ctrl, source, dst, orientation);
}
+static void nativeSetBlurRegions(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jobjectArray regions, jint regionsLength) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+
+ std::vector<BlurRegion> blurRegionVector;
+ const int size = regionsLength;
+ float region[10];
+ for (int i = 0; i < size; i++) {
+ jfloatArray regionArray = (jfloatArray)env->GetObjectArrayElement(regions, i);
+ env->GetFloatArrayRegion(regionArray, 0, 10, region);
+ float blurRadius = region[0];
+ float alpha = region[1];
+ float left = region[2];
+ float top = region[3];
+ float right = region[4];
+ float bottom = region[5];
+ float cornerRadiusTL = region[6];
+ float cornerRadiusTR = region[7];
+ float cornerRadiusBL = region[8];
+ float cornerRadiusBR = region[9];
+
+ blurRegionVector.push_back(BlurRegion{.blurRadius = static_cast<uint32_t>(blurRadius),
+ .cornerRadiusTL = cornerRadiusTL,
+ .cornerRadiusTR = cornerRadiusTR,
+ .cornerRadiusBL = cornerRadiusBL,
+ .cornerRadiusBR = cornerRadiusBR,
+ .alpha = alpha,
+ .left = static_cast<int>(left),
+ .top = static_cast<int>(top),
+ .right = static_cast<int>(right),
+ .bottom = static_cast<int>(bottom)});
+ }
+
+ transaction->setBlurRegions(ctrl, blurRegionVector);
+}
+
static void nativeSetSize(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jint w, jint h) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -1626,6 +1664,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetBackgroundBlurRadius },
{"nativeSetLayerStack", "(JJI)V",
(void*)nativeSetLayerStack },
+ {"nativeSetBlurRegions", "(JJ[[FI)V",
+ (void*)nativeSetBlurRegions },
{"nativeSetShadowRadius", "(JJF)V",
(void*)nativeSetShadowRadius },
{"nativeSetFrameRate", "(JJFI)V",
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 45f64f9a92af..d46da876a6f4 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -779,6 +779,26 @@ enum Action {
// CATEGORY: SETTINGS
// OS: S
ACTION_COLUMBUS_ACTION_NOTIFICATION_SHADE = 1746;
+
+ // ACTION: Settings > System > Gestures > Double tap > Require harder taps
+ // CATEGORY: SETTINGS
+ // OS: S
+ ACTION_COLUMBUS_LOW_SENSITIVITY = 1747;
+
+ // OPEN: Columbus Gesture training intro in Settings
+ // CATEGORY: SETTINGS
+ // OS: S
+ SETTINGS_COLUMBUS_GESTURE_TRAINING_INTRO = 1748;
+
+ // OPEN: Columbus Gesture training enrolling in Settings
+ // CATEGORY: SETTINGS
+ // OS: S
+ SETTINGS_COLUMBUS_GESTURE_TRAINING_ENROLLING = 1749;
+
+ // OPEN: Columbus Gesture training finished in Settings
+ // CATEGORY: SETTINGS
+ // OS: S
+ SETTINGS_COLUMBUS_GESTURE_TRAINING_FINISHED = 1750;
}
/**
diff --git a/core/proto/android/inputmethodservice/inputmethodservice.proto b/core/proto/android/inputmethodservice/inputmethodservice.proto
index 3b4ebb5d73e7..e5d171361695 100644
--- a/core/proto/android/inputmethodservice/inputmethodservice.proto
+++ b/core/proto/android/inputmethodservice/inputmethodservice.proto
@@ -39,8 +39,8 @@ message InputMethodServiceProto {
optional .android.view.inputmethod.EditorInfoProto input_editor_info = 13;
optional bool show_input_requested = 14;
optional bool last_show_input_requested = 15;
- optional bool can_pre_render = 16;
- optional bool is_pre_rendered = 17;
+ reserved 16; // can_pre_render
+ reserved 17; // is_pre_rendered
optional int32 show_input_flags = 18;
optional int32 candidates_visibility = 19;
optional bool fullscreen_applied = 20;
diff --git a/core/proto/android/server/alarm/alarmmanagerservice.proto b/core/proto/android/server/alarm/alarmmanagerservice.proto
index e1240245d20f..8fe1bfc81702 100644
--- a/core/proto/android/server/alarm/alarmmanagerservice.proto
+++ b/core/proto/android/server/alarm/alarmmanagerservice.proto
@@ -144,6 +144,8 @@ message AlarmManagerServiceDumpProto {
repeated IdleDispatchEntryProto allow_while_idle_dispatches = 40;
repeated WakeupEventProto recent_wakeup_history = 41;
+
+ repeated AlarmProto pending_alarms = 42;
}
// This is a soft wrapper for alarm clock information. It is not representative
diff --git a/core/proto/android/stats/tls/enums.proto b/core/proto/android/stats/tls/enums.proto
index 0ae87ee1d89b..a64137d7caa9 100644
--- a/core/proto/android/stats/tls/enums.proto
+++ b/core/proto/android/stats/tls/enums.proto
@@ -20,11 +20,11 @@ package android.stats.tls;
// external/conscrypt/{android,platform}/src/main/java/org/conscrypt/Platform.java
enum Protocol {
UNKNOWN_PROTO = 0;
- SSLv3 = 1;
- TLSv1 = 2;
- TLSv1_1 = 3;
- TLSv1_2 = 4;
- TLSv1_3 = 5;
+ SSL_V3 = 1;
+ TLS_V1 = 2;
+ TLS_V1_1 = 3;
+ TLS_V1_2 = 4;
+ TLS_V1_3 = 5;
}
// Cipher suites' ids are based on IANA's database:
diff --git a/core/proto/android/view/imeinsetssourceconsumer.proto b/core/proto/android/view/imeinsetssourceconsumer.proto
index 5bee81bdc7cd..1b9aff989cc8 100644
--- a/core/proto/android/view/imeinsetssourceconsumer.proto
+++ b/core/proto/android/view/imeinsetssourceconsumer.proto
@@ -28,6 +28,6 @@ option java_multiple_files = true;
*/
message ImeInsetsSourceConsumerProto {
optional InsetsSourceConsumerProto insets_source_consumer = 1;
- optional .android.view.inputmethod.EditorInfoProto focused_editor = 2;
+ reserved 2; // focused_editor = 2
optional bool is_requested_visible_awaiting_control = 3;
} \ No newline at end of file
diff --git a/core/proto/android/view/windowlayoutparams.proto b/core/proto/android/view/windowlayoutparams.proto
index 64e6da852529..4bb56f8acfa4 100644
--- a/core/proto/android/view/windowlayoutparams.proto
+++ b/core/proto/android/view/windowlayoutparams.proto
@@ -35,7 +35,7 @@ message WindowLayoutParamsProto {
optional int32 height = 5;
optional float horizontal_margin = 6;
optional float vertical_margin = 7;
- optional int32 gravity = 8; // TODO (b/160129453): Add IntDef
+ optional int32 gravity = 8;
optional int32 soft_input_mode = 9 [(.android.typedef) = "android.view.WindowManager.LayoutParams.SoftInputModeFlags"];
optional .android.graphics.PixelFormatProto.Format format = 10;
optional int32 window_animations = 11;
@@ -54,14 +54,14 @@ message WindowLayoutParamsProto {
optional float preferred_refresh_rate = 16;
optional int32 preferred_display_mode_id = 17;
optional bool has_system_ui_listeners = 18;
- optional uint32 input_feature_flags = 19; // TODO (b/160129453): Add IntDef
+ optional uint32 input_feature_flags = 19 [(.android.typedef) = "android.view.WindowManager.LayoutParams.InputFeatureFlags"];
optional int64 user_activity_timeout = 20;
optional DisplayProto.ColorMode color_mode = 23;
optional uint32 flags = 24 [(.android.typedef) = "android.view.WindowManager.LayoutParams.Flags"];
optional uint32 private_flags = 26 [(.android.typedef) = "android.view.WindowManager.LayoutParams.PrivateFlags"];
- optional uint32 system_ui_visibility_flags = 27; // TODO (b/160129453): Add IntDef
- optional uint32 subtree_system_ui_visibility_flags = 28; // TODO (b/160129453): Add IntDef
+ optional uint32 system_ui_visibility_flags = 27 [(.android.typedef) = "android.view.WindowManager.LayoutParams.SystemUiVisibilityFlags"];
+ optional uint32 subtree_system_ui_visibility_flags = 28 [(.android.typedef) = "android.view.WindowManager.LayoutParams.SystemUiVisibilityFlags"];
optional uint32 appearance = 29 [(.android.typedef) = "android.view.WindowInsetsController.Appearance"];
optional uint32 behavior = 30 [(.android.typedef) = "android.view.WindowInsetsController.Behavior"];
optional uint32 fit_insets_types = 31 [(.android.typedef) = "android.view.WindowInsets.Type.InsetsType"];
diff --git a/core/res/res/layout/notification_material_action_list.xml b/core/res/res/layout/notification_material_action_list.xml
index ffb9603529c2..bf66e69b52d3 100644
--- a/core/res/res/layout/notification_material_action_list.xml
+++ b/core/res/res/layout/notification_material_action_list.xml
@@ -44,6 +44,14 @@
</com.android.internal.widget.NotificationActionListLayout>
<ImageView
+ android:id="@+id/snooze_button"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_gravity="center_vertical|end"
+ android:visibility="gone"
+ android:scaleType="centerInside"
+ />
+ <ImageView
android:id="@+id/bubble_button"
android:layout_width="48dp"
android:layout_height="48dp"
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index d0fceb094355..393f229b75bb 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1129,10 +1129,8 @@
<string name="capital_off" msgid="7443704171014626777">"DESACTIVADO"</string>
<string name="checked" msgid="9179896827054513119">"seleccionado"</string>
<string name="not_checked" msgid="7972320087569023342">"no seleccionado"</string>
- <!-- no translation found for selected (6614607926197755875) -->
- <skip />
- <!-- no translation found for not_selected (410652016565864475) -->
- <skip />
+ <string name="selected" msgid="6614607926197755875">"seleccionado"</string>
+ <string name="not_selected" msgid="410652016565864475">"no seleccionado"</string>
<string name="whichApplication" msgid="5432266899591255759">"Completar acción utilizando"</string>
<string name="whichApplicationNamed" msgid="6969946041713975681">"Completar acción con %1$s"</string>
<string name="whichApplicationLabel" msgid="7852182961472531728">"Completar acción"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index a3b8f64bf57b..f7f6214cc2b2 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -940,7 +940,7 @@
<string name="double_tap_toast" msgid="7065519579174882778">"ટિપ: ઝૂમ વધારવા અને ઘટાડવા માટે બે વાર ટેપ કરો."</string>
<string name="autofill_this_form" msgid="3187132440451621492">"સ્વતઃભરણ"</string>
<string name="setup_autofill" msgid="5431369130866618567">"સ્વતઃભરણ સેટ કરો"</string>
- <string name="autofill_window_title" msgid="4379134104008111961">"<xliff:g id="SERVICENAME">%1$s</xliff:g> સાથે આપમેળે ભરો"</string>
+ <string name="autofill_window_title" msgid="4379134104008111961">"<xliff:g id="SERVICENAME">%1$s</xliff:g> સાથે ઑટોમૅટિક રીતે ભરો"</string>
<string name="autofill_address_name_separator" msgid="8190155636149596125">" "</string>
<string name="autofill_address_summary_name_format" msgid="3402882515222673691">"$1$2$3"</string>
<string name="autofill_address_summary_separator" msgid="760522655085707045">", "</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 82a27a85a264..53c92af2da3f 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -1798,7 +1798,7 @@
<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="4424488535318105801">"ដើម្បី​បង្កើនកម្រិត​ថាមពលថ្ម កម្មវិធី​សន្សំថ្ម៖\n\n• បើករចនាប័ទ្មងងឹត\n• បិទ ឬដាក់កំហិតលើ​សកម្មភាពផ្ទៃខាងក្រោយ ឥទ្ធិពល​ជារូបភាពមួយចំនួន និងមុខងារផ្សេងទៀត​ដូចជា “Ok Google” ជាដើម\n\n"<annotation id="url">"ស្វែងយល់​បន្ថែម"</annotation></string>
+ <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"ដើម្បី​បង្កើនកម្រិត​ថាមពលថ្ម មុខងារ​សន្សំ​ថ្ម៖\n\n• បើករចនាប័ទ្មងងឹត\n• បិទ ឬដាក់កំហិតលើ​សកម្មភាពផ្ទៃខាងក្រោយ ឥទ្ធិពល​ជារូបភាពមួយចំនួន និងមុខងារផ្សេងទៀត​ដូចជា “Hey Google” ជាដើម\n\n"<annotation id="url">"ស្វែងយល់​បន្ថែម"</annotation></string>
<string name="battery_saver_description" msgid="6794188153647295212">"ដើម្បី​បង្កើនកម្រិត​ថាមពលថ្ម មុខងារ​សន្សំថ្ម៖\n\n• បើករចនាប័ទ្មងងឹត\n• បិទ ឬដាក់កំហិតលើ​សកម្មភាពផ្ទៃខាងក្រោយ ឥទ្ធិពលរូបភាពមួយចំនួន និងមុខងារផ្សេងទៀត​ដូចជា “Ok Google” ជាដើម"</string>
<string name="data_saver_description" msgid="4995164271550590517">"ដើម្បីជួយកាត់បន្ថយការប្រើប្រាស់ទិន្នន័យ កម្មវិធីសន្សំសំចៃទិន្នន័យរារាំងកម្មវិធីមួយចំនួនមិនឲ្យបញ្ជូន ឬទទួលទិន្នន័យនៅផ្ទៃខាងក្រោយទេ។ កម្មវិធីដែលអ្នកកំពុងប្រើនាពេលបច្ចុប្បន្នអាចចូលប្រើប្រាស់​ទិន្នន័យបាន ប៉ុន្តែអាចនឹងមិនញឹកញាប់ដូចមុនទេ។ ឧទាហរណ៍ រូបភាពមិនបង្ហាញទេ លុះត្រាតែអ្នកប៉ះរូបភាពទាំងនោះ។"</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"បើកកម្មវិធីសន្សំសំចៃទិន្នន័យ?"</string>
@@ -2007,9 +2007,9 @@
<string name="notification_feedback_indicator" msgid="663476517711323016">"ផ្ដល់​មតិកែលម្អ"</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_off_notification_title" msgid="7637255960468032515">"កម្មវិធី​សន្សំ​ថ្ម​ត្រូវបានបិទ"</string>
+ <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"មុខងារ​សន្សំ​ថ្ម​ត្រូវបានបិទ"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ទូរសព្ទ​មាន​កម្រិតថ្ម​គ្រប់គ្រាន់​។ មុខងារ​ផ្សេងៗ​មិន​ត្រូវបាន​រឹតបន្តឹងទៀត​ទេ។"</string>
<string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"ថេប្លេត​មាន​កម្រិតថ្ម​គ្រប់គ្រាន់​។ មុខងារ​ផ្សេងៗ​មិន​ត្រូវបាន​រឹតបន្តឹងទៀត​ទេ។"</string>
<string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"ឧបករណ៍​មាន​កម្រិតថ្ម​គ្រប់គ្រាន់​។ មុខងារ​ផ្សេងៗ​មិន​ត្រូវបាន​រឹតបន្តឹងទៀត​ទេ។"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index db5603c8a624..e39d46dfb6f7 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1129,10 +1129,8 @@
<string name="capital_off" msgid="7443704171014626777">"बंद"</string>
<string name="checked" msgid="9179896827054513119">"तपासले"</string>
<string name="not_checked" msgid="7972320087569023342">"तपासले नाही"</string>
- <!-- no translation found for selected (6614607926197755875) -->
- <skip />
- <!-- no translation found for not_selected (410652016565864475) -->
- <skip />
+ <string name="selected" msgid="6614607926197755875">"निवडला"</string>
+ <string name="not_selected" msgid="410652016565864475">"निवडला नाही"</string>
<string name="whichApplication" msgid="5432266899591255759">"याचा वापर करून क्रिया पूर्ण करा"</string>
<string name="whichApplicationNamed" msgid="6969946041713975681">"%1$s वापरून क्रिया पूर्ण करा"</string>
<string name="whichApplicationLabel" msgid="7852182961472531728">"क्रिया पूर्ण झाली"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index b5fd7b245555..915e158f3267 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1129,10 +1129,8 @@
<string name="capital_off" msgid="7443704171014626777">"बन्द"</string>
<string name="checked" msgid="9179896827054513119">"जाँच गरिएको"</string>
<string name="not_checked" msgid="7972320087569023342">"जाँच गरिएको छैन"</string>
- <!-- no translation found for selected (6614607926197755875) -->
- <skip />
- <!-- no translation found for not_selected (410652016565864475) -->
- <skip />
+ <string name="selected" msgid="6614607926197755875">"चयन गरियो"</string>
+ <string name="not_selected" msgid="410652016565864475">"चयन गरिएन"</string>
<string name="whichApplication" msgid="5432266899591255759">"प्रयोग गरेर कारबाही पुरा गर्नुहोस्"</string>
<string name="whichApplicationNamed" msgid="6969946041713975681">"निम्न एपको प्रयोग गरी कारबाही पुरा गर्नुहोस्: %1$s"</string>
<string name="whichApplicationLabel" msgid="7852182961472531728">"पूर्ण कारबाही"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index df03ccc784d4..6e03398283ac 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1694,7 +1694,7 @@
to be explicitly declared in this resource to be enabled.
* SDK level 28 makes the following algorithms mandatory : "cbc(aes)", "hmac(md5)",
"hmac(sha1)", "hmac(sha256)", "hmac(sha384)", "hmac(sha512)", "rfc4106(gcm(aes))"
- * SDK level 30 makes the following algorithms mandatory : "rfc3686(ctr(aes))",
+ * SDK level 31 makes the following algorithms mandatory : "rfc3686(ctr(aes))",
"xcbc(aes)", "rfc7539esp(chacha20,poly1305)"
-->
<string-array name="config_optionalIpSecAlgorithms" translatable="false">
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 7eff3d7bcb06..544be54eb785 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -858,6 +858,7 @@
<dimen name="waterfall_display_right_edge_size">0px</dimen>
<dimen name="waterfall_display_bottom_edge_size">0px</dimen>
+ <dimen name="default_background_blur_radius">100dp</dimen>
<!-- The maximum height of a thumbnail in a ThumbnailTemplate. The image will be reduced to that height in case they are bigger. -->
<dimen name="controls_thumbnail_image_max_height">140dp</dimen>
<!-- The maximum width of a thumbnail in a ThumbnailTemplate. The image will be reduced to that width in case they are bigger.-->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e4a4e20ee0bb..a294c9d1e537 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3553,6 +3553,7 @@
<java-symbol type="id" name="clip_to_padding_tag" />
<java-symbol type="id" name="clip_children_tag" />
<java-symbol type="id" name="bubble_button" />
+ <java-symbol type="id" name="snooze_button" />
<java-symbol type="dimen" name="bubble_visible_padding_end" />
<java-symbol type="dimen" name="bubble_gone_padding_end" />
<java-symbol type="dimen" name="text_size_body_2_material" />
@@ -4078,6 +4079,7 @@
<java-symbol type="integer" name="config_defaultBinderHeavyHitterAutoSamplerBatchSize" />
<java-symbol type="dimen" name="config_defaultBinderHeavyHitterAutoSamplerThreshold" />
+ <java-symbol type="dimen" name="default_background_blur_radius" />
<java-symbol type="array" name="config_keep_warming_services" />
<java-symbol type="string" name="config_display_features" />
<java-symbol type="array" name="config_internalFoldedPhysicalDisplayIds" />
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java
index ac2d4b5c5f7d..2f2bef8bc5cc 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/AppSearchEmailTest.java
@@ -30,7 +30,7 @@ public class AppSearchEmailTest {
// Score and Property are mixed into the middle to make sure DocumentBuilder's
// methods can be interleaved with EmailBuilder's methods.
.setScore(1)
- .setProperty("propertyKey", "propertyValue1", "propertyValue2")
+ .setPropertyString("propertyKey", "propertyValue1", "propertyValue2")
.setSubject("subject")
.setBody("EmailBody")
.build();
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java
index 1f2c12bca028..9c29943dbef4 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/GenericDocumentTest.java
@@ -39,22 +39,22 @@ public class GenericDocumentTest {
GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1")
.setCreationTimestampMillis(5L)
.setTtlMillis(1L)
- .setProperty("longKey1", 1L, 2L, 3L)
- .setProperty("doubleKey1", 1.0, 2.0, 3.0)
- .setProperty("booleanKey1", true, false, true)
- .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
- .setProperty("byteKey1", sByteArray1, sByteArray2)
- .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
+ .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
+ .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+ .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
.build();
GenericDocument document2 = new GenericDocument.Builder("uri1", "schemaType1")
.setCreationTimestampMillis(5L)
.setTtlMillis(1L)
- .setProperty("longKey1", 1L, 2L, 3L)
- .setProperty("doubleKey1", 1.0, 2.0, 3.0)
- .setProperty("booleanKey1", true, false, true)
- .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
- .setProperty("byteKey1", sByteArray1, sByteArray2)
- .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
+ .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
+ .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+ .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
.build();
assertThat(document1).isEqualTo(document2);
assertThat(document1.hashCode()).isEqualTo(document2.hashCode());
@@ -64,23 +64,23 @@ public class GenericDocumentTest {
public void testDocumentEquals_DifferentOrder() {
GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1")
.setCreationTimestampMillis(5L)
- .setProperty("longKey1", 1L, 2L, 3L)
- .setProperty("byteKey1", sByteArray1, sByteArray2)
- .setProperty("doubleKey1", 1.0, 2.0, 3.0)
- .setProperty("booleanKey1", true, false, true)
- .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
- .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
+ .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+ .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
+ .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
.build();
// Create second document with same parameter but different order.
GenericDocument document2 = new GenericDocument.Builder("uri1", "schemaType1")
.setCreationTimestampMillis(5L)
- .setProperty("booleanKey1", true, false, true)
- .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
- .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
- .setProperty("doubleKey1", 1.0, 2.0, 3.0)
- .setProperty("byteKey1", sByteArray1, sByteArray2)
- .setProperty("longKey1", 1L, 2L, 3L)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
+ .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
+ .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+ .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
.build();
assertThat(document1).isEqualTo(document2);
assertThat(document1.hashCode()).isEqualTo(document2.hashCode());
@@ -90,13 +90,13 @@ public class GenericDocumentTest {
public void testDocumentEquals_Failure() {
GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1")
.setCreationTimestampMillis(5L)
- .setProperty("longKey1", 1L, 2L, 3L)
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
.build();
// Create second document with same order but different value.
GenericDocument document2 = new GenericDocument.Builder("uri1", "schemaType1")
.setCreationTimestampMillis(5L)
- .setProperty("longKey1", 1L, 2L, 4L) // Different
+ .setPropertyLong("longKey1", 1L, 2L, 4L) // Different
.build();
assertThat(document1).isNotEqualTo(document2);
assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode());
@@ -106,13 +106,13 @@ public class GenericDocumentTest {
public void testDocumentEquals_Failure_RepeatedFieldOrder() {
GenericDocument document1 = new GenericDocument.Builder("uri1", "schemaType1")
.setCreationTimestampMillis(5L)
- .setProperty("booleanKey1", true, false, true)
+ .setPropertyBoolean("booleanKey1", true, false, true)
.build();
// Create second document with same order but different value.
GenericDocument document2 = new GenericDocument.Builder("uri1", "schemaType1")
.setCreationTimestampMillis(5L)
- .setProperty("booleanKey1", true, true, false) // Different
+ .setPropertyBoolean("booleanKey1", true, true, false) // Different
.build();
assertThat(document1).isNotEqualTo(document2);
assertThat(document1.hashCode()).isNotEqualTo(document2.hashCode());
@@ -124,12 +124,12 @@ public class GenericDocumentTest {
.setCreationTimestampMillis(5L)
.setScore(1)
.setTtlMillis(1L)
- .setProperty("longKey1", 1L)
- .setProperty("doubleKey1", 1.0)
- .setProperty("booleanKey1", true)
- .setProperty("stringKey1", "test-value1")
- .setProperty("byteKey1", sByteArray1)
- .setProperty("documentKey1", sDocumentProperties1)
+ .setPropertyLong("longKey1", 1L)
+ .setPropertyDouble("doubleKey1", 1.0)
+ .setPropertyBoolean("booleanKey1", true)
+ .setPropertyString("stringKey1", "test-value1")
+ .setPropertyBytes("byteKey1", sByteArray1)
+ .setPropertyDocument("documentKey1", sDocumentProperties1)
.build();
assertThat(document.getUri()).isEqualTo("uri1");
assertThat(document.getTtlMillis()).isEqualTo(1L);
@@ -149,12 +149,12 @@ public class GenericDocumentTest {
public void testDocumentGetArrayValues() {
GenericDocument document = new GenericDocument.Builder("uri1", "schemaType1")
.setCreationTimestampMillis(5L)
- .setProperty("longKey1", 1L, 2L, 3L)
- .setProperty("doubleKey1", 1.0, 2.0, 3.0)
- .setProperty("booleanKey1", true, false, true)
- .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
- .setProperty("byteKey1", sByteArray1, sByteArray2)
- .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
+ .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
+ .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+ .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
.build();
assertThat(document.getUri()).isEqualTo("uri1");
@@ -176,12 +176,12 @@ public class GenericDocumentTest {
public void testDocument_ToString() throws Exception {
GenericDocument document = new GenericDocument.Builder("uri1", "schemaType1")
.setCreationTimestampMillis(5L)
- .setProperty("longKey1", 1L, 2L, 3L)
- .setProperty("doubleKey1", 1.0, 2.0, 3.0)
- .setProperty("booleanKey1", true, false, true)
- .setProperty("stringKey1", "String1", "String2", "String3")
- .setProperty("byteKey1", sByteArray1, sByteArray2)
- .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
+ .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyString("stringKey1", "String1", "String2", "String3")
+ .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+ .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
.build();
String exceptedString = "{ key: 'creationTimestampMillis' value: 5 } "
+ "{ key: 'namespace' value: } "
@@ -219,9 +219,9 @@ public class GenericDocumentTest {
public void testDocumentGetValues_DifferentTypes() {
GenericDocument document = new GenericDocument.Builder("uri1", "schemaType1")
.setScore(1)
- .setProperty("longKey1", 1L)
- .setProperty("booleanKey1", true, false, true)
- .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
+ .setPropertyLong("longKey1", 1L)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
.build();
// Get a value for a key that doesn't exist
@@ -246,6 +246,7 @@ public class GenericDocumentTest {
public void testDocumentInvalid() {
GenericDocument.Builder builder = new GenericDocument.Builder("uri1", "schemaType1");
expectThrows(
- IllegalArgumentException.class, () -> builder.setProperty("test", new boolean[]{}));
+ IllegalArgumentException.class,
+ () -> builder.setPropertyBoolean("test", new boolean[]{}));
}
}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java
new file mode 100644
index 000000000000..d4635fdda052
--- /dev/null
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/SearchSpecTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.appsearch;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.testng.Assert.expectThrows;
+
+import android.os.Bundle;
+
+import org.junit.Test;
+
+public class SearchSpecTest {
+ @Test
+ public void buildSearchSpecWithoutTermMatchType() {
+ expectThrows(RuntimeException.class, () -> new SearchSpec.Builder()
+ .addSchema("testSchemaType")
+ .build());
+ }
+
+ @Test
+ public void testBuildSearchSpec() {
+ SearchSpec searchSpec = new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+ .addNamespace("namespace1", "namespace2")
+ .addSchema("schemaTypes1", "schemaTypes2")
+ .setSnippetCount(5)
+ .setSnippetCountPerProperty(10)
+ .setMaxSnippetSize(15)
+ .setNumPerPage(42)
+ .setOrder(SearchSpec.ORDER_ASCENDING)
+ .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE)
+ .build();
+
+ assertThat(searchSpec.getTermMatch()).isEqualTo(SearchSpec.TERM_MATCH_PREFIX);
+ assertThat(searchSpec.getNamespaces())
+ .containsExactly("namespace1", "namespace2").inOrder();
+ assertThat(searchSpec.getSchemas())
+ .containsExactly("schemaTypes1", "schemaTypes2").inOrder();
+ assertThat(searchSpec.getSnippetCount()).isEqualTo(5);
+ assertThat(searchSpec.getSnippetCountPerProperty()).isEqualTo(10);
+ assertThat(searchSpec.getMaxSnippetSize()).isEqualTo(15);
+ assertThat(searchSpec.getNumPerPage()).isEqualTo(42);
+ assertThat(searchSpec.getOrder()).isEqualTo(SearchSpec.ORDER_ASCENDING);
+ assertThat(searchSpec.getRankingStrategy())
+ .isEqualTo(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE);
+ }
+
+ @Test
+ public void testGetBundle() {
+ SearchSpec searchSpec = new SearchSpec.Builder()
+ .setTermMatch(SearchSpec.TERM_MATCH_PREFIX)
+ .addNamespace("namespace1", "namespace2")
+ .addSchema("schemaTypes1", "schemaTypes2")
+ .setSnippetCount(5)
+ .setSnippetCountPerProperty(10)
+ .setMaxSnippetSize(15)
+ .setNumPerPage(42)
+ .setOrder(SearchSpec.ORDER_ASCENDING)
+ .setRankingStrategy(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE)
+ .build();
+
+ Bundle bundle = searchSpec.getBundle();
+ assertThat(bundle.getInt(SearchSpec.TERM_MATCH_TYPE_FIELD))
+ .isEqualTo(SearchSpec.TERM_MATCH_PREFIX);
+ assertThat(bundle.getStringArrayList(SearchSpec.NAMESPACE_FIELD)).containsExactly(
+ "namespace1", "namespace2");
+ assertThat(bundle.getStringArrayList(SearchSpec.SCHEMA_TYPE_FIELD)).containsExactly(
+ "schemaTypes1", "schemaTypes2");
+ assertThat(bundle.getInt(SearchSpec.SNIPPET_COUNT_FIELD)).isEqualTo(5);
+ assertThat(bundle.getInt(SearchSpec.SNIPPET_COUNT_PER_PROPERTY_FIELD)).isEqualTo(10);
+ assertThat(bundle.getInt(SearchSpec.MAX_SNIPPET_FIELD)).isEqualTo(15);
+ assertThat(bundle.getInt(SearchSpec.NUM_PER_PAGE_FIELD)).isEqualTo(42);
+ assertThat(bundle.getInt(SearchSpec.ORDER_FIELD)).isEqualTo(SearchSpec.ORDER_ASCENDING);
+ assertThat(bundle.getInt(SearchSpec.RANKING_STRATEGY_FIELD))
+ .isEqualTo(SearchSpec.RANKING_STRATEGY_DOCUMENT_SCORE);
+ }
+}
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java b/core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java
index 2c7c35feface..d56d0c3c5c8e 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java
+++ b/core/tests/coretests/src/android/app/appsearch/external/app/customer/CustomerDocumentTest.java
@@ -46,12 +46,12 @@ public class CustomerDocumentTest {
CustomerDocument customerDocument = new CustomerDocument.Builder("uri1")
.setScore(1)
.setCreationTimestampMillis(0)
- .setProperty("longKey1", 1L, 2L, 3L)
- .setProperty("doubleKey1", 1.0, 2.0, 3.0)
- .setProperty("booleanKey1", true, false, true)
- .setProperty("stringKey1", "test-value1", "test-value2", "test-value3")
- .setProperty("byteKey1", sByteArray1, sByteArray2)
- .setProperty("documentKey1", sDocumentProperties1, sDocumentProperties2)
+ .setPropertyLong("longKey1", 1L, 2L, 3L)
+ .setPropertyDouble("doubleKey1", 1.0, 2.0, 3.0)
+ .setPropertyBoolean("booleanKey1", true, false, true)
+ .setPropertyString("stringKey1", "test-value1", "test-value2", "test-value3")
+ .setPropertyBytes("byteKey1", sByteArray1, sByteArray2)
+ .setPropertyDocument("documentKey1", sDocumentProperties1, sDocumentProperties2)
.build();
assertThat(customerDocument.getUri()).isEqualTo("uri1");
diff --git a/core/tests/coretests/src/android/os/CombinedVibrationEffectTest.java b/core/tests/coretests/src/android/os/CombinedVibrationEffectTest.java
index faa67a8bbd62..1947c6cf8ca0 100644
--- a/core/tests/coretests/src/android/os/CombinedVibrationEffectTest.java
+++ b/core/tests/coretests/src/android/os/CombinedVibrationEffectTest.java
@@ -26,22 +26,135 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
+import java.util.Arrays;
+
@Presubmit
@RunWith(JUnit4.class)
public class CombinedVibrationEffectTest {
+ private static final VibrationEffect VALID_EFFECT = VibrationEffect.createOneShot(10, 255);
+ private static final VibrationEffect INVALID_EFFECT = new VibrationEffect.OneShot(-1, -1);
+
@Test
public void testValidateMono() {
- CombinedVibrationEffect.createSynced(VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
+ CombinedVibrationEffect.createSynced(VALID_EFFECT);
+
+ assertThrows(IllegalArgumentException.class,
+ () -> CombinedVibrationEffect.createSynced(INVALID_EFFECT));
+ }
+
+ @Test
+ public void testValidateStereo() {
+ CombinedVibrationEffect.startSynced()
+ .addVibrator(0, VALID_EFFECT)
+ .addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_TICK))
+ .combine();
+ CombinedVibrationEffect.startSynced()
+ .addVibrator(0, INVALID_EFFECT)
+ .addVibrator(0, VALID_EFFECT)
+ .combine();
+
+ assertThrows(IllegalArgumentException.class,
+ () -> CombinedVibrationEffect.startSynced()
+ .addVibrator(0, INVALID_EFFECT)
+ .combine());
+ }
+ @Test
+ public void testValidateSequential() {
+ CombinedVibrationEffect.startSequential()
+ .addNext(0, VALID_EFFECT)
+ .addNext(CombinedVibrationEffect.createSynced(VALID_EFFECT))
+ .combine();
+ CombinedVibrationEffect.startSequential()
+ .addNext(0, VALID_EFFECT)
+ .addNext(0, VALID_EFFECT, 100)
+ .combine();
+ CombinedVibrationEffect.startSequential()
+ .addNext(CombinedVibrationEffect.startSequential()
+ .addNext(0, VALID_EFFECT)
+ .combine())
+ .combine();
+
+ assertThrows(IllegalArgumentException.class,
+ () -> CombinedVibrationEffect.startSequential()
+ .addNext(0, VALID_EFFECT, -1)
+ .combine());
assertThrows(IllegalArgumentException.class,
- () -> CombinedVibrationEffect.createSynced(new VibrationEffect.OneShot(-1, -1)));
+ () -> CombinedVibrationEffect.startSequential()
+ .addNext(0, INVALID_EFFECT)
+ .combine());
+ assertThrows(IllegalArgumentException.class,
+ () -> new CombinedVibrationEffect.Sequential(
+ Arrays.asList(CombinedVibrationEffect.startSequential()
+ .addNext(CombinedVibrationEffect.createSynced(VALID_EFFECT))
+ .combine()),
+ Arrays.asList(0))
+ .validate());
+ }
+
+ @Test
+ public void testNestedSequentialAccumulatesDelays() {
+ CombinedVibrationEffect.Sequential combined =
+ (CombinedVibrationEffect.Sequential) CombinedVibrationEffect.startSequential()
+ .addNext(CombinedVibrationEffect.startSequential()
+ .addNext(0, VALID_EFFECT, /* delay= */ 100)
+ .addNext(1, VALID_EFFECT, /* delay= */ 100)
+ .combine(),
+ /* delay= */ 10)
+ .addNext(CombinedVibrationEffect.startSequential()
+ .addNext(0, VALID_EFFECT, /* delay= */ 100)
+ .combine())
+ .addNext(CombinedVibrationEffect.startSequential()
+ .addNext(0, VALID_EFFECT)
+ .addNext(0, VALID_EFFECT, /* delay= */ 100)
+ .combine(),
+ /* delay= */ 10)
+ .combine();
+
+ assertEquals(Arrays.asList(110, 100, 100, 10, 100), combined.getDelays());
+ }
+
+ @Test
+ public void testCombineEmptyFails() {
+ assertThrows(IllegalStateException.class,
+ () -> CombinedVibrationEffect.startSynced().combine());
+ assertThrows(IllegalStateException.class,
+ () -> CombinedVibrationEffect.startSequential().combine());
}
@Test
public void testSerializationMono() {
- CombinedVibrationEffect original = CombinedVibrationEffect.createSynced(
- VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
+ CombinedVibrationEffect original = CombinedVibrationEffect.createSynced(VALID_EFFECT);
+
+ Parcel parcel = Parcel.obtain();
+ original.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ CombinedVibrationEffect restored = CombinedVibrationEffect.CREATOR.createFromParcel(parcel);
+ assertEquals(original, restored);
+ }
+
+ @Test
+ public void testSerializationStereo() {
+ CombinedVibrationEffect original = CombinedVibrationEffect.startSynced()
+ .addVibrator(0, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
+ .addVibrator(1, VibrationEffect.createOneShot(10, 255))
+ .combine();
+
+ Parcel parcel = Parcel.obtain();
+ original.writeToParcel(parcel, 0);
+ parcel.setDataPosition(0);
+ CombinedVibrationEffect restored = CombinedVibrationEffect.CREATOR.createFromParcel(parcel);
+ assertEquals(original, restored);
+ }
+
+ @Test
+ public void testSerializationSequential() {
+ CombinedVibrationEffect original = CombinedVibrationEffect.startSequential()
+ .addNext(0, VALID_EFFECT)
+ .addNext(CombinedVibrationEffect.createSynced(VALID_EFFECT))
+ .addNext(0, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), 100)
+ .combine();
Parcel parcel = Parcel.obtain();
original.writeToParcel(parcel, 0);
diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
index a5b7c6156109..db838e81eb28 100644
--- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
@@ -17,7 +17,6 @@
package android.view;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
-import static android.view.ImeInsetsSourceConsumer.areEditorsSimilar;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -33,11 +32,9 @@ import android.content.Context;
import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
-import android.os.Bundle;
import android.platform.test.annotations.Presubmit;
import android.view.WindowManager.BadTokenException;
import android.view.WindowManager.LayoutParams;
-import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -50,8 +47,6 @@ import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.Spy;
-import java.util.ArrayList;
-
/**
* Test {@link InsetsSourceConsumer} with IME type.
*
@@ -133,50 +128,4 @@ public class ImeInsetsSourceConsumerTest {
eq(WindowInsets.Type.ime()), eq(false) /* show */, eq(true) /* fromIme */);
});
}
-
- @Test
- public void testAreEditorsSimilar() {
- EditorInfo info1 = new EditorInfo();
- info1.privateImeOptions = "dummy";
- EditorInfo info2 = new EditorInfo();
-
- assertFalse(areEditorsSimilar(info1, info2));
-
- info1.privateImeOptions = null;
- assertTrue(areEditorsSimilar(info1, info2));
-
- info1.inputType = info2.inputType = 3;
- info1.imeOptions = info2.imeOptions = 0x4;
- info1.packageName = info2.packageName = "dummy.package";
- assertTrue(areEditorsSimilar(info1, info2));
-
- Bundle extras1 = new Bundle();
- extras1.putByteArray("key1", "value1".getBytes());
- extras1.putChar("key2", 'c');
- Bundle extras2 = new Bundle();
- extras2.putByteArray("key1", "value1".getBytes());
- extras2.putChar("key2", 'c');
- info1.extras = extras1;
- info2.extras = extras2;
- assertTrue(areEditorsSimilar(info1, info2));
-
- Bundle extraBundle = new Bundle();
- ArrayList<Integer> list = new ArrayList<>();
- list.add(2);
- list.add(5);
- extraBundle.putByteArray("key1", "value1".getBytes());
- extraBundle.putChar("key2", 'c');
- extraBundle.putIntegerArrayList("key3", list);
-
- extras1.putAll(extraBundle);
- extras2.putAll(extraBundle);
- assertTrue(areEditorsSimilar(info1, info2));
-
- extras2.putChar("key2", 'd');
- assertFalse(areEditorsSimilar(info1, info2));
-
- extras2.putChar("key2", 'c');
- extras2.putInt("key4", 1);
- assertFalse(areEditorsSimilar(info1, info2));
- }
}
diff --git a/core/tests/coretests/src/android/widget/TextViewOnReceiveContentCallbackTest.java b/core/tests/coretests/src/android/widget/TextViewOnReceiveContentTest.java
index ef659af6c570..8efd3b4f0135 100644
--- a/core/tests/coretests/src/android/widget/TextViewOnReceiveContentCallbackTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewOnReceiveContentTest.java
@@ -63,12 +63,12 @@ import org.mockito.Mockito;
/**
* Tests for {@link TextViewOnReceiveContentCallback}. Most of the test cases are in the CTS test
- * {@link android.widget.cts.TextViewOnReceiveContentCallbackTest}. This class tests some internal
+ * {@link android.widget.cts.TextViewOnReceiveContentTest}. This class tests some internal
* implementation details, e.g. fallback to the keyboard image API.
*/
@MediumTest
@RunWith(AndroidJUnit4.class)
-public class TextViewOnReceiveContentCallbackTest {
+public class TextViewOnReceiveContentTest {
private static final Uri SAMPLE_CONTENT_URI = Uri.parse("content://com.example/path");
@Rule
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index b143be7b4d6a..441c16322645 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -327,7 +327,7 @@ public class Typeface {
* 1) Create Typeface from ttf file.
* <pre>
* <code>
- * Typeface.Builder buidler = new Typeface.Builder("your_font_file.ttf");
+ * Typeface.Builder builder = new Typeface.Builder("your_font_file.ttf");
* Typeface typeface = builder.build();
* </code>
* </pre>
@@ -335,7 +335,7 @@ public class Typeface {
* 2) Create Typeface from ttc file in assets directory.
* <pre>
* <code>
- * Typeface.Builder buidler = new Typeface.Builder(getAssets(), "your_font_file.ttc");
+ * Typeface.Builder builder = new Typeface.Builder(getAssets(), "your_font_file.ttc");
* builder.setTtcIndex(2); // Set index of font collection.
* Typeface typeface = builder.build();
* </code>
@@ -344,7 +344,7 @@ public class Typeface {
* 3) Create Typeface with variation settings.
* <pre>
* <code>
- * Typeface.Builder buidler = new Typeface.Builder("your_font_file.ttf");
+ * Typeface.Builder builder = new Typeface.Builder("your_font_file.ttf");
* builder.setFontVariationSettings("'wght' 700, 'slnt' 20, 'ital' 1");
* builder.setWeight(700); // Tell the system that this is a bold font.
* builder.setItalic(true); // Tell the system that this is an italic style font.
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index 586c512b3f97..c07b4bcf0e72 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -626,25 +626,33 @@ public final class Font {
return mNativePtr;
}
- @Override
- public boolean equals(@Nullable Object o) {
- if (o == this) {
- return true;
- }
- if (!(o instanceof Font)) {
- return false;
- }
- Font f = (Font) o;
- boolean paramEqual = mFontStyle.equals(f.mFontStyle) && f.mTtcIndex == mTtcIndex
- && Arrays.equals(f.mAxes, mAxes) && Objects.equals(f.mLocaleList, mLocaleList)
- && Objects.equals(mFile, f.mFile);
+ /**
+ * Returns true if the given font is created from the same source data from this font.
+ *
+ * This method essentially compares {@link ByteBuffer} inside Font, but has some optimization
+ * for faster comparing. This method compares the internal object before going to one-by-one
+ * byte compare with {@link ByteBuffer}. This typically works efficiently if you compares the
+ * font that is created from {@link Builder#Builder(Font)}.
+ *
+ * This API is typically useful for checking if two fonts can be interpolated by font variation
+ * axes. For example, when you call {@link android.text.TextShaper} for the same
+ * string but different style, you may get two font objects which is created from the same
+ * source but have different parameters. You may want to animate between them by interpolating
+ * font variation settings if these fonts are created from the same source.
+ *
+ * @param other a font object to be compared.
+ * @return true if given font is created from the same source from this font. Otherwise false.
+ */
+ public boolean isSameSource(@NonNull Font other) {
+ Objects.requireNonNull(other);
- if (!paramEqual) {
- return false;
+ // Shortcut for the same instance.
+ if (mBuffer == other.mBuffer) {
+ return true;
}
// Shortcut for different font buffer check by comparing size.
- if (mBuffer.capacity() != f.mBuffer.capacity()) {
+ if (mBuffer.capacity() != other.mBuffer.capacity()) {
return false;
}
@@ -652,15 +660,35 @@ public final class Font {
// underlying native font object holds buffer address, check if this buffer points exactly
// the same address as a shortcut of equality. For being compatible with of API30 or before,
// check buffer position even if the buffer points the same address.
- if (nIsSameBufferAddress(mNativePtr, f.mNativePtr)
- && mBuffer.position() == f.mBuffer.position()) {
+ if (nIsSameBufferAddress(mNativePtr, other.mNativePtr)
+ && mBuffer.position() == other.mBuffer.position()) {
return true;
}
// Unfortunately, need to compare bytes one-by-one since the buffer may be different font
// file but has the same file size, or two font has same content but they are allocated
// differently. For being compatible with API30 ore before, compare with ByteBuffer#equals.
- return mBuffer.equals(f.mBuffer);
+ return mBuffer.equals(other.mBuffer);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (!(o instanceof Font)) {
+ return false;
+ }
+ Font f = (Font) o;
+ boolean paramEqual = mFontStyle.equals(f.mFontStyle) && f.mTtcIndex == mTtcIndex
+ && Arrays.equals(f.mAxes, mAxes) && Objects.equals(f.mLocaleList, mLocaleList)
+ && Objects.equals(mFile, f.mFile);
+
+ if (!paramEqual) {
+ return false;
+ }
+
+ return isSameSource(f);
}
@Override
diff --git a/keystore/java/android/security/Credentials.java b/keystore/java/android/security/Credentials.java
index 8f5982cd4528..7abcfdc98bc6 100644
--- a/keystore/java/android/security/Credentials.java
+++ b/keystore/java/android/security/Credentials.java
@@ -49,18 +49,38 @@ public class Credentials {
public static final String INSTALL_AS_USER_ACTION = "android.credentials.INSTALL_AS_USER";
- /** Key prefix for CA certificates. */
+ /**
+ * Key prefix for CA certificates.
+ *
+ * @deprecated Keystore no longer supports unstructured blobs. Public certificates are
+ * stored in typed slots associated with a given alias.
+ */
+ @Deprecated
public static final String CA_CERTIFICATE = "CACERT_";
- /** Key prefix for user certificates. */
+ /**
+ * Key prefix for user certificates.
+ *
+ * @deprecated Keystore no longer supports unstructured blobs. Public certificates are
+ * stored in typed slots associated with a given alias.
+ */
+ @Deprecated
public static final String USER_CERTIFICATE = "USRCERT_";
- /** Key prefix for user private and secret keys. */
+ /**
+ * Key prefix for user private and secret keys.
+ *
+ * @deprecated Keystore no longer uses alias prefixes to discriminate between entry types.
+ */
+ @Deprecated
public static final String USER_PRIVATE_KEY = "USRPKEY_";
- /** Key prefix for user secret keys.
- * @deprecated use {@code USER_PRIVATE_KEY} for this category instead.
+ /**
+ * Key prefix for user secret keys.
+ *
+ * @deprecated use {@code USER_PRIVATE_KEY} for this category instead.
*/
+ @Deprecated
public static final String USER_SECRET_KEY = "USRSKEY_";
/** Key prefix for VPN. */
@@ -72,7 +92,13 @@ public class Credentials {
/** Key prefix for WIFI. */
public static final String WIFI = "WIFI_";
- /** Key prefix for App Source certificates. */
+ /**
+ * Key prefix for App Source certificates.
+ *
+ * @deprecated This was intended for FS-verity but never used. FS-verity is not
+ * going to use this constant moving forward.
+ */
+ @Deprecated
public static final String APP_SOURCE_CERTIFICATE = "FSV_";
/** Key containing suffix of lockdown VPN profile. */
@@ -150,6 +176,7 @@ public class Credentials {
pw.close();
return bao.toByteArray();
}
+
/**
* Convert objects from PEM format, which is used for
* CA_CERTIFICATE and USER_CERTIFICATE entries.
@@ -167,7 +194,8 @@ public class Credentials {
PemObject o;
while ((o = pr.readPemObject()) != null) {
if (o.getType().equals("CERTIFICATE")) {
- Certificate c = cf.generateCertificate(new ByteArrayInputStream(o.getContent()));
+ Certificate c = cf.generateCertificate(
+ new ByteArrayInputStream(o.getContent()));
result.add((X509Certificate) c);
} else {
throw new IllegalArgumentException("Unknown type " + o.getType());
diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java
index d5b34c432e79..1c1c2eeee794 100644
--- a/keystore/java/android/security/KeyPairGeneratorSpec.java
+++ b/keystore/java/android/security/KeyPairGeneratorSpec.java
@@ -16,9 +16,9 @@
package android.security;
-import android.app.KeyguardManager;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.KeyguardManager;
import android.content.Context;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
@@ -78,8 +78,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
private final Date mEndDate;
- private final int mFlags;
-
/**
* Parameter specification for the "{@code AndroidKeyPairGenerator}"
* instance of the {@link java.security.KeyPairGenerator} API. The
@@ -144,7 +142,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
mSerialNumber = serialNumber;
mStartDate = startDate;
mEndDate = endDate;
- mFlags = flags;
}
/**
@@ -229,7 +226,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
* @hide
*/
public int getFlags() {
- return mFlags;
+ return 0;
}
/**
@@ -243,9 +240,15 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
* screen after boot.
*
* @see KeyguardManager#isDeviceSecure()
+ *
+ * @deprecated Encryption at rest is on by default. If extra binding to the lockscreen screen
+ * credential is desired use
+ * {@link KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean)}.
+ * This flag will be ignored from Android S.
*/
+ @Deprecated
public boolean isEncryptionRequired() {
- return (mFlags & KeyStore.FLAG_ENCRYPTED) != 0;
+ return false;
}
/**
@@ -292,8 +295,6 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
private Date mEndDate;
- private int mFlags;
-
/**
* Creates a new instance of the {@code Builder} with the given
* {@code context}. The {@code context} passed in may be used to pop up
@@ -431,10 +432,15 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
* secure lock screen after boot.
*
* @see KeyguardManager#isDeviceSecure()
+ *
+ * @deprecated Data at rest encryption is enabled by default. If extra binding to the
+ * lockscreen credential is desired, use
+ * {@link KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean)}.
+ * This flag will be ignored from Android S.
*/
@NonNull
+ @Deprecated
public Builder setEncryptionRequired() {
- mFlags |= KeyStore.FLAG_ENCRYPTED;
return this;
}
@@ -455,7 +461,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec {
mSerialNumber,
mStartDate,
mEndDate,
- mFlags);
+ 0);
}
}
}
diff --git a/keystore/java/android/security/KeyStoreParameter.java b/keystore/java/android/security/KeyStoreParameter.java
index 66c87ed2ec1e..51d29b13ce80 100644
--- a/keystore/java/android/security/KeyStoreParameter.java
+++ b/keystore/java/android/security/KeyStoreParameter.java
@@ -48,18 +48,16 @@ import java.security.KeyStore.ProtectionParameter;
*/
@Deprecated
public final class KeyStoreParameter implements ProtectionParameter {
- private final int mFlags;
private KeyStoreParameter(
int flags) {
- mFlags = flags;
}
/**
* @hide
*/
public int getFlags() {
- return mFlags;
+ return 0;
}
/**
@@ -74,9 +72,16 @@ public final class KeyStoreParameter implements ProtectionParameter {
* screen after boot.
*
* @see KeyguardManager#isDeviceSecure()
+ *
+ * @deprecated Data at rest encryption is enabled by default. If extra binding to the
+ * lockscreen credential is desired, use
+ * {@link android.security.keystore.KeyGenParameterSpec
+ * .Builder#setUserAuthenticationRequired(boolean)}.
+ * This flag will be ignored from Android S.
*/
+ @Deprecated
public boolean isEncryptionRequired() {
- return (mFlags & KeyStore.FLAG_ENCRYPTED) != 0;
+ return false;
}
/**
@@ -100,7 +105,6 @@ public final class KeyStoreParameter implements ProtectionParameter {
*/
@Deprecated
public final static class Builder {
- private int mFlags;
/**
* Creates a new instance of the {@code Builder} with the given
@@ -126,14 +130,15 @@ public final class KeyStoreParameter implements ProtectionParameter {
* the user unlocks the secure lock screen after boot.
*
* @see KeyguardManager#isDeviceSecure()
+ *
+ * @deprecated Data at rest encryption is enabled by default. If extra binding to the
+ * lockscreen credential is desired, use
+ * {@link android.security.keystore.KeyGenParameterSpec
+ * .Builder#setUserAuthenticationRequired(boolean)}.
+ * This flag will be ignored from Android S.
*/
@NonNull
public Builder setEncryptionRequired(boolean required) {
- if (required) {
- mFlags |= KeyStore.FLAG_ENCRYPTED;
- } else {
- mFlags &= ~KeyStore.FLAG_ENCRYPTED;
- }
return this;
}
@@ -145,8 +150,7 @@ public final class KeyStoreParameter implements ProtectionParameter {
*/
@NonNull
public KeyStoreParameter build() {
- return new KeyStoreParameter(
- mFlags);
+ return new KeyStoreParameter(0 /* flags */);
}
}
}
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 1d85e9fceac9..b87a642a8dc7 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -57,6 +57,9 @@
<dimen name="pip_resize_handle_margin">4dp</dimen>
<dimen name="pip_resize_handle_padding">0dp</dimen>
+ <!-- PIP stash offset size, which is the width of visible PIP region when stashed. -->
+ <dimen name="pip_stash_offset">32dp</dimen>
+
<dimen name="dismiss_target_x_size">24dp</dimen>
<dimen name="floating_dismiss_bottom_margin">50dp</dimen>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index d4ff275d426d..51ddb17daa00 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -335,6 +335,12 @@ public class ShellTaskOrganizer extends TaskOrganizer {
listener = mTaskListeners.get(taskId);
if (listener != null) return listener;
+ // Next priority goes to the listener listening to its parent.
+ if (runningTaskInfo.hasParentTask()) {
+ listener = mTaskListeners.get(runningTaskInfo.parentTaskId);
+ if (listener != null) return listener;
+ }
+
// Next we try type specific listeners.
final int taskListenerType = taskInfoToTaskListenerType(runningTaskInfo);
return mTaskListeners.get(taskListenerType);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
index d0ab31dd72c8..394fba6461d2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java
@@ -37,6 +37,7 @@ public final class PipBoundsState {
private final @NonNull Rect mBounds = new Rect();
private float mAspectRatio;
+ private boolean mIsStashed;
private PipReentryState mPipReentryState;
private ComponentName mLastPipComponentName;
private final DisplayInfo mDisplayInfo = new DisplayInfo();
@@ -54,6 +55,20 @@ public final class PipBoundsState {
return new Rect(mBounds);
}
+ /**
+ * Dictate where PiP currently should be stashed or not.
+ */
+ public void setStashed(boolean isStashed) {
+ mIsStashed = isStashed;
+ }
+
+ /**
+ * Whether PiP is stashed or not.
+ */
+ public boolean isStashed() {
+ return mIsStashed;
+ }
+
public void setAspectRatio(float aspectRatio) {
mAspectRatio = aspectRatio;
}
@@ -175,6 +190,7 @@ public final class PipBoundsState {
pw.println(innerPrefix + "mAspectRatio=" + mAspectRatio);
pw.println(innerPrefix + "mDisplayInfo=" + mDisplayInfo);
pw.println(innerPrefix + "mDisplayLayout=" + mDisplayLayout);
+ pw.println(innerPrefix + "mIsStashed=" + mIsStashed);
if (mPipReentryState == null) {
pw.println(innerPrefix + "mPipReentryState=null");
} else {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index f44ebf3a3a5c..833924c8ee28 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -63,7 +63,6 @@ import com.android.internal.os.SomeArgs;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.pip.phone.PipMenuActivityController;
import com.android.wm.shell.pip.phone.PipMotionHelper;
import com.android.wm.shell.pip.phone.PipUpdateThread;
@@ -137,7 +136,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
private final PipBoundsState mPipBoundsState;
private final PipBoundsHandler mPipBoundsHandler;
private final PipMenuActivityController mMenuActivityController;
- private final SystemWindows mSystemWindows;
private final PipAnimationController mPipAnimationController;
private final PipUiEventLogger mPipUiEventLoggerLogger;
private final List<PipTransitionCallback> mPipTransitionCallbacks = new ArrayList<>();
@@ -270,14 +268,12 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
Optional<SplitScreen> splitScreenOptional,
@NonNull DisplayController displayController,
@NonNull PipUiEventLogger pipUiEventLogger,
- @NonNull ShellTaskOrganizer shellTaskOrganizer,
- @NonNull SystemWindows systemWindows) {
+ @NonNull ShellTaskOrganizer shellTaskOrganizer) {
mMainHandler = new Handler(Looper.getMainLooper());
mUpdateHandler = new Handler(PipUpdateThread.get().getLooper(), mUpdateCallbacks);
mPipBoundsState = pipBoundsState;
mPipBoundsHandler = boundsHandler;
mMenuActivityController = menuActivityController;
- mSystemWindows = systemWindows;
mEnterExitAnimationDuration = context.getResources()
.getInteger(R.integer.config_pipResizeAnimationDuration);
mSurfaceTransactionHelper = surfaceTransactionHelper;
@@ -499,9 +495,13 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
}
if (mShouldIgnoreEnteringPipTransition) {
+ final Rect destinationBounds = mPipBoundsState.getBounds();
// animation is finished in the Launcher and here we directly apply the final touch.
- applyEnterPipSyncTransaction(mPipBoundsState.getBounds(),
- () -> sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP));
+ applyEnterPipSyncTransaction(destinationBounds, () -> {
+ // ensure menu's settled in its final bounds first
+ finishResizeForMenu(destinationBounds);
+ sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
+ });
mShouldIgnoreEnteringPipTransition = false;
return;
}
@@ -995,16 +995,21 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
return;
} else if (isInPipDirection(direction) && type == ANIM_TYPE_ALPHA) {
// TODO: Synchronize this correctly in #applyEnterPipSyncTransaction
- runOnMainHandler(() -> {
- mMenuActivityController.movePipMenu(null, null, destinationBounds);
- mMenuActivityController.updateMenuBounds(destinationBounds);
- });
+ finishResizeForMenu(destinationBounds);
return;
}
WindowContainerTransaction wct = new WindowContainerTransaction();
prepareFinishResizeTransaction(destinationBounds, direction, tx, wct);
applyFinishBoundsResize(wct, direction);
+ finishResizeForMenu(destinationBounds);
+ }
+
+ private void finishResizeForMenu(Rect destinationBounds) {
+ if (mMenuActivityController == null) {
+ if (DEBUG) Log.d(TAG, "mMenuActivityController is null");
+ return;
+ }
runOnMainHandler(() -> {
mMenuActivityController.movePipMenu(null, null, destinationBounds);
mMenuActivityController.updateMenuBounds(destinationBounds);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActivityController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActivityController.java
index a5252654aa23..24144b21e6d0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActivityController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActivityController.java
@@ -305,8 +305,8 @@ public class PipMenuActivityController {
}
private boolean maybeCreateSyncApplier() {
- if (mPipMenuView == null) {
- Log.v(TAG, "Not going to move PiP since the menu is not created.");
+ if (mPipMenuView == null || mPipMenuView.getViewRootImpl() == null) {
+ Log.v(TAG, "Not going to move PiP, either menu or its parent is not created.");
return false;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
index 9240b3f41ff4..9247c683a082 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
@@ -33,6 +33,7 @@ import androidx.dynamicanimation.animation.AnimationHandler;
import androidx.dynamicanimation.animation.AnimationHandler.FrameCallbackScheduler;
import androidx.dynamicanimation.animation.SpringForce;
+import com.android.wm.shell.R;
import com.android.wm.shell.animation.FloatProperties;
import com.android.wm.shell.animation.PhysicsAnimator;
import com.android.wm.shell.common.FloatingContentCoordinator;
@@ -60,7 +61,6 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
private static final int EXPAND_STACK_TO_MENU_DURATION = 250;
private static final int LEAVE_PIP_DURATION = 300;
private static final int SHIFT_DURATION = 300;
- private static final float STASH_RATIO = 0.25f;
/** Friction to use for PIP when it moves via physics fling animations. */
private static final float DEFAULT_FRICTION = 2f;
@@ -94,6 +94,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
/** The destination bounds to which PIP is animating. */
private final Rect mAnimatingToBounds = new Rect();
+ private int mStashOffset = 0;
+
/** Coordinator instance for resolving conflicts with other floating content. */
private FloatingContentCoordinator mFloatingContentCoordinator;
@@ -189,6 +191,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
mPipTaskOrganizer.registerPipTransitionCallback(mPipTransitionCallback);
mTemporaryBoundsPhysicsAnimator.setCustomAnimationHandler(
mSfAnimationHandlerThreadLocal.get());
+ reloadResources();
mResizePipUpdateListener = (target, values) -> {
if (!mTemporaryBounds.isEmpty()) {
@@ -198,6 +201,11 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
};
}
+ void reloadResources() {
+ mStashOffset = mContext.getResources()
+ .getDimensionPixelSize(R.dimen.pip_stash_offset);
+ }
+
@NonNull
@Override
public Rect getFloatingBoundsOnScreen() {
@@ -414,9 +422,10 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
FloatProperties.RECT_Y, velocityY, mFlingConfigY, mSpringConfig)
.withEndActions(endAction);
- final float offset = ((float) getBounds().width()) * (1.0f - STASH_RATIO);
- final float leftEdge = isStash ? mMovementBounds.left - offset : mMovementBounds.left;
- final float rightEdge = isStash ? mMovementBounds.right + offset : mMovementBounds.right;
+ final float leftEdge = isStash ? mStashOffset - mPipBoundsState.getBounds().width()
+ : mMovementBounds.left;
+ final float rightEdge = isStash ? mPipBoundsState.getDisplayBounds().right - mStashOffset
+ : mMovementBounds.right;
final float xEndValue = velocityX < 0 ? leftEdge : rightEdge;
final float estimatedFlingYEndValue =
@@ -524,9 +533,9 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
DEFAULT_FRICTION, mMovementBounds.left, mMovementBounds.right);
mFlingConfigY = new PhysicsAnimator.FlingConfig(
DEFAULT_FRICTION, mMovementBounds.top, mMovementBounds.bottom);
- final float offset = ((float) getBounds().width()) * (1.0f - STASH_RATIO);
mStashConfigX = new PhysicsAnimator.FlingConfig(
- DEFAULT_FRICTION, mMovementBounds.left - offset, mMovementBounds.right + offset);
+ DEFAULT_FRICTION, mStashOffset - mPipBoundsState.getBounds().width(),
+ mPipBoundsState.getDisplayBounds().right - mStashOffset);
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index ef3875597aa2..f3d8c7b0f598 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -47,6 +47,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.policy.TaskResizingAlgorithm;
import com.android.wm.shell.R;
import com.android.wm.shell.pip.PipBoundsHandler;
+import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipTaskOrganizer;
import com.android.wm.shell.pip.PipUiEventLogger;
@@ -67,6 +68,7 @@ public class PipResizeGestureHandler {
private final Context mContext;
private final PipBoundsHandler mPipBoundsHandler;
private final PipMotionHelper mMotionHelper;
+ private final PipBoundsState mPipBoundsState;
private final int mDisplayId;
private final Executor mMainExecutor;
private final ScaleGestureDetector mScaleGestureDetector;
@@ -107,13 +109,15 @@ public class PipResizeGestureHandler {
private int mCtrlType;
public PipResizeGestureHandler(Context context, PipBoundsHandler pipBoundsHandler,
- PipMotionHelper motionHelper, PipTaskOrganizer pipTaskOrganizer,
- Function<Rect, Rect> movementBoundsSupplier, Runnable updateMovementBoundsRunnable,
- PipUiEventLogger pipUiEventLogger, PipMenuActivityController menuActivityController) {
+ PipBoundsState pipBoundsState, PipMotionHelper motionHelper,
+ PipTaskOrganizer pipTaskOrganizer, Function<Rect, Rect> movementBoundsSupplier,
+ Runnable updateMovementBoundsRunnable, PipUiEventLogger pipUiEventLogger,
+ PipMenuActivityController menuActivityController) {
mContext = context;
mDisplayId = context.getDisplayId();
mMainExecutor = context.getMainExecutor();
mPipBoundsHandler = pipBoundsHandler;
+ mPipBoundsState = pipBoundsState;
mMotionHelper = motionHelper;
mPipTaskOrganizer = pipTaskOrganizer;
mMovementBoundsSupplier = movementBoundsSupplier;
@@ -263,6 +267,11 @@ public class PipResizeGestureHandler {
}
private void onInputEvent(InputEvent ev) {
+ // Don't allow resize when PiP is stashed.
+ if (mPipBoundsState.isStashed()) {
+ return;
+ }
+
if (ev instanceof MotionEvent) {
if (mUsingPinchToZoom) {
mScaleGestureDetector.onTouchEvent((MotionEvent) ev);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index e95e4a07ed92..d820e772d490 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -179,8 +179,8 @@ public class PipTouchHandler {
mMotionHelper = new PipMotionHelper(mContext, pipBoundsState, pipTaskOrganizer,
mMenuController, mPipBoundsHandler.getSnapAlgorithm(), floatingContentCoordinator);
mPipResizeGestureHandler =
- new PipResizeGestureHandler(context, pipBoundsHandler, mMotionHelper,
- pipTaskOrganizer, this::getMovementBounds,
+ new PipResizeGestureHandler(context, pipBoundsHandler, pipBoundsState,
+ mMotionHelper, pipTaskOrganizer, this::getMovementBounds,
this::updateMovementBounds, pipUiEventLogger, menuController);
mPipDismissTargetHandler = new PipDismissTargetHandler(context, pipUiEventLogger,
mMotionHelper, mHandler);
@@ -221,6 +221,7 @@ public class PipTouchHandler {
R.dimen.pip_expanded_shortest_edge_size);
mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
mPipDismissTargetHandler.updateMagneticTargetSize();
+ mMotionHelper.reloadResources();
}
private boolean shouldShowResizeHandle() {
@@ -463,7 +464,7 @@ public class PipTouchHandler {
}
MotionEvent ev = (MotionEvent) inputEvent;
- if (mPipResizeGestureHandler.willStartResizeGesture(ev)) {
+ if (!mPipBoundsState.isStashed() && mPipResizeGestureHandler.willStartResizeGesture(ev)) {
// Initialize the touch state for the gesture, but immediately reset to invalidate the
// gesture
mTouchState.onTouchEvent(ev);
@@ -553,6 +554,8 @@ public class PipTouchHandler {
}
}
+ shouldDeliverToMenu |= !mPipBoundsState.isStashed();
+
// Deliver the event to PipMenuActivity to handle button click if the menu has shown.
if (shouldDeliverToMenu) {
final MotionEvent cloneEvent = MotionEvent.obtain(ev);
@@ -715,7 +718,7 @@ public class PipTouchHandler {
// If the menu is still visible then just poke the menu
// so that it will timeout after the user stops touching it
- if (mMenuState != MENU_STATE_NONE) {
+ if (mMenuState != MENU_STATE_NONE && !mPipBoundsState.isStashed()) {
mMenuController.pokeMenu();
}
}
@@ -727,6 +730,7 @@ public class PipTouchHandler {
}
if (touchState.startedDragging()) {
+ mPipBoundsState.setStashed(false);
mSavedSnapFraction = -1f;
mPipDismissTargetHandler.showDismissTargetMaybe();
}
@@ -785,12 +789,13 @@ public class PipTouchHandler {
if (mEnableStash
&& (animatingBounds.right > mPipBoundsState.getDisplayBounds().right
|| animatingBounds.left < mPipBoundsState.getDisplayBounds().left)) {
+ mPipBoundsState.setStashed(true);
mMotionHelper.stashToEdge(vel.x, vel.y, this::flingEndAction /* endAction */);
} else {
mMotionHelper.flingToSnapTarget(vel.x, vel.y,
this::flingEndAction /* endAction */);
}
- } else if (mTouchState.isDoubleTap()) {
+ } else if (mTouchState.isDoubleTap() && !mPipBoundsState.isStashed()) {
// If using pinch to zoom, double-tap functions as resizing between max/min size
if (mPipResizeGestureHandler.isUsingPinchToZoom()) {
final boolean toExpand =
@@ -809,7 +814,7 @@ public class PipTouchHandler {
setTouchEnabled(false);
mMotionHelper.expandLeavePip();
}
- } else if (mMenuState != MENU_STATE_FULL) {
+ } else if (mMenuState != MENU_STATE_FULL && !mPipBoundsState.isStashed()) {
if (!mTouchState.isWaitingForDoubleTap()) {
// User has stalled long enough for this not to be a drag or a double tap, just
// expand the menu
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 69d428a3ae1f..8b616e8fd1ee 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -117,7 +117,7 @@ public class SplitScreenController implements SplitScreen,
mTransactionPool = transactionPool;
mWindowManagerProxy = new WindowManagerProxy(syncQueue, shellTaskOrganizer);
mTaskOrganizer = shellTaskOrganizer;
- mSplits = new SplitScreenTaskListener(this, shellTaskOrganizer);
+ mSplits = new SplitScreenTaskListener(this, shellTaskOrganizer, syncQueue);
mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler,
shellTaskOrganizer);
mRotationController =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java
index 191a317452e3..f709fed78b44 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTaskListener.java
@@ -27,8 +27,10 @@ import static com.android.wm.shell.ShellTaskOrganizer.getWindowingMode;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
import android.app.ActivityManager.RunningTaskInfo;
+import android.graphics.Point;
import android.graphics.Rect;
import android.util.Log;
+import android.util.SparseArray;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
@@ -36,6 +38,8 @@ import androidx.annotation.NonNull;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.Transitions;
+import com.android.wm.shell.common.SyncTransactionQueue;
import java.io.PrintWriter;
@@ -44,6 +48,8 @@ class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
private static final boolean DEBUG = SplitScreenController.DEBUG;
private final ShellTaskOrganizer mTaskOrganizer;
+ private final SyncTransactionQueue mSyncQueue;
+ private final SparseArray<SurfaceControl> mLeashByTaskId = new SparseArray<>();
RunningTaskInfo mPrimary;
RunningTaskInfo mSecondary;
@@ -58,9 +64,11 @@ class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
final SurfaceSession mSurfaceSession = new SurfaceSession();
SplitScreenTaskListener(SplitScreenController splitScreenController,
- ShellTaskOrganizer shellTaskOrganizer) {
+ ShellTaskOrganizer shellTaskOrganizer,
+ SyncTransactionQueue syncQueue) {
mSplitScreenController = splitScreenController;
mTaskOrganizer = shellTaskOrganizer;
+ mSyncQueue = syncQueue;
}
void init() {
@@ -93,6 +101,11 @@ class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
@Override
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
synchronized (this) {
+ if (taskInfo.hasParentTask()) {
+ handleChildTaskAppeared(taskInfo, leash);
+ return;
+ }
+
final int winMode = getWindowingMode(taskInfo);
if (winMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
ProtoLog.v(WM_SHELL_TASK_ORG,
@@ -139,6 +152,11 @@ class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
@Override
public void onTaskVanished(RunningTaskInfo taskInfo) {
synchronized (this) {
+ if (taskInfo.hasParentTask()) {
+ mLeashByTaskId.remove(taskInfo.taskId);
+ return;
+ }
+
final boolean isPrimaryTask = mPrimary != null
&& taskInfo.token.equals(mPrimary.token);
final boolean isSecondaryTask = mSecondary != null
@@ -165,7 +183,41 @@ class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
if (taskInfo.displayId != DEFAULT_DISPLAY) {
return;
}
- mSplitScreenController.post(() -> handleTaskInfoChanged(taskInfo));
+ synchronized (this) {
+ if (taskInfo.hasParentTask()) {
+ handleChildTaskChanged(taskInfo);
+ return;
+ }
+
+ mSplitScreenController.post(() -> handleTaskInfoChanged(taskInfo));
+ }
+ }
+
+ private void handleChildTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
+ mLeashByTaskId.put(taskInfo.taskId, leash);
+ updateChildTaskSurface(taskInfo, leash, true /* firstAppeared */);
+ }
+
+ private void handleChildTaskChanged(RunningTaskInfo taskInfo) {
+ final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
+ updateChildTaskSurface(taskInfo, leash, false /* firstAppeared */);
+ }
+
+ private void updateChildTaskSurface(
+ RunningTaskInfo taskInfo, SurfaceControl leash, boolean firstAppeared) {
+ final Rect taskBounds = taskInfo.getConfiguration().windowConfiguration.getBounds();
+ final Point taskPositionInParent = taskInfo.positionInParent;
+ final Rect corp = new Rect(taskBounds);
+ corp.offset(-taskBounds.left, -taskBounds.top);
+ mSyncQueue.runInSync(t -> {
+ t.setWindowCrop(leash, corp);
+ t.setPosition(leash, taskPositionInParent.x, taskPositionInParent.y);
+ if (firstAppeared && !Transitions.ENABLE_SHELL_TRANSITIONS) {
+ t.setAlpha(leash, 1f);
+ t.setMatrix(leash, 1, 0, 0, 1);
+ t.show(leash);
+ }
+ });
}
/**
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index 35a2293cbf13..e4155a257cee 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -248,6 +248,20 @@ public class ShellTaskOrganizerTests {
}
@Test
+ public void testGetParentTaskListener() {
+ RunningTaskInfo task1 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
+ TrackingTaskListener mwListener = new TrackingTaskListener();
+ mOrganizer.onTaskAppeared(task1, null);
+ mOrganizer.addListenerForTaskId(mwListener, task1.taskId);
+ RunningTaskInfo task2 = createTaskInfo(1, WINDOWING_MODE_MULTI_WINDOW);
+ task2.parentTaskId = task1.taskId;
+
+ mOrganizer.onTaskAppeared(task2, null);
+
+ assertTrue(mwListener.appeared.contains(task2));
+ }
+
+ @Test
public void testTaskInfoToTaskListenerType_whenLetterboxBoundsPassed_returnsLetterboxType() {
RunningTaskInfo taskInfo = createTaskInfo(
/* taskId */ 1,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
index ccc679797472..39381c6d677e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipTaskOrganizerTest.java
@@ -41,7 +41,6 @@ import android.window.WindowContainerToken;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.pip.phone.PipMenuActivityController;
import com.android.wm.shell.splitscreen.SplitScreen;
@@ -69,7 +68,6 @@ public class PipTaskOrganizerTest extends PipTestCase {
@Mock private PipUiEventLogger mMockPipUiEventLogger;
@Mock private Optional<SplitScreen> mMockOptionalSplitScreen;
@Mock private ShellTaskOrganizer mMockShellTaskOrganizer;
- @Mock private SystemWindows mSystemWindows;
private PipBoundsState mPipBoundsState;
private ComponentName mComponent1;
@@ -84,7 +82,7 @@ public class PipTaskOrganizerTest extends PipTestCase {
mSpiedPipTaskOrganizer = spy(new PipTaskOrganizer(mContext, mPipBoundsState,
mMockPipBoundsHandler, mMenuActivityController, mMockPipSurfaceTransactionHelper,
mMockOptionalSplitScreen, mMockdDisplayController, mMockPipUiEventLogger,
- mMockShellTaskOrganizer, mSystemWindows));
+ mMockShellTaskOrganizer));
preparePipTaskOrg();
}
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 1d06e2837841..a2861c234407 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -943,7 +943,7 @@ public final class AudioFormat implements Parcelable {
* with named endpoint channels. The samples in the frame correspond to the
* named set bits in the channel position mask, in ascending bit order.
* See {@link #setChannelIndexMask(int)} to specify channels
- * based on endpoint numbered channels. This <a href="#channelPositionMask>description of
+ * based on endpoint numbered channels. This <a href="#channelPositionMask">description of
* channel position masks</a> covers the concept in more details.
* @param channelMask describes the configuration of the audio channels.
* <p> For output, the channelMask can be an OR-ed combination of
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 42e39101de13..655454466b3d 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -16,6 +16,9 @@
package android.media;
+import static android.Manifest.permission.BIND_IMS_SERVICE;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -83,6 +86,7 @@ import java.util.BitSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Scanner;
import java.util.Set;
import java.util.UUID;
@@ -2109,8 +2113,8 @@ public class MediaPlayer extends PlayerBase
mOnInfoListener = null;
mOnVideoSizeChangedListener = null;
mOnTimedTextListener = null;
- mOnImsRxNoticeListener = null;
- mOnImsRxNoticeHandler = null;
+ mOnRtpRxNoticeListener = null;
+ mOnRtpRxNoticeHandler = null;
synchronized (mTimeProviderLock) {
if (mTimeProvider != null) {
mTimeProvider.close();
@@ -3323,7 +3327,7 @@ public class MediaPlayer extends PlayerBase
private static final int MEDIA_META_DATA = 202;
private static final int MEDIA_DRM_INFO = 210;
private static final int MEDIA_TIME_DISCONTINUITY = 211;
- private static final int MEDIA_IMS_RX_NOTICE = 300;
+ private static final int MEDIA_RTP_RX_NOTICE = 300;
private static final int MEDIA_AUDIO_ROUTING_CHANGED = 10000;
private TimeProvider mTimeProvider;
@@ -3633,31 +3637,34 @@ public class MediaPlayer extends PlayerBase
}
return;
- case MEDIA_IMS_RX_NOTICE:
- final OnImsRxNoticeListener imsRxNoticeListener;
- final Handler imsRxNoticeHandler;
- imsRxNoticeListener = mOnImsRxNoticeListener;
- imsRxNoticeHandler = mOnImsRxNoticeHandler;
- if (imsRxNoticeListener == null) {
+ case MEDIA_RTP_RX_NOTICE:
+ final OnRtpRxNoticeListener rtpRxNoticeListener = mOnRtpRxNoticeListener;
+ final Handler rtpRxNoticeHandler = mOnRtpRxNoticeHandler;
+ if (rtpRxNoticeListener == null) {
return;
}
if (msg.obj instanceof Parcel) {
Parcel parcel = (Parcel) msg.obj;
- byte[] event;
+ parcel.setDataPosition(0);
+ int noticeType;
+ int[] data;
try {
- event = parcel.marshall();
+ noticeType = parcel.readInt();
+ int numOfArgs = parcel.dataAvail() / 4;
+ data = new int[numOfArgs];
+ for (int i = 0; i < numOfArgs; i++) {
+ data[i] = parcel.readInt();
+ }
} finally {
parcel.recycle();
}
- if (imsRxNoticeHandler == null) {
- imsRxNoticeListener.onImsRxNotice(mMediaPlayer, event);
+ if (rtpRxNoticeHandler == null) {
+ rtpRxNoticeListener.onRtpRxNotice(mMediaPlayer, noticeType, data);
} else {
- imsRxNoticeHandler.post(new Runnable() {
- @Override
- public void run() {
- imsRxNoticeListener.onImsRxNotice(mMediaPlayer, event);
- }
- });
+ rtpRxNoticeHandler.post(
+ () ->
+ rtpRxNoticeListener
+ .onRtpRxNotice(mMediaPlayer, noticeType, data));
}
}
return;
@@ -4103,18 +4110,18 @@ public class MediaPlayer extends PlayerBase
/**
* Interface definition of a callback to be invoked when
- * IMS Rx connection has a notice.
+ * RTP Rx connection has a notice.
*
- * @see MediaPlayer.setOnImsRxNoticeListener
+ * @see #setOnRtpRxNoticeListener
*
* @hide
*/
@SystemApi
- public interface OnImsRxNoticeListener
+ public interface OnRtpRxNoticeListener
{
/**
- * Called to indicate an IMS event noticed from native media frameworks.
- * <p></p>
+ * Called when an RTP Rx connection has a notice.
+ * <p>
* Basic format. All TYPE and ARG are 4 bytes unsigned integer in native byte order.
* <pre>{@code
* 0 4 8 12
@@ -4169,14 +4176,14 @@ public class MediaPlayer extends PlayerBase
* TYPE 205 - Transport layer Feedback message. (RFC-5104 Sec.4.2)
* 0 4 8 12
* +----------------+---------------+----------------+----------------+
- * | 205 | SSRC | FB type(1 or 3)| value |
+ * | 205 |FB type(1 or 3)| SSRC | Value |
* +----------------+---------------+----------------+----------------+
- * SSRC
- * - Remote side's SSRC value of the media sender (RFC-3550 Sec.5.1)
* Feedback (FB) type: determines the type of the event.
* - if 1, we received a NACK request from the remote side.
* - if 3, we received a TMMBR (Temporary Maximum Media Stream Bit Rate Request) from
* the remote side.
+ * SSRC
+ * - Remote side's SSRC value of the media sender (RFC-3550 Sec.5.1)
* Value: the FCI (Feedback Control Information) depending on the value of FB type
* - if FB type is 1, the Generic NACK as specified in RFC-4585 Sec.6.2.1
* - if FB type is 3, the TMMBR as specified in RFC-5104 Sec.4.2.1.1
@@ -4185,13 +4192,13 @@ public class MediaPlayer extends PlayerBase
* TYPE 206 - Payload-specific Feedback message. (RFC-5104 Sec.4.3)
* 0 4 8
* +----------------+---------------+----------------+
- * | 206 | SSRC | FB type(1 or 4)|
+ * | 206 |FB type(1 or 4)| SSRC |
* +----------------+---------------+----------------+
- * SSRC
- * - Remote side's SSRC value of the media sender (RFC-3550 Sec.5.1)
* Feedback (FB) type: determines the type of the event.
* - if 1, we received a PLI request from the remote side.
* - if 4, we received a FIR request from the remote side.
+ * SSRC
+ * - Remote side's SSRC value of the media sender (RFC-3550 Sec.5.1)
*
*
* TYPE 300 - CVO (RTP Extension) message.
@@ -4212,34 +4219,39 @@ public class MediaPlayer extends PlayerBase
* }</pre>
*
* @param mp the {@code MediaPlayer} associated with this callback.
- * @param event an IMS media event serialized as byte[] array.
+ * @param noticeType TYPE of the event.
+ * @param params RTP Rx media data serialized as int[] array.
*/
- void onImsRxNotice(@NonNull MediaPlayer mp, @NonNull byte[] event);
+ void onRtpRxNotice(@NonNull MediaPlayer mp, int noticeType, @NonNull int[] params);
}
/**
- * Register a callback to be invoked when IMS Rx connection has a notice.
- * The callback required if mediaplayer configured for RTPSource by
- * MediaPlayer.setDataSource(String8 rtpParams) of mediaplayer.h
+ * Sets the listener to be invoked when an RTP Rx connection has a notice.
+ * The listener is required if MediaPlayer is configured for RTPSource by
+ * MediaPlayer.setDataSource(String8 rtpParams) of mediaplayer.h.
*
- * @see MediaPlayer.OnImsRxNoticeListener
+ * @see OnRtpRxNoticeListener
*
- * @param listener the callback that will be run
- * @param handler Specifies Handler object for the thread on which to execute
- * the callback. If null, the handler on the main looper will be used.
+ * @param listener the listener called after a notice from RTP Rx
+ * @param handler the {@link Handler} that receives RTP Tx events
*
* @hide
*/
@SystemApi
@RequiresPermission("android.permission.BIND_IMS_SERVICE")
- public void setOnImsRxNoticeListener(
- @Nullable OnImsRxNoticeListener listener, @Nullable Handler handler) {
- mOnImsRxNoticeListener = listener;
- mOnImsRxNoticeHandler = handler;
- }
-
- private OnImsRxNoticeListener mOnImsRxNoticeListener;
- private Handler mOnImsRxNoticeHandler;
+ public void setOnRtpRxNoticeListener(
+ @NonNull Context context,
+ @NonNull OnRtpRxNoticeListener listener, @Nullable Handler handler) {
+ Objects.requireNonNull(context);
+ Preconditions.checkArgument(
+ context.checkSelfPermission(BIND_IMS_SERVICE) == PERMISSION_GRANTED,
+ "android.permission.BIND_IMS_SERVICE permission not granted.");
+ mOnRtpRxNoticeListener = Objects.requireNonNull(listener);
+ mOnRtpRxNoticeHandler = handler;
+ }
+
+ private OnRtpRxNoticeListener mOnRtpRxNoticeListener;
+ private Handler mOnRtpRxNoticeHandler;
/**
* Register a callback to be invoked when a selected track has timed metadata available.
diff --git a/media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java b/media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java
index 9fc3a234876b..dd386b01003a 100644
--- a/media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java
+++ b/media/java/android/media/tv/tuner/frontend/DtmbFrontendCapabilities.java
@@ -25,7 +25,7 @@ import android.annotation.SystemApi;
* @hide
*/
@SystemApi
-public class DtmbFrontendCapabilities extends FrontendCapabilities {
+public final class DtmbFrontendCapabilities extends FrontendCapabilities {
private final int mModulationCap;
private final int mTransmissionModeCap;
private final int mGuardIntervalCap;
diff --git a/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
index 2c3fe6a2583c..d85e60d31f7c 100644
--- a/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DtmbFrontendSettings.java
@@ -34,7 +34,7 @@ import java.lang.annotation.RetentionPolicy;
* @hide
*/
@SystemApi
-public class DtmbFrontendSettings extends FrontendSettings {
+public final class DtmbFrontendSettings extends FrontendSettings {
/** @hide */
@IntDef(flag = true,
diff --git a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
index e6968bb4ec90..a611da669d35 100644
--- a/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/DvbcFrontendSettings.java
@@ -223,6 +223,40 @@ public class DvbcFrontendSettings extends FrontendSettings {
public static final int TIME_INTERLEAVE_MODE_128_4 = android.hardware.tv.tuner.V1_1.Constants
.FrontendCableTimeInterleaveMode.INTERLEAVING_128_4;
+ /** @hide */
+ @IntDef(flag = true,
+ prefix = "BANDWIDTH_",
+ value = {BANDWIDTH_UNDEFINED, BANDWIDTH_5MHZ, BANDWIDTH_6MHZ, BANDWIDTH_7MHZ,
+ BANDWIDTH_8MHZ})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Bandwidth {}
+
+ /**
+ * Bandwidth undefined.
+ */
+ public static final int BANDWIDTH_UNDEFINED =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.UNDEFINED;
+ /**
+ * 5 MHz bandwidth.
+ */
+ public static final int BANDWIDTH_5MHZ =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_5MHZ;
+ /**
+ * 6 MHz bandwidth.
+ */
+ public static final int BANDWIDTH_6MHZ =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_6MHZ;
+ /**
+ * 7 MHz bandwidth.
+ */
+ public static final int BANDWIDTH_7MHZ =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_7MHZ;
+ /**
+ * 8 MHz bandwidth.
+ */
+ public static final int BANDWIDTH_8MHZ =
+ android.hardware.tv.tuner.V1_1.Constants.FrontendDvbcBandwidth.BANDWIDTH_8MHZ;
+
private final int mModulation;
private final long mInnerFec;
@@ -232,9 +266,11 @@ public class DvbcFrontendSettings extends FrontendSettings {
private final int mSpectralInversion;
// Dvbc time interleave mode is only supported in Tuner 1.1 or higher.
private final int mInterleaveMode;
+ // Dvbc bandwidth is only supported in Tuner 1.1 or higher.
+ private final int mBandwidth;
private DvbcFrontendSettings(int frequency, int modulation, long innerFec, int symbolRate,
- int outerFec, int annex, int spectralInversion, int interleaveMode) {
+ int outerFec, int annex, int spectralInversion, int interleaveMode, int bandwidth) {
super(frequency);
mModulation = modulation;
mInnerFec = innerFec;
@@ -243,6 +279,7 @@ public class DvbcFrontendSettings extends FrontendSettings {
mAnnex = annex;
mSpectralInversion = spectralInversion;
mInterleaveMode = interleaveMode;
+ mBandwidth = bandwidth;
}
/**
@@ -293,6 +330,13 @@ public class DvbcFrontendSettings extends FrontendSettings {
public int getTimeInterleaveMode() {
return mInterleaveMode;
}
+ /**
+ * Gets Bandwidth.
+ */
+ @Bandwidth
+ public int getBandwidth() {
+ return mBandwidth;
+ }
/**
* Creates a builder for {@link DvbcFrontendSettings}.
@@ -314,6 +358,7 @@ public class DvbcFrontendSettings extends FrontendSettings {
private int mAnnex = ANNEX_UNDEFINED;
private int mSpectralInversion = FrontendSettings.FRONTEND_SPECTRAL_INVERSION_UNDEFINED;
private int mInterleaveMode = TIME_INTERLEAVE_MODE_UNDEFINED;
+ private int mBandwidth = BANDWIDTH_UNDEFINED;
private Builder() {
}
@@ -407,6 +452,23 @@ public class DvbcFrontendSettings extends FrontendSettings {
}
return this;
}
+ /**
+ * Set the Bandwidth.
+ *
+ * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
+ * no-op. Use {@link TunerVersionChecker.getTunerVersion()} to check the version.
+ *
+ * @param bandwidth the value to set as the bandwidth. Default value is
+ * {@link #BANDWIDTH_UNDEFINED}.
+ */
+ @NonNull
+ public Builder setBandwidth(@Bandwidth int bandwidth) {
+ if (TunerVersionChecker.checkHigherOrEqualVersionTo(
+ TunerVersionChecker.TUNER_VERSION_1_1, "setBandwidth")) {
+ mBandwidth = bandwidth;
+ }
+ return this;
+ }
/**
* Builds a {@link DvbcFrontendSettings} object.
@@ -414,7 +476,7 @@ public class DvbcFrontendSettings extends FrontendSettings {
@NonNull
public DvbcFrontendSettings build() {
return new DvbcFrontendSettings(mFrequency, mModulation, mInnerFec, mSymbolRate,
- mOuterFec, mAnnex, mSpectralInversion, mInterleaveMode);
+ mOuterFec, mAnnex, mSpectralInversion, mInterleaveMode, mBandwidth);
}
}
diff --git a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
index dd9347cd6e5d..c93e07915441 100644
--- a/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
+++ b/media/java/android/media/tv/tuner/frontend/FrontendStatus.java
@@ -17,6 +17,7 @@
package android.media.tv.tuner.frontend;
import android.annotation.IntDef;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.hardware.tv.tuner.V1_0.Constants;
@@ -634,7 +635,7 @@ public class FrontendStatus {
}
/**
- * Gets an array of BERS status.
+ * Gets an array of extended bit error ratio status.
*
* <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
* {@link TunerVersionChecker.getTunerVersion()} to check the version.
@@ -650,12 +651,14 @@ public class FrontendStatus {
}
/**
- * Gets an array of code rates status.
+ * Gets an array of code rates status. The {@link FrontendSettings.InnerFec} would be used to
+ * show the code rate.
*
* <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
* {@link TunerVersionChecker.getTunerVersion()} to check the version.
*/
@NonNull
+ @FrontendSettings.InnerFec
public int[] getCodeRates() {
TunerVersionChecker.checkHigherOrEqualVersionTo(
TunerVersionChecker.TUNER_VERSION_1_1, "getCodeRates status");
@@ -714,7 +717,8 @@ public class FrontendStatus {
}
/**
- * Gets UEC status.
+ * Gets the Uncorrectable Error Counts of the frontend's Physical Layer Pipe (PLP) since the
+ * last tune operation.
*
* <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
* {@link TunerVersionChecker.getTunerVersion()} to check the version.
@@ -729,11 +733,12 @@ public class FrontendStatus {
}
/**
- * Gets system id status.
+ * Gets the current DVB-T2 system id status.
*
* <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
* {@link TunerVersionChecker.getTunerVersion()} to check the version.
*/
+ @IntRange(from = 0, to = 0xffff)
public int getSystemId() {
TunerVersionChecker.checkHigherOrEqualVersionTo(
TunerVersionChecker.TUNER_VERSION_1_1, "getSystemId status");
@@ -744,13 +749,14 @@ public class FrontendStatus {
}
/**
- * Gets an array of interleaving status. Array value should be withink {@link
+ * Gets an array of interleaving status. Array value should be within {@link
* FrontendInterleaveMode}.
*
* <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
* {@link TunerVersionChecker.getTunerVersion()} to check the version.
*/
@NonNull
+ @FrontendInterleaveMode
public int[] getInterleaving() {
TunerVersionChecker.checkHigherOrEqualVersionTo(
TunerVersionChecker.TUNER_VERSION_1_1, "getInterleaving status");
@@ -761,12 +767,13 @@ public class FrontendStatus {
}
/**
- * Gets an array of isdbt segment status.
+ * Gets an array of the segments status in ISDB-T Specification of all the channels.
*
* <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
* {@link TunerVersionChecker.getTunerVersion()} to check the version.
*/
@NonNull
+ @IntRange(from = 0, to = 0xff)
public int[] getIsdbtSegment() {
TunerVersionChecker.checkHigherOrEqualVersionTo(
TunerVersionChecker.TUNER_VERSION_1_1, "getIsdbtSegment status");
@@ -777,7 +784,7 @@ public class FrontendStatus {
}
/**
- * Gets an array of TS data rate status.
+ * Gets an array of the Transport Stream Data Rate in BPS of the current channel.
*
* <p>This status query is only supported by Tuner HAL 1.1 or higher. Use
* {@link TunerVersionChecker.getTunerVersion()} to check the version.
@@ -800,9 +807,9 @@ public class FrontendStatus {
* {@link TunerVersionChecker.getTunerVersion()} to check the version.
*/
@NonNull
- public int[] getModulationsExt() {
+ public int[] getExtendedModulations() {
TunerVersionChecker.checkHigherOrEqualVersionTo(
- TunerVersionChecker.TUNER_VERSION_1_1, "getModulationsExt status");
+ TunerVersionChecker.TUNER_VERSION_1_1, "getExtendedModulations status");
if (mModulationsExt == null) {
throw new IllegalStateException();
}
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 1be0d4439e69..27e199205459 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -140,6 +140,7 @@ using ::android::hardware::tv::tuner::V1_1::FrontendAnalogAftFlag;
using ::android::hardware::tv::tuner::V1_1::FrontendAnalogSettingsExt1_1;
using ::android::hardware::tv::tuner::V1_1::FrontendBandwidth;
using ::android::hardware::tv::tuner::V1_1::FrontendCableTimeInterleaveMode;
+using ::android::hardware::tv::tuner::V1_1::FrontendDvbcBandwidth;
using ::android::hardware::tv::tuner::V1_1::FrontendDvbsScanType;
using ::android::hardware::tv::tuner::V1_1::FrontendDvbcSettingsExt1_1;
using ::android::hardware::tv::tuner::V1_1::FrontendDvbsSettingsExt1_1;
@@ -2725,9 +2726,13 @@ static void getDvbcFrontendSettingsExt1_1(JNIEnv *env, const jobject& settings,
FrontendCableTimeInterleaveMode interleaveMode =
static_cast<FrontendCableTimeInterleaveMode>(
env->GetIntField(settings, env->GetFieldID(clazz, "mInterleaveMode", "I")));
+ FrontendDvbcBandwidth bandwidth =
+ static_cast<FrontendDvbcBandwidth>(
+ env->GetIntField(settings, env->GetFieldID(clazz, "mBandwidth", "I")));
FrontendDvbcSettingsExt1_1 dvbcExt1_1 {
.interleaveMode = interleaveMode,
+ .bandwidth = bandwidth,
};
settingsExt1_1.settingExt.dvbc(dvbcExt1_1);
}
diff --git a/packages/CompanionDeviceManager/res/layout/buttons.xml b/packages/CompanionDeviceManager/res/layout/buttons.xml
index 7de0035d0cc9..b190a7f675ca 100644
--- a/packages/CompanionDeviceManager/res/layout/buttons.xml
+++ b/packages/CompanionDeviceManager/res/layout/buttons.xml
@@ -30,13 +30,13 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@android:string/cancel"
- style="@android:style/Widget.Material.Light.Button.Borderless.Colored"
+ style="@android:style/Widget.Material.Button.Borderless.Colored"
/>
<Button
android:id="@+id/button_pair"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@android:string/ok"
- style="@android:style/Widget.Material.Light.Button.Borderless.Colored"
+ style="@android:style/Widget.Material.Button.Borderless.Colored"
/>
</LinearLayout> \ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/layout/device_chooser.xml b/packages/CompanionDeviceManager/res/layout/device_chooser.xml
index 88de33f89442..db014aef6e8b 100644
--- a/packages/CompanionDeviceManager/res/layout/device_chooser.xml
+++ b/packages/CompanionDeviceManager/res/layout/device_chooser.xml
@@ -29,7 +29,7 @@
android:layout_height="match_parent"
android:layout_below="@+id/title"
android:layout_above="@+id/buttons"
- style="@android:style/Widget.Material.Light.ListView"
+ style="@android:style/Widget.Material.ListView"
/>
<include layout="@layout/buttons" />
diff --git a/packages/CompanionDeviceManager/res/layout/title.xml b/packages/CompanionDeviceManager/res/layout/title.xml
index dfa71e243815..0a44fbb34a9c 100644
--- a/packages/CompanionDeviceManager/res/layout/title.xml
+++ b/packages/CompanionDeviceManager/res/layout/title.xml
@@ -20,6 +20,5 @@
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:textColor="@android:color/black"
style="@*android:style/TextAppearance.Widget.Toolbar.Title"
/> \ No newline at end of file
diff --git a/packages/CompanionDeviceManager/res/values/themes.xml b/packages/CompanionDeviceManager/res/values/themes.xml
index e3fc67c50d75..667293471580 100644
--- a/packages/CompanionDeviceManager/res/values/themes.xml
+++ b/packages/CompanionDeviceManager/res/values/themes.xml
@@ -21,6 +21,7 @@
<item name="*android:windowFixedHeightMajor">100%</item>
<item name="*android:windowFixedHeightMinor">100%</item>
<item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:forceDarkAllowed">true</item>
</style>
</resources>
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index f108e06951ef..c5876af268a9 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -49,6 +49,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.net.wifi.WifiManager;
@@ -58,6 +59,8 @@ import android.os.Parcelable;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
+import android.util.SparseArray;
+import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
@@ -317,6 +320,8 @@ public class DeviceDiscoveryService extends Service {
private Drawable BLUETOOTH_ICON = icon(android.R.drawable.stat_sys_data_bluetooth);
private Drawable WIFI_ICON = icon(com.android.internal.R.drawable.ic_wifi_signal_3);
+ private SparseArray<Integer> mColors = new SparseArray();
+
private Drawable icon(int drawableRes) {
Drawable icon = getResources().getDrawable(drawableRes, null);
icon.setTint(Color.DKGRAY);
@@ -343,24 +348,36 @@ public class DeviceDiscoveryService extends Service {
textView.setText(device.getDisplayName());
textView.setBackgroundColor(
device.equals(mSelectedDevice)
- ? Color.GRAY
+ ? getColor(android.R.attr.colorControlHighlight)
: Color.TRANSPARENT);
textView.setCompoundDrawablesWithIntrinsicBounds(
device.device instanceof android.net.wifi.ScanResult
? WIFI_ICON
: BLUETOOTH_ICON,
null, null, null);
+ textView.getCompoundDrawables()[0].setTint(getColor(android.R.attr.colorForeground));
}
- //TODO move to a layout file
private TextView newView() {
final TextView textView = new TextView(DeviceDiscoveryService.this);
- textView.setTextColor(Color.BLACK);
+ textView.setTextColor(getColor(android.R.attr.colorForeground));
final int padding = DeviceChooserActivity.getPadding(getResources());
textView.setPadding(padding, padding, padding, padding);
textView.setCompoundDrawablePadding(padding);
return textView;
}
+
+ private int getColor(int colorAttr) {
+ if (mColors.contains(colorAttr)) {
+ return mColors.get(colorAttr);
+ }
+ TypedValue typedValue = new TypedValue();
+ TypedArray a = obtainStyledAttributes(typedValue.data, new int[] { colorAttr });
+ int result = a.getColor(0, 0);
+ a.recycle();
+ mColors.put(colorAttr, result);
+ return result;
+ }
}
/**
diff --git a/packages/DynamicSystemInstallationService/res/values-af/strings.xml b/packages/DynamicSystemInstallationService/res/values-af/strings.xml
index 1829d342e9c5..1b300358adb1 100644
--- a/packages/DynamicSystemInstallationService/res/values-af/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-af/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Herbegin"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Het dinamiese stelsel weggegooi"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Kan nie dinamiese stelsel herbegin of laai nie"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-am/strings.xml b/packages/DynamicSystemInstallationService/res/values-am/strings.xml
index 7fcc40de38d2..a8a7b00dd03e 100644
--- a/packages/DynamicSystemInstallationService/res/values-am/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-am/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ዳግም ጀምር"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"የተጣለ ተለዋዋጭ ሥርዓት"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ዳግም ማስጀመር አይቻልም ወይም ተለዋዋጭ ሥርዓትን ይስቀሉ"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ar/strings.xml b/packages/DynamicSystemInstallationService/res/values-ar/strings.xml
index be705c37ef1d..44a6503eec08 100644
--- a/packages/DynamicSystemInstallationService/res/values-ar/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ar/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"إعادة التشغيل"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"تم تجاهل النظام الديناميكي."</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"لا يمكن إعادة التشغيل أو تحميل النظام الديناميكي."</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-as/strings.xml b/packages/DynamicSystemInstallationService/res/values-as/strings.xml
index 14eead9f9753..e93ad9bec77c 100644
--- a/packages/DynamicSystemInstallationService/res/values-as/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-as/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ৰিষ্টাৰ্ট কৰক"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"বাতিল কৰা ডায়নামিক ছিষ্টেম"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ডায়নামিক ছিষ্টেম ৰিষ্টার্ট অথবা ল\'ড কৰিব নোৱাৰি"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-az/strings.xml b/packages/DynamicSystemInstallationService/res/values-az/strings.xml
index d1f0a4b78ebb..ad3d3e7b1d28 100644
--- a/packages/DynamicSystemInstallationService/res/values-az/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-az/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Yenidən başladın"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinamik sistemdən imtina edildi"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dinamik sistemi yenidən başlatmaq və ya yükləmək mümkün deyil"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-b+sr+Latn/strings.xml b/packages/DynamicSystemInstallationService/res/values-b+sr+Latn/strings.xml
index ea23a28bc9e5..01070479cd53 100644
--- a/packages/DynamicSystemInstallationService/res/values-b+sr+Latn/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-b+sr+Latn/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Restartuj"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinamični sistem je odbačen"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Restartovanje ili učitavanje dinamičnog sistema nije uspelo"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-be/strings.xml b/packages/DynamicSystemInstallationService/res/values-be/strings.xml
index 7eef297be292..5a52f735aee1 100644
--- a/packages/DynamicSystemInstallationService/res/values-be/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-be/strings.xml
@@ -5,7 +5,7 @@
<string name="notification_install_completed" msgid="6252047868415172643">"Дынамічная сістэма гатовая. Каб пачаць выкарыстоўваць яе, перазапусціце прыладу."</string>
<string name="notification_install_inprogress" msgid="7383334330065065017">"Ідзе ўсталёўка"</string>
<string name="notification_install_failed" msgid="4066039210317521404">"Збой усталёўкі"</string>
- <string name="notification_image_validation_failed" msgid="2720357826403917016">"Збой пры праверцы відарыса. Усталёўка спынена."</string>
+ <string name="notification_image_validation_failed" msgid="2720357826403917016">"Збой пры праверцы вобраза дыска. Усталёўка спынена."</string>
<string name="notification_dynsystem_in_use" msgid="1053194595682188396">"Цяпер запушчана дынамічная сістэма. Перазапусціце, каб скарыстаць арыгінальную версію Android."</string>
<string name="notification_action_cancel" msgid="5929299408545961077">"Скасаваць"</string>
<string name="notification_action_discard" msgid="1817481003134947493">"Адхіліць"</string>
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Перазапусціць"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Дынамічная сістэма адхілена"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Не ўдалося перазапусціць або загрузіць дынамічную сістэму"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-bg/strings.xml b/packages/DynamicSystemInstallationService/res/values-bg/strings.xml
index 9176676c0618..194bf2dd5a58 100644
--- a/packages/DynamicSystemInstallationService/res/values-bg/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-bg/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Рестартиране"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Динамичната система е отхвърлена"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Динамичната система не може да се рестартира или зареди"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-bn/strings.xml b/packages/DynamicSystemInstallationService/res/values-bn/strings.xml
index 38ef64935fb4..43886b348888 100644
--- a/packages/DynamicSystemInstallationService/res/values-bn/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-bn/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"রিস্টার্ট করুন"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ডায়নামিক সিস্টেম বাতিল করা হয়েছে"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ডায়নামিক সিস্টেম রিস্টার্ট বা লোড করা যাচ্ছে না"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-bs/strings.xml b/packages/DynamicSystemInstallationService/res/values-bs/strings.xml
index 84ba540bb822..342230b25f9d 100644
--- a/packages/DynamicSystemInstallationService/res/values-bs/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-bs/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Ponovo pokreni"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinamični sistem je odbačen"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nije moguće ponovo pokrenuti ili učitati dinamični sistem"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ca/strings.xml b/packages/DynamicSystemInstallationService/res/values-ca/strings.xml
index 787e4960513b..e9e4d3573f58 100644
--- a/packages/DynamicSystemInstallationService/res/values-ca/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ca/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reinicia"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"S\'ha descartat el sistema dinàmic"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"No es pot reiniciar ni carregar el sistema dinàmic"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-cs/strings.xml b/packages/DynamicSystemInstallationService/res/values-cs/strings.xml
index 3dfb23f7d2ff..6ae71c6c438b 100644
--- a/packages/DynamicSystemInstallationService/res/values-cs/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-cs/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Restartovat"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Zahodit dynamický systém"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dynamický systém nelze znovu spustit nebo načíst"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-da/strings.xml b/packages/DynamicSystemInstallationService/res/values-da/strings.xml
index 20005e739205..10b798c2ce29 100644
--- a/packages/DynamicSystemInstallationService/res/values-da/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-da/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Genstart"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Det dynamiske system blev slettet"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Det dynamiske system kan ikke genstartes eller indlæses"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-de/strings.xml b/packages/DynamicSystemInstallationService/res/values-de/strings.xml
index 3f000eaea251..82459b2f368d 100644
--- a/packages/DynamicSystemInstallationService/res/values-de/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-de/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Neu starten"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dynamisches System verworfen"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Neustart und Laden des dynamischen Systems nicht möglich"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-el/strings.xml b/packages/DynamicSystemInstallationService/res/values-el/strings.xml
index 4d830dde12e5..ef029063f544 100644
--- a/packages/DynamicSystemInstallationService/res/values-el/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-el/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Επανεκκίνηση"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Οι δυναμικές συστήματος απορρίφθηκαν."</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Δεν είναι δυνατή η επανεκκίνηση ή η φόρτωση δυναμικών συστήματος"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-en-rAU/strings.xml b/packages/DynamicSystemInstallationService/res/values-en-rAU/strings.xml
index d72863128257..6f3f88763597 100644
--- a/packages/DynamicSystemInstallationService/res/values-en-rAU/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-en-rAU/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Restart"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Discarded dynamic system"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Can’t restart or load dynamic system"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-en-rCA/strings.xml b/packages/DynamicSystemInstallationService/res/values-en-rCA/strings.xml
index d72863128257..6f3f88763597 100644
--- a/packages/DynamicSystemInstallationService/res/values-en-rCA/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-en-rCA/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Restart"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Discarded dynamic system"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Can’t restart or load dynamic system"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-en-rGB/strings.xml b/packages/DynamicSystemInstallationService/res/values-en-rGB/strings.xml
index d72863128257..6f3f88763597 100644
--- a/packages/DynamicSystemInstallationService/res/values-en-rGB/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-en-rGB/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Restart"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Discarded dynamic system"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Can’t restart or load dynamic system"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-en-rIN/strings.xml b/packages/DynamicSystemInstallationService/res/values-en-rIN/strings.xml
index d72863128257..6f3f88763597 100644
--- a/packages/DynamicSystemInstallationService/res/values-en-rIN/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-en-rIN/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Restart"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Discarded dynamic system"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Can’t restart or load dynamic system"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-en-rXC/strings.xml b/packages/DynamicSystemInstallationService/res/values-en-rXC/strings.xml
index 6ac376322ceb..2e83672f1927 100644
--- a/packages/DynamicSystemInstallationService/res/values-en-rXC/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-en-rXC/strings.xml
@@ -13,4 +13,5 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‎‎‏‎‎‎‏‎‏‏‏‎‎‎‎‏‎‎‎‎‏‏‏‏‏‎‏‎‎‏‎Restart‎‏‎‎‏‎"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎Discarded dynamic system‎‏‎‎‏‎"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‏‎‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‎Can’t restart or load dynamic system‎‏‎‎‏‎"</string>
+ <string name="toast_failed_to_disable_dynsystem" msgid="3285742944977744413">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‎‎‏‎‏‎‎‏‏‎‏‏‏‎‎‏‏‎‎‏‏‎‎‎‎‏‎‏‎‏‎‎‏‎‎‏‏‏‏‎‎‏‎‎‎‎‏‏‏‎‏‎Failed to disable dynamic system‎‏‎‎‏‎"</string>
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-es-rUS/strings.xml b/packages/DynamicSystemInstallationService/res/values-es-rUS/strings.xml
index 9ec819656495..aeb65be46f27 100644
--- a/packages/DynamicSystemInstallationService/res/values-es-rUS/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-es-rUS/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reiniciar"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Se descartó el sistema dinámico"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"No se puede reiniciar o cargar el sistema dinámico"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-es/strings.xml b/packages/DynamicSystemInstallationService/res/values-es/strings.xml
index cd9db07168a2..0c3ae5381453 100644
--- a/packages/DynamicSystemInstallationService/res/values-es/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-es/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reiniciar"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Se ha descartado el sistema dinámico"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"No se ha podido reiniciar o cargar el sistema dinámico"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-et/strings.xml b/packages/DynamicSystemInstallationService/res/values-et/strings.xml
index 64968b60ac6f..ab20a04493ef 100644
--- a/packages/DynamicSystemInstallationService/res/values-et/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-et/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Taaskäivita"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dünaamilisest süsteemist loobuti"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dünaamilist süsteemi ei saa taaskäivitada ega laadida"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-eu/strings.xml b/packages/DynamicSystemInstallationService/res/values-eu/strings.xml
index 7c4a67d4e6c2..18637786ebea 100644
--- a/packages/DynamicSystemInstallationService/res/values-eu/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-eu/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Berrabiarazi"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Baztertu da sistema dinamikoa"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Ezin da berrabiarazi edo kargatu sistema dinamikoa"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-fa/strings.xml b/packages/DynamicSystemInstallationService/res/values-fa/strings.xml
index 7533e71cb26c..5b0b21891a09 100644
--- a/packages/DynamicSystemInstallationService/res/values-fa/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-fa/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"بازراه‌اندازی"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"از سیستم پویا صرف‌نظر شد"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"نمی‌توان سیستم پویا را بازراه‌اندازی یا بار کرد"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-fi/strings.xml b/packages/DynamicSystemInstallationService/res/values-fi/strings.xml
index 948c3336cea8..b4315e7a22ef 100644
--- a/packages/DynamicSystemInstallationService/res/values-fi/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-fi/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Käynn. uudelleen"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dynaaminen järjestelmä hylätty"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dynaamista järjestelmää ei voi käynnistää uudelleen tai ladata"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-fr-rCA/strings.xml b/packages/DynamicSystemInstallationService/res/values-fr-rCA/strings.xml
index 6e2f235bcb76..973efef68a47 100644
--- a/packages/DynamicSystemInstallationService/res/values-fr-rCA/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-fr-rCA/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Redémarrer"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Système dynamique supprimé"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Impossible de redémarrer ou de charger le système dynamique"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-fr/strings.xml b/packages/DynamicSystemInstallationService/res/values-fr/strings.xml
index 67f799731c6d..5422e8e4ec5b 100644
--- a/packages/DynamicSystemInstallationService/res/values-fr/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-fr/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Redémarrer"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Système dynamique supprimé"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Impossible de redémarrer ou de charger le système dynamique"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-gl/strings.xml b/packages/DynamicSystemInstallationService/res/values-gl/strings.xml
index 8ea6d1c6c3b6..e24f495a425f 100644
--- a/packages/DynamicSystemInstallationService/res/values-gl/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-gl/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reiniciar"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Descartouse o sistema dinámico"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Non se puido reiniciar nin cargar o sistema dinámico"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-gu/strings.xml b/packages/DynamicSystemInstallationService/res/values-gu/strings.xml
index aec18049fdb0..6c2e67336c21 100644
--- a/packages/DynamicSystemInstallationService/res/values-gu/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-gu/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ફરી શરૂ કરો"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ડાઇનૅમિક સિસ્ટમ કાઢી નાખવામાં આવી"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ડાઇનૅમિક સિસ્ટમને ફરી શરૂ અથવા લોડ કરી શકાતી નથી"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-hi/strings.xml b/packages/DynamicSystemInstallationService/res/values-hi/strings.xml
index efedbe8e7ee6..13dc9e8a3984 100644
--- a/packages/DynamicSystemInstallationService/res/values-hi/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-hi/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"रीस्टार्ट करें"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"डाइनैमिक सिस्टम खारिज किया गया"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"डाइनैमिक सिस्टम रीस्टार्ट या लोड नहीं हो सका"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-hr/strings.xml b/packages/DynamicSystemInstallationService/res/values-hr/strings.xml
index 50ceaa16f764..3318d2040196 100644
--- a/packages/DynamicSystemInstallationService/res/values-hr/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-hr/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Pokreni"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Odbačeni dinamični sustav"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nije moguće ponovno pokretanje ili učitavanje dinamičnog sustava"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-hu/strings.xml b/packages/DynamicSystemInstallationService/res/values-hu/strings.xml
index 94afa3b927b3..208ab3bdd260 100644
--- a/packages/DynamicSystemInstallationService/res/values-hu/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-hu/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Újraindítás"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Elvetett dinamikus rendszer"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nem lehet újraindítani vagy betölteni a dinamikus rendszert"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-hy/strings.xml b/packages/DynamicSystemInstallationService/res/values-hy/strings.xml
index b0cd740d3e8d..4dcc72e38121 100644
--- a/packages/DynamicSystemInstallationService/res/values-hy/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-hy/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Վերագործարկել"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Դինամիկ համակարգի գործարկումը չեղարկվեց"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Չհաջողվեց վերագործարկել կամ բեռնել դինամիկ համակարգը"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-in/strings.xml b/packages/DynamicSystemInstallationService/res/values-in/strings.xml
index 44b4aeec8b78..2fa4f113341a 100644
--- a/packages/DynamicSystemInstallationService/res/values-in/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-in/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Mulai ulang"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dynamic System dihapus"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Tidak dapat memulai ulang atau memuat Dynamic System"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-is/strings.xml b/packages/DynamicSystemInstallationService/res/values-is/strings.xml
index 048d1bca5518..ef7484c1d6cc 100644
--- a/packages/DynamicSystemInstallationService/res/values-is/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-is/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Endurræsa"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Breytilegu kerfi fleygt"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Ekki tókst að endurræsa eða hlaða breytilegu kerfi"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-it/strings.xml b/packages/DynamicSystemInstallationService/res/values-it/strings.xml
index f70b38178021..c8fa41b3c92c 100644
--- a/packages/DynamicSystemInstallationService/res/values-it/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-it/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Riavvia"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Sistema dinamico annullato"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Impossibile riavviare o caricare il sistema dinamico"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-iw/strings.xml b/packages/DynamicSystemInstallationService/res/values-iw/strings.xml
index aff7c824ba1d..d9bf983d4d76 100644
--- a/packages/DynamicSystemInstallationService/res/values-iw/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-iw/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"הפעלה מחדש"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"המערכת הדינמית נסגרה"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"לא ניתן להפעיל מחדש או לטעון את המערכת הדינמית"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ja/strings.xml b/packages/DynamicSystemInstallationService/res/values-ja/strings.xml
index 46c093057a49..2082d91294da 100644
--- a/packages/DynamicSystemInstallationService/res/values-ja/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ja/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"再起動"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"動的システムを破棄しました"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"動的システムの再起動や読み込みを行えません"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ka/strings.xml b/packages/DynamicSystemInstallationService/res/values-ka/strings.xml
index f841a59801e4..e57de2c1016a 100644
--- a/packages/DynamicSystemInstallationService/res/values-ka/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ka/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"გადატვირთვა"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"გაუქმებული დინამიური სისტემა"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"დინამიური სისტემის გადატვირთვა ან ჩატვირთვა ვერ ხერხდება"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-kk/strings.xml b/packages/DynamicSystemInstallationService/res/values-kk/strings.xml
index d367b614e528..da10e9c582c0 100644
--- a/packages/DynamicSystemInstallationService/res/values-kk/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-kk/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Қайта қосу"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Динамикалық жүйе өшірілді."</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Динамикалық жүйені қайта қосу не жүктеу мүмкін емес."</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-km/strings.xml b/packages/DynamicSystemInstallationService/res/values-km/strings.xml
index 56a37164fa6e..7bb5980ca1d4 100644
--- a/packages/DynamicSystemInstallationService/res/values-km/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-km/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ចាប់ផ្ដើមឡើងវិញ"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"បានលុបចោល​ប្រព័ន្ធឌីណាមិច"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"មិនអាច​ចាប់ផ្ដើមឡើងវិញ ឬផ្ទុក​ប្រព័ន្ធឌីណាមិច​បានទេ"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-kn/strings.xml b/packages/DynamicSystemInstallationService/res/values-kn/strings.xml
index b4063df9c10d..f41f2eff5cde 100644
--- a/packages/DynamicSystemInstallationService/res/values-kn/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-kn/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ಮರುಪ್ರಾರಂಭಿಸಿ"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ಡೈನಮಿಕ್ ಸಿಸ್ಟಂ ಅನ್ನು ತ್ಯಜಿಸಲಾಗಿದೆ"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ಡೈನಾಮಿಕ್ ಸಿಸ್ಟಂ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಲು ಅಥವಾ ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ko/strings.xml b/packages/DynamicSystemInstallationService/res/values-ko/strings.xml
index 24ac9245e22c..bca9e0725a6e 100644
--- a/packages/DynamicSystemInstallationService/res/values-ko/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ko/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"다시 시작"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"동적 시스템 삭제됨"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"동적 시스템을 다시 시작하거나 로드할 수 없음"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ky/strings.xml b/packages/DynamicSystemInstallationService/res/values-ky/strings.xml
index a4387e7bf4a1..d2ad56a44897 100644
--- a/packages/DynamicSystemInstallationService/res/values-ky/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ky/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Өчүрүп күйгүзүү"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Динамикалык система жоюлду"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Динамикалык система өчүрүлүп күйгүзүлбөй же жүктөлбөй жатат"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-lo/strings.xml b/packages/DynamicSystemInstallationService/res/values-lo/strings.xml
index f17ca16bf777..a732aa414780 100644
--- a/packages/DynamicSystemInstallationService/res/values-lo/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-lo/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ຣີສະຕາດ"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ລະບົບໄດນາມິກທີ່ຍົກເລີກແລ້ວ"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ບໍ່ສາມາດຣີສະຕາດ ຫຼື ໂຫຼດລະບົບໄດນາມິກໄດ້"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-lt/strings.xml b/packages/DynamicSystemInstallationService/res/values-lt/strings.xml
index 8128eb7b0a72..b25c62a5f4ff 100644
--- a/packages/DynamicSystemInstallationService/res/values-lt/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-lt/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Pal. iš naujo"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinaminė sistema atmesta"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nepavyko paleisti iš naujo ar įkelti dinaminės sistemos"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-lv/strings.xml b/packages/DynamicSystemInstallationService/res/values-lv/strings.xml
index cfe7a087e148..4ca6ace3f5b3 100644
--- a/packages/DynamicSystemInstallationService/res/values-lv/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-lv/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Restartēt"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinamiskā sistēma tika atmesta"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nevar restartēt vai ielādēt dinamisko sistēmu"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-mk/strings.xml b/packages/DynamicSystemInstallationService/res/values-mk/strings.xml
index 21215aa77631..52a52a5ca10d 100644
--- a/packages/DynamicSystemInstallationService/res/values-mk/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-mk/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Рестартирај"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Отфрлен динамичен систем"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Не може да го рестартира или вчита динамичниот систем"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ml/strings.xml b/packages/DynamicSystemInstallationService/res/values-ml/strings.xml
index 951a0b95f7e4..25040694bbda 100644
--- a/packages/DynamicSystemInstallationService/res/values-ml/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ml/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"റീസ്റ്റാർട്ട് ചെയ്യൂ"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ഡെെനാമിക് സിസ്റ്റം നിരസിച്ചു"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"റീസ്റ്റാർട്ട് ചെയ്യാനോ ഡെെനാമിക് സിസ്റ്റം ലോഡ് ചെയ്യാനോ ആവില്ല"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-mn/strings.xml b/packages/DynamicSystemInstallationService/res/values-mn/strings.xml
index d0965d021c65..fe93f65939b3 100644
--- a/packages/DynamicSystemInstallationService/res/values-mn/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-mn/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Дахин эхлүүлэх"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Динамик системийг устгасан"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Динамик системийг дахин эхлүүлэх эсвэл ачаалах боломжгүй байна"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-mr/strings.xml b/packages/DynamicSystemInstallationService/res/values-mr/strings.xml
index 268e1d344620..5f27af01f635 100644
--- a/packages/DynamicSystemInstallationService/res/values-mr/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-mr/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"रीस्टार्ट करा"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"डायनॅमिक सिस्टम काढून टाकली"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"डायनॅमिक सिस्टम रीस्टार्ट किंवा लोड करू शकत नाही"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ms/strings.xml b/packages/DynamicSystemInstallationService/res/values-ms/strings.xml
index bba8b9724f0d..797152c937ed 100644
--- a/packages/DynamicSystemInstallationService/res/values-ms/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ms/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Mulakan semula"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Sistem dinamik dibuang"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Tidak dapat memulakan semula atau memuatkan sistem dinamik"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-my/strings.xml b/packages/DynamicSystemInstallationService/res/values-my/strings.xml
index b2488ece9ce3..3ee85b2136ee 100644
--- a/packages/DynamicSystemInstallationService/res/values-my/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-my/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ပြန်စရန်"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ပြောင်းလဲနိုင်သောစနစ်ကို ဖယ်လိုက်သည်"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ပြန်စ၍ မရပါ (သို့) ပြောင်းလဲနိုင်သောစနစ် ဖွင့်၍မရပါ"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-nb/strings.xml b/packages/DynamicSystemInstallationService/res/values-nb/strings.xml
index 36e3d6912e23..88087e542b0c 100644
--- a/packages/DynamicSystemInstallationService/res/values-nb/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-nb/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Start på nytt"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Det dynamiske systemet er forkastet"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Det dynamiske systemet kan ikke startes på nytt eller lastes inn"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ne/strings.xml b/packages/DynamicSystemInstallationService/res/values-ne/strings.xml
index ee9267852250..da98fee056e5 100644
--- a/packages/DynamicSystemInstallationService/res/values-ne/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ne/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"रिस्टार्ट गर्नु…"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dynamic System खारेज गरियो"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"रिस्टार्ट गर्न वा Dynamic System लोड गर्न सकिएन"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-nl/strings.xml b/packages/DynamicSystemInstallationService/res/values-nl/strings.xml
index 2b9fa414dcc5..5120c90eadc6 100644
--- a/packages/DynamicSystemInstallationService/res/values-nl/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-nl/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Herstarten"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dynamisch systeem niet opgeslagen"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Kan dynamisch systeem niet opnieuw opstarten of laden"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-or/strings.xml b/packages/DynamicSystemInstallationService/res/values-or/strings.xml
index e0c847094844..878947e48579 100644
--- a/packages/DynamicSystemInstallationService/res/values-or/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-or/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ରିଷ୍ଟାର୍ଟ କରନ୍ତୁ"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ଡାଇନାମିକ୍ ସିଷ୍ଟମ୍ ଖାରଜ କରାଯାଇଛି"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ଡାଇନାମିକ୍ ସିଷ୍ଟମ୍ ରିଷ୍ଟାର୍ଟ କିମ୍ବା ଲୋଡ୍ କରାଯାଇପାରିବ ନାହିଁ"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-pa/strings.xml b/packages/DynamicSystemInstallationService/res/values-pa/strings.xml
index c5f7a3d38cdc..2695aaf39b25 100644
--- a/packages/DynamicSystemInstallationService/res/values-pa/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-pa/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ਮੁੜ-ਸ਼ੁਰੂ ਕਰੋ"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ਪਰਿਵਰਤਨਸ਼ੀਲ ਸਿਸਟਮ ਰੱਦ ਕੀਤਾ ਗਿਆ"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ਪਰਿਵਰਤਨਸ਼ੀਲ ਸਿਸਟਮ ਮੁੜ-ਸ਼ੁਰੂ ਜਾਂ ਲੋਡ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-pl/strings.xml b/packages/DynamicSystemInstallationService/res/values-pl/strings.xml
index bc7d5fe5b222..33592c86a090 100644
--- a/packages/DynamicSystemInstallationService/res/values-pl/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-pl/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Uruchom ponownie"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Usunięto system dynamiczny"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nie można ponownie uruchomić lub wczytać systemu dynamicznego"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-pt-rBR/strings.xml b/packages/DynamicSystemInstallationService/res/values-pt-rBR/strings.xml
index 31a9bb439235..43bd02135672 100644
--- a/packages/DynamicSystemInstallationService/res/values-pt-rBR/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-pt-rBR/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reiniciar"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Sistema dinâmico descartado"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Não é possível reiniciar ou carregar o sistema dinâmico"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-pt-rPT/strings.xml b/packages/DynamicSystemInstallationService/res/values-pt-rPT/strings.xml
index d917c6afec6e..dc29a659d24c 100644
--- a/packages/DynamicSystemInstallationService/res/values-pt-rPT/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-pt-rPT/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reiniciar"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Sistema dinâmico rejeitado"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Não é possível reiniciar ou carregar o sistema dinâmico."</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-pt/strings.xml b/packages/DynamicSystemInstallationService/res/values-pt/strings.xml
index 31a9bb439235..43bd02135672 100644
--- a/packages/DynamicSystemInstallationService/res/values-pt/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-pt/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reiniciar"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Sistema dinâmico descartado"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Não é possível reiniciar ou carregar o sistema dinâmico"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ro/strings.xml b/packages/DynamicSystemInstallationService/res/values-ro/strings.xml
index c21131857830..c9d391a7fb88 100644
--- a/packages/DynamicSystemInstallationService/res/values-ro/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ro/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reporniți"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"S-a renunțat la sistemul dinamic"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nu se poate reporni sau încărca sistemul dinamic"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ru/strings.xml b/packages/DynamicSystemInstallationService/res/values-ru/strings.xml
index bf94c99b8fb5..cba9a713f8fa 100644
--- a/packages/DynamicSystemInstallationService/res/values-ru/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ru/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Перезапустить"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Динамическая система удалена."</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Не удается запустить или загрузить динамическую систему."</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-si/strings.xml b/packages/DynamicSystemInstallationService/res/values-si/strings.xml
index e6a6ea2fe351..7aab6e9b0ada 100644
--- a/packages/DynamicSystemInstallationService/res/values-si/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-si/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"යළි අරඹන්න"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ගතික පද්ධතිය ඉවත දමන ලදි"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ගතික පද්ධතිය නැවත ආරම්භ කිරීමට හෝ පූරණය කිරීමට නොහැක"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-sk/strings.xml b/packages/DynamicSystemInstallationService/res/values-sk/strings.xml
index 99390cf07c74..61c176fb8905 100644
--- a/packages/DynamicSystemInstallationService/res/values-sk/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-sk/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Reštartovať"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Zahodený dynamický systém"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Nie je možné reštartovať alebo načítať dynamický systém"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-sl/strings.xml b/packages/DynamicSystemInstallationService/res/values-sl/strings.xml
index 3ffd741ea4f6..0be1248bcff1 100644
--- a/packages/DynamicSystemInstallationService/res/values-sl/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-sl/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Znova zaženi"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinamični sistem je bil zavržen"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dinamičnega sistema ni mogoče znova zagnati ali naložiti"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-sq/strings.xml b/packages/DynamicSystemInstallationService/res/values-sq/strings.xml
index 704b512ad9ab..43a5f7bbc876 100644
--- a/packages/DynamicSystemInstallationService/res/values-sq/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-sq/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Rinis"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Sistemi dinamik u hoq"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Sistemi dinamik nuk mund të rinisej ose të ngarkohej"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-sr/strings.xml b/packages/DynamicSystemInstallationService/res/values-sr/strings.xml
index 5e4540a5eff0..a5ba6565d1ea 100644
--- a/packages/DynamicSystemInstallationService/res/values-sr/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-sr/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Рестартуј"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Динамични систем је одбачен"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Рестартовање или учитавање динамичног система није успело"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-sv/strings.xml b/packages/DynamicSystemInstallationService/res/values-sv/strings.xml
index 546ffddde639..99e6752c0bed 100644
--- a/packages/DynamicSystemInstallationService/res/values-sv/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-sv/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Starta om"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Det dynamiska systemet ignorerades"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Det gick inte att starta om eller läsa in det dynamiska systemet"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-sw/strings.xml b/packages/DynamicSystemInstallationService/res/values-sw/strings.xml
index 53414d5f6b0a..8af9ad35a763 100644
--- a/packages/DynamicSystemInstallationService/res/values-sw/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-sw/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Zima kisha uwashe"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Umeondoa Dynamic System"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Imeshindwa kuzima na kuwasha au kupakia Dynamic System"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ta/strings.xml b/packages/DynamicSystemInstallationService/res/values-ta/strings.xml
index e0aaaf7458fc..bbe8c4e5e03e 100644
--- a/packages/DynamicSystemInstallationService/res/values-ta/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ta/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"மீண்டும் தொடங்கு"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dynamic system நிராகரிக்கப்பட்டது"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dynamic systemமை மீண்டும் தொடங்கவோ ஏற்றவோ முடியவில்லை"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-te/strings.xml b/packages/DynamicSystemInstallationService/res/values-te/strings.xml
index d497630660e3..4a9433e7116e 100644
--- a/packages/DynamicSystemInstallationService/res/values-te/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-te/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"రీస్టార్ట్ చేయి"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"డైనమిక్ సిస్టమ్ విస్మరించబడింది"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"డైనమిక్ సిస్టమ్‌ను రీస్టార్ట్ చేయడం లేదా లోడ్ చేయడం సాధ్యపడలేదు"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-th/strings.xml b/packages/DynamicSystemInstallationService/res/values-th/strings.xml
index 786324f57488..5b81a03c51e3 100644
--- a/packages/DynamicSystemInstallationService/res/values-th/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-th/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"รีสตาร์ท"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"ยกเลิกระบบแบบไดนามิกแล้ว"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"รีสตาร์ทหรือโหลดระบบแบบไดนามิกไม่ได้"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-tl/strings.xml b/packages/DynamicSystemInstallationService/res/values-tl/strings.xml
index df39f7b1886a..d6c2f1508f75 100644
--- a/packages/DynamicSystemInstallationService/res/values-tl/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-tl/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"I-restart"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Na-discard ang dynamic system"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Hindi ma-restart o ma-load ang dynamic system"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-tr/strings.xml b/packages/DynamicSystemInstallationService/res/values-tr/strings.xml
index 1446f9632456..a98526e0cdbe 100644
--- a/packages/DynamicSystemInstallationService/res/values-tr/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-tr/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Yeniden başlat"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinamik sistem silindi"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dinamik sistem yeniden başlatılamıyor veya yüklenemiyor"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-uk/strings.xml b/packages/DynamicSystemInstallationService/res/values-uk/strings.xml
index 9a44d9764014..65267872b724 100644
--- a/packages/DynamicSystemInstallationService/res/values-uk/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-uk/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Перезапустити"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Динамічну систему видалено"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Не вдається перезапустити пристрій або завантажити динамічну систему"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-ur/strings.xml b/packages/DynamicSystemInstallationService/res/values-ur/strings.xml
index 48dddbea3281..f5e2b744e5b2 100644
--- a/packages/DynamicSystemInstallationService/res/values-ur/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-ur/strings.xml
@@ -5,7 +5,7 @@
<string name="notification_install_completed" msgid="6252047868415172643">"ڈائنیمک سسٹم تیار ہے۔ اس کا استعمال شروع کرنے کے لیے، اپنا آلہ ری سٹارٹ کریں۔"</string>
<string name="notification_install_inprogress" msgid="7383334330065065017">"انسٹال جاری ہے"</string>
<string name="notification_install_failed" msgid="4066039210317521404">"انسٹال ناکام ہو گیا"</string>
- <string name="notification_image_validation_failed" msgid="2720357826403917016">"تصویر کی توثیق ناکام ہو گئی۔ انسٹالیشن منسوخ کریں-"</string>
+ <string name="notification_image_validation_failed" msgid="2720357826403917016">"ڈسک امیج کی توثیق ناکام ہو گئی۔ انسٹالیشن منسوخ کریں۔"</string>
<string name="notification_dynsystem_in_use" msgid="1053194595682188396">"‏فی الحال ہم ایک ڈائنیمک سسٹم چلا رہے ہیں۔ Android کا اصل ورژن استعمال کرنے کے لیے ری سٹارٹ کریں۔"</string>
<string name="notification_action_cancel" msgid="5929299408545961077">"منسوخ کریں"</string>
<string name="notification_action_discard" msgid="1817481003134947493">"مسترد کریں"</string>
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"ری سٹارٹ کریں"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"مسترد کردہ ڈائنیمک سسٹم"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"ڈائنیمک سسٹم کو ری سٹارٹ یا لوڈ نہیں کر سکتے"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-uz/strings.xml b/packages/DynamicSystemInstallationService/res/values-uz/strings.xml
index 3f0227c1c383..3c347e2e87ba 100644
--- a/packages/DynamicSystemInstallationService/res/values-uz/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-uz/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Boshidan"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Dinamik tizim bekor qilindi"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Dinamik tizim qayta ishga tushmadi yoki yuklanmadi"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-vi/strings.xml b/packages/DynamicSystemInstallationService/res/values-vi/strings.xml
index 18c051c893f8..a93d29e383ca 100644
--- a/packages/DynamicSystemInstallationService/res/values-vi/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-vi/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Khởi động lại"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Đã hủy hệ thống động"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Không thể khởi động lại hoặc tải hệ thống động"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-zh-rCN/strings.xml b/packages/DynamicSystemInstallationService/res/values-zh-rCN/strings.xml
index b41d4e2bf912..c27718ea8c76 100644
--- a/packages/DynamicSystemInstallationService/res/values-zh-rCN/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-zh-rCN/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"重启"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"已舍弃动态系统"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"无法重启或加载动态系统"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-zh-rHK/strings.xml b/packages/DynamicSystemInstallationService/res/values-zh-rHK/strings.xml
index c830dae24e97..656c2af188c4 100644
--- a/packages/DynamicSystemInstallationService/res/values-zh-rHK/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-zh-rHK/strings.xml
@@ -5,7 +5,7 @@
<string name="notification_install_completed" msgid="6252047868415172643">"動態系統已可供使用。如要開始使用,請重新啟動裝置。"</string>
<string name="notification_install_inprogress" msgid="7383334330065065017">"安裝中"</string>
<string name="notification_install_failed" msgid="4066039210317521404">"無法安裝"</string>
- <string name="notification_image_validation_failed" msgid="2720357826403917016">"圖片驗證失敗,系統將取消安裝。"</string>
+ <string name="notification_image_validation_failed" msgid="2720357826403917016">"磁碟影像驗證失敗,系統將取消安裝。"</string>
<string name="notification_dynsystem_in_use" msgid="1053194595682188396">"系統目前正在執行動態系統。如要使用原本的 Android 版本,請重新啟動裝置。"</string>
<string name="notification_action_cancel" msgid="5929299408545961077">"取消"</string>
<string name="notification_action_discard" msgid="1817481003134947493">"捨棄"</string>
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"重新啟動"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"已捨棄動態系統"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"無法重新啟動或載入動態系統"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-zh-rTW/strings.xml b/packages/DynamicSystemInstallationService/res/values-zh-rTW/strings.xml
index e43c0f2b08bb..a6f9b56e438c 100644
--- a/packages/DynamicSystemInstallationService/res/values-zh-rTW/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-zh-rTW/strings.xml
@@ -5,7 +5,7 @@
<string name="notification_install_completed" msgid="6252047868415172643">"動態系統已可供使用。如要開始使用,請重新啟動裝置。"</string>
<string name="notification_install_inprogress" msgid="7383334330065065017">"安裝中"</string>
<string name="notification_install_failed" msgid="4066039210317521404">"無法安裝"</string>
- <string name="notification_image_validation_failed" msgid="2720357826403917016">"圖片驗證失敗,系統將取消安裝作業。"</string>
+ <string name="notification_image_validation_failed" msgid="2720357826403917016">"映像檔驗證失敗,系統將取消安裝作業。"</string>
<string name="notification_dynsystem_in_use" msgid="1053194595682188396">"系統目前正在執行動態系統。如要使用原本的 Android 版本,請重新啟動裝置。"</string>
<string name="notification_action_cancel" msgid="5929299408545961077">"取消"</string>
<string name="notification_action_discard" msgid="1817481003134947493">"捨棄"</string>
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"重新啟動"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"已捨棄動態系統"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"無法重新啟動或載入動態系統"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/DynamicSystemInstallationService/res/values-zu/strings.xml b/packages/DynamicSystemInstallationService/res/values-zu/strings.xml
index 4a48444cb9a0..0cf79ba51b45 100644
--- a/packages/DynamicSystemInstallationService/res/values-zu/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-zu/strings.xml
@@ -13,4 +13,6 @@
<string name="notification_action_reboot_to_origin" msgid="4013901243271889897">"Qala kabusha"</string>
<string name="toast_dynsystem_discarded" msgid="1733249860276017050">"Kulahlwe uhlole olunhlobonhlobo"</string>
<string name="toast_failed_to_reboot_to_dynsystem" msgid="6336737274625452067">"Ayikwazi ukuqalisa kabusha noma ukulayisha uhlole olunhlobonhlobo"</string>
+ <!-- no translation found for toast_failed_to_disable_dynsystem (3285742944977744413) -->
+ <skip />
</resources>
diff --git a/packages/SettingsLib/HelpUtils/res/values-es/strings.xml b/packages/SettingsLib/HelpUtils/res/values-es/strings.xml
index 97ff5efc6401..97e3559914a2 100644
--- a/packages/SettingsLib/HelpUtils/res/values-es/strings.xml
+++ b/packages/SettingsLib/HelpUtils/res/values-es/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="help_feedback_label" msgid="7106780063063027882">"Ayuda y sugerencias"</string>
+ <string name="help_feedback_label" msgid="7106780063063027882">"Ayuda y comentarios"</string>
</resources>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index dd1c12a0dc27..6a563f3fb0ef 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -550,9 +550,9 @@
<string name="guest_new_guest" msgid="3482026122932643557">"Lisää vieras"</string>
<string name="guest_exit_guest" msgid="5908239569510734136">"Poista vieras"</string>
<string name="guest_nickname" msgid="6332276931583337261">"Vieras"</string>
- <string name="user_image_take_photo" msgid="467512954561638530">"Ota valokuva"</string>
+ <string name="user_image_take_photo" msgid="467512954561638530">"Ota kuva"</string>
<string name="user_image_choose_photo" msgid="1363820919146782908">"Valitse kuva"</string>
- <string name="user_image_photo_selector" msgid="433658323306627093">"Valitse valokuva"</string>
+ <string name="user_image_photo_selector" msgid="433658323306627093">"Valitse kuva"</string>
<string name="cached_apps_freezer_device_default" msgid="2616594131750144342">"Laitteen oletusasetus"</string>
<string name="cached_apps_freezer_disabled" msgid="4816382260660472042">"Ei käytössä"</string>
<string name="cached_apps_freezer_enabled" msgid="8866703500183051546">"Käytössä"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 08a2b99458cd..90d49e229fc4 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -33,11 +33,11 @@
<string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\' સાથે કનેક્ટ કરી શકાતું નથી"</string>
<string name="wifi_check_password_try_again" msgid="8817789642851605628">"પાસવર્ડ તપાસો અને ફરી પ્રયાસ કરો"</string>
<string name="wifi_not_in_range" msgid="1541760821805777772">"રેન્જમાં નથી"</string>
- <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"આપમેળે કનેક્ટ કરશે નહીં"</string>
+ <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"ઑટોમૅટિક રીતે કનેક્ટ કરશે નહીં"</string>
<string name="wifi_no_internet" msgid="1774198889176926299">"કોઈ ઇન્ટરનેટ ઍક્સેસ નથી"</string>
<string name="saved_network" msgid="7143698034077223645">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા સચવાયું"</string>
<string name="connected_via_network_scorer" msgid="7665725527352893558">"%1$s દ્વારા સ્વત: કનેક્ટ થયેલ"</string>
- <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"નેટવર્ક રેટિંગ પ્રદાતા દ્વારા આપમેળે કનેક્ટ થયું"</string>
+ <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"નેટવર્ક રેટિંગ પ્રદાતા દ્વારા ઑટોમૅટિક રીતે કનેક્ટ થયું"</string>
<string name="connected_via_passpoint" msgid="7735442932429075684">"%1$s દ્વારા કનેક્ટ થયેલ"</string>
<string name="connected_via_app" msgid="3532267661404276584">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા કનેક્ટ થયેલ"</string>
<string name="available_via_passpoint" msgid="1716000261192603682">"%1$s દ્વારા ઉપલબ્ધ"</string>
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index baa266a6e5cd..48eb60097f1d 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -229,6 +229,8 @@ public class SettingsBackupTest {
Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM,
Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR,
Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_SV,
+ Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_VR,
+ Settings.Global.DEVELOPMENT_IGNORE_VENDOR_DISPLAY_SETTINGS,
Settings.Global.DEVICE_DEMO_MODE,
Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS,
Settings.Global.BATTERY_SAVER_CONSTANTS,
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index 3714db324fb4..939c5f9f7ecb 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -73,7 +73,7 @@
android:id="@+id/gradient_clock_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textSize="100dp"
+ android:textSize="80dp"
android:letterSpacing="0.02"
android:lineSpacingMultiplier=".8"
android:includeFontPadding="false"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 220a77318ce6..4042ef91585a 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Battery, twee stawe."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery, drie stawe."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Battery vol."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Geen foon nie."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Foon, een staaf."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Foon, twee stawe."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profiel kan gemonitor word"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Netwerk kan dalk gemonitor word"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Netwerk kan dalk gemonitor word"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Hierdie toestel word deur jou ouer bestuur"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Jou organisasie besit hierdie toestel en kan netwerkverkeer monitor"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> besit hierdie toestel en kan netwerkverkeer monitor"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Hierdie toestel behoort aan jou organisasie en is gekoppel aan <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Deaktiveer VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Ontkoppel VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Bekyk beleide"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Bekyk kontroles"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Hierdie toestel behoort aan <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nJou IT-admin kan instellings, korporatiewe toegang, programme, data wat met jou toestel geassosieer word, en jou toestel se ligginginligting monitor en bestuur.\n\nKontak jou IT-admin vir meer inligting."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Hierdie toestel behoort aan jou organisasie.\n\nJou IT-admin kan instellings, korporatiewe toegang, programme, data wat met jou toestel geassosieer word, en jou toestel se ligginginligting monitor en bestuur.\n\nKontak jou IT-admin vir meer inligting."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Jou organisasie het \'n sertifikaatoutoriteit op hierdie toestel geïnstalleer. Jou veilige netwerkverkeer kan gemonitor of gewysig word."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Jou administrateur het netwerkloglêers aangeskakel wat verkeer op jou toestel monitor.\n\nKontak jou administrateur vir meer inligting."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Jy het \'n program toestemming gegee om \'n VPN-verbinding op te stel.\n\nHierdie program kan jou toestel- en netwerkaktiwiteit monitor, insluitend e-posse, programme en webwerwe."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Jou werkprofiel word deur <xliff:g id="ORGANIZATION">%1$s</xliff:g> bestuur.\n\nJou administrateur kan jou netwerkaktiwiteit, insluitend e-posse, programme en webwerwe, bestuur.\n\nKontak jou administrateur vir meer inligting.\n\nJy is ook aan \'n VPN gekoppel, wat jou netwerkaktiwiteit kan monitor."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Hierdie toestel word deur jou ouer bestuur. Jou ouer kan inligting sien en bestuur soos die programme wat jy gebruik, jou ligging en jou skermtyd."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Jy is gekoppel aan <xliff:g id="APPLICATION">%1$s</xliff:g>, wat jou netwerkaktiwiteit, insluitend e-posse, programme en webwerwe, kan monitor."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Jy is gekoppel aan <xliff:g id="APPLICATION">%1$s</xliff:g>, wat jou persoonlike netwerkaktiwiteit, insluitend e-posse, programme en webwerwe, kan monitor."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Bind nuwe toestel saam"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Bounommer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Bounommer is na knipbord gekopieer."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index b2a7c16c8ad0..e8a8a0d359bc 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"ባትሪ ሁለት አሞሌዎች።"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ባትሪ ሦስት አሞሌዎች።"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ባትሪ ሙሉ ነው።"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"ምንም ስልክ የለም።"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"የስልክ አንድ አሞሌ"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"የስልክ ሁለት አሞሌ"</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"መገለጫ ክትትል ሊደረግበት ይችላል"</string>
<string name="vpn_footer" msgid="3457155078010607471">"አውታረ መረብ በክትትል እየተደረገበት ሊሆን ይችላል"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"አውታረ መረብ ክትትል የሚደረግበት ሊሆን ይችላል"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ይህ መሣሪያ በእርስዎ ወላጅ የሚተዳደር ነው።"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"የእርስዎ ድርጅት የዚህ መሣሪያ ባለቤት ነው፣ እና የአውታረ መረብ ትራፊክን ሊከታተል ይችላል"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> የዚህ መሣሪያ ባለቤት ነው፣ እና የአውታረ መረብ ትራፊክን ሊከታተል ይችላል"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ይህ መሣሪያ የድርጅትዎ ሲሆን ከ<xliff:g id="VPN_APP">%1$s</xliff:g> ጋር ተገናኝቷል"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN አሰናክል"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"የVPN ግንኙነት አቋርጥ"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"መመሪያዎችን ይመልከቱ"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"መቆጣጠሪያዎችን አሳይ"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"ይህ መሣሪያ የ<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ነው።\n\nየእርስዎ የአይቲ አስተዳዳሪ ቅንብሮችን፣ የኮርፖሬት መዳረሻን፣ መተግበሪያዎችን፣ ከመሣሪያዎ ጋር የተጎዳኘ ውሂብን እና የመሣሪያዎ አካባቢ መረጃን መከታተል እና ማቀናበር ይችላል።\n\nተጨማሪ መረጃ የአይቲ አስተዳዳሪዎን ያነጋግሩ።"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"ይህ መሣሪያ የድርጅትዎ ነው።\n\nየእርስዎ የአይቲ አስተዳዳሪ ቅንብሮችን፣ የኮርፖሬት መዳረሻን፣ መተግበሪያዎችን፣ ከመሣሪያዎ ጋር የተጎዳኘ ውሂብን እና የመሣሪያዎ አካባቢ መረጃን መከታተል እና ማቀናበር ይችላል።\n\nለተጨማሪ መረጃ የአይቲ አስተዳዳሪዎን ያነጋግሩ።"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"የእርስዎ ድርጅት የእውቅና ማረጋገጫ ሰጪ ባለሥልጣን በዚህ መሣሪያ ላይ ጭኗል። የእርስዎ ደኅንነቱ የተጠበቀ አውታረ መረብ ትራፊክ ክትትል ሊደረግበት እና ሊሻሻል ይችላል።"</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"የእርስዎ አስተዳዳሪ የአውታረ መረብ ምዝግብ ማስታወሻ መያዝን አብርተዋል፣ ይህም በመሣሪያዎ ላይ ያለውን ትራፊክ ይከታተላል።\n\nተጨማሪ መረጃ ለማግኘት አስተዳዳሪዎን ያነጋግሩ።"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"አንድ መተግበሪያ የVPN ግንኙነት እንዲያዋቅር ፍቃድ ሰጥተውታል።\n\nይህ መተግበሪያ ኢሜይሎችን፣ መተግበሪያዎችን እና ድር ጣቢያዎችንም ጨምሮ የመሣሪያዎን እና የአውታረ መረብ እንቅስቃሴዎን መከታተል ይችላል።"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"የእርስዎ የስራ መገለጫ በ<xliff:g id="ORGANIZATION">%1$s</xliff:g> ነው የሚቀናበረው።\n\nየእርስዎ አስተዳዳሪ ኢሜይሎችን፣ መተግበሪያዎችን እና ድር ጣቢያዎችን ጨምሮ የአውታረ መረብ እንቅስቃሴዎን መከታተል ይችላል።\n\nተጨማሪ መረጃ ለማግኘት አስተዳዳሪዎን ያነጋግሩ።\n\nእርስዎ እንዲሁም የአውታረ መረብ እንቅስቃሴዎን መከታተል ከሚችል ቪፒኤን ጋር ተገናኝተዋል።"</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ይህ መሣሪያ በእርስዎ ወላጅ የሚተዳደር ነው። ወላጅዎ የሚጠቀሙባቸውን መተግበሪያዎች፣ አካባቢዎን እና የማያ ገጽ ጊዜዎን የመሳሰሉ መረጃዎችን ማየት እና ማስተዳደር ይችላል።"</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"እርስዎ ኢሜይሎችን፣ መተግበሪያዎችን እና ድር ጣቢያዎችንም ጨምሮ የአውታረ መረብ እንቅስቃሴዎን ከሚከታተለው <xliff:g id="APPLICATION">%1$s</xliff:g> ጋር ተገናኝተዋል።"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"እርስዎ ኢሜይሎችን፣ መተግበሪያዎችን እና ድር ጣቢያዎችንም ጨምሮ የግል የአውታረ መረብ እንቅስቃሴዎን መከታተል ከሚችለው <xliff:g id="APPLICATION">%1$s</xliff:g> ጋር ተገናኝተዋል።"</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"አዲስ መሣሪያ ያጣምሩ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"የግንብ ቁጥር"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"የገንባ ቁጥር ወደ ቅንጥብ ሰሌዳ ተቀድቷል።"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 2cced237e948..83940bff0adc 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"إشارة البطارية تتكون من شريطين."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"إشارة البطارية تتكون من ثلاثة أشرطة."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"إشارة البطارية كاملة."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"ليست هناك إشارة بالهاتف."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"إشارة الهاتف تتكون من شريط واحد."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"إشارة الهاتف تتكون من شريطين."</string>
@@ -532,6 +534,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"ربما تتم مراقبة الملف الشخصي"</string>
<string name="vpn_footer" msgid="3457155078010607471">"قد تكون الشبكة خاضعة للمراقبة"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"قد تكون الشبكة خاضعة للمراقبة"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"يتولّى أحد الوالدين إدارة هذا الجهاز."</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"تملك مؤسستك هذا الجهاز ويمكنها تتبّع حركة بيانات الشبكة."</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"تملك مؤسسة <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> هذا الجهاز ويمكنها تتبّع حركة بيانات الشبكة"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"هذا الجهاز يخص مؤسستك وتم ربطه بشبكة <xliff:g id="VPN_APP">%1$s</xliff:g>."</string>
@@ -556,6 +559,7 @@
<string name="disable_vpn" msgid="482685974985502922">"إيقاف الشبكة الافتراضية الخاصة"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"‏قطع الاتصال بشبكة VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"عرض السياسات"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"عرض عناصر التحكم"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"هذا الجهاز يخص <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nيمكن لمشرف تكنولوجيا المعلومات تتبّع وإدارة الإعدادات والتطبيقات والبيانات المرتبطة بجهازك ومعلومات الموقع الجغرافي للجهاز وعمليات الدخول إلى نظام المؤسسة.\n\nللحصول على المزيد من المعلومات، يمكنك التواصل مع مشرف تكنولوجيا المعلومات."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"هذا الجهاز يخص مؤسستك.\n\nيمكن لمشرف تكنولوجيا المعلومات في مؤسستك تتبّع وإدارة الإعدادات والتطبيقات والبيانات المرتبطة بجهازك ومعلومات الموقع الجغرافي للجهاز وعمليات الدخول إلى نظام المؤسسة.\n\nللحصول على المزيد من المعلومات، يمكنك التواصل مع مشرف تكنولوجيا المعلومات."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ثبّتت مؤسستك مرجعًا مصدّقًا على هذا الجهاز. قد تتم مراقبة حركة بيانات شبكتك الآمنة أو تعديلها."</string>
@@ -579,6 +583,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"شغَّل المشرف ميزة تسجيل بيانات الشبكة، والتي يتم من خلالها مراقبة حركة البيانات على جهازك.\n\nللحصول على المزيد من المعلومات، اتصل بالمشرف."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"‏لقد منحت تطبيقًا الإذن لإعداد اتصال شبكة افتراضية خاصة (VPN).\n\nيمكن لهذا التطبيق مراقبة أنشطتك على الجهاز والشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"تتم إدارة ملفك الشخصي للعمل بواسطة <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nويمكن للمشرف مراقبة نشاط الشبكة، بما في ذلك رسائل البريد الإلكتروني والتطبيقات والمواقع الإلكترونية.\n\nللحصول على المزيد من المعلومات، اتصل بالمشرف.\n\nوتجدر الإشارة إلى أنك متصل أيضًا بشبكة افتراضية خاصة يمكن أن تراقب نشاط الشبكة."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"يتولّى أحد الوالدين إدارة هذا الجهاز. يمكن للوالدين عرض وإدارة معلوماتك، مثلاً التطبيقات التي تستخدمها وموقعك الجغرافي ووقت النظر إلى الشاشة."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"شبكة افتراضية خاصة"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"تم ربطك بـ <xliff:g id="APPLICATION">%1$s</xliff:g>، الذي يمكنه مراقبة أنشطتك على الشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"أنت متصل بـ <xliff:g id="APPLICATION">%1$s</xliff:g>، الذي يمكنه مراقبة أنشطتك الشخصية على الشبكة، بما في ذلك الرسائل الإلكترونية والتطبيقات ومواقع الويب."</string>
@@ -1113,4 +1118,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"إقران جهاز جديد"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"رقم الإصدار"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"تم نسخ رقم الإصدار إلى الحافظة."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 4c43e4ebed8f..5444b53bd1df 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"বেটাৰিৰ দুডাল দণ্ড।"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"বেটাৰিৰ তিনিডাল দণ্ড।"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"বেটাৰি পূৰাকৈ চ্চাৰ্জ হৈছে।"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"ফ\'নত ছিগনেল নাই৷"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ফ\'ন ছিগনেলৰ এডাল দণ্ড।"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ফ\'ন ছিগনেলৰ দুডাল দণ্ড।"</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"প্ৰ\'ফাইল নিৰীক্ষণ কৰা হ\'ব পাৰে"</string>
<string name="vpn_footer" msgid="3457155078010607471">"নেটৱৰ্ক নিৰীক্ষণ কৰা হ\'ব পাৰে"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"নেটৱৰ্ক নিৰীক্ষণ কৰা হ\'ব পাৰে"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"এই ডিভাইচটো আপোনাৰ অভিভাৱকে পৰিচালনা কৰে"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"এই ডিভাইচটোৰ গৰাকী আপোনাৰ প্ৰতিষ্ঠান আৰু ই নেটৱৰ্কৰ ট্ৰেফিক নিৰীক্ষণ কৰিব পাৰে"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"এই ডিভাইচটোৰ গৰাকী <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> আৰু এইটোৱে নেটৱৰ্কৰ ট্ৰেফিক নিৰীক্ষণ কৰিব পাৰে"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"এই ডিভাইচটো আপোনাৰ প্ৰতিষ্ঠানৰ আৰু এইটো <xliff:g id="VPN_APP">%1$s</xliff:g>ৰ সৈতে সংযুক্ত হৈ আছে"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"ভিপিএন অক্ষম কৰক"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"ভিপিএন সংযোগ বিচ্ছিন্ন কৰক"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"নীতিসমূহ চাওক"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"নিয়ন্ত্ৰণসমূহ চাওক"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"এই ডিভাইচটো <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>ৰ।\n\nআপোনাৰ আইটি প্ৰশাসকে আপোনাৰ ডিভাইচটোৰ লগত জড়িত ছেটিংসমূহ, কৰ্পৰে’টৰ এক্সেছ, এপ্‌সমূহ, ডেটা আৰু আপোনাৰ ডিভাইচটোৰ অৱস্থান সম্পৰ্কীয় তথ্য নিৰীক্ষণ কৰাৰ লগতে সেয়া পৰিচালনা কৰিব পাৰে।\n\nঅধিক তথ্যৰ বাবে আপোনাৰ আইটি প্ৰশাসকৰ সৈতে যোগাযোগ কৰক।"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"এই ডিভাইচটো আপোনাৰ প্ৰতিষ্ঠানৰ।\n\nআপোনাৰ আইটি প্ৰশাসকে আপোনাৰ ডিভাইচটোৰ লগত জড়িত ছেটিংসমূহ, কৰ্পৰে’টৰ এক্সেছ, এপ্‌সমূহ, ডেটা আৰু আপোনাৰ ডিভাইচটোৰ অৱস্থান সম্পৰ্কীয় তথ্য নিৰীক্ষণ কৰাৰ লগতে সেয়া পৰিচালনা কৰিব পাৰে।\n\nঅধিক তথ্যৰ বাবে আপোনাৰ আইটি প্ৰশাসকৰ সৈতে যোগাযোগ কৰক।"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"আপোনাৰ প্ৰতিষ্ঠানে এই ডিভাইচটোত এটা প্ৰমাণপত্ৰ সম্পৰ্কীয় কৰ্তৃপক্ষ ইনষ্টল কৰিছে। আপোনাৰ সুৰক্ষিত নেটৱৰ্ক ট্ৰেফিক পৰ্যবেক্ষণ বা সংশোধন কৰা হ\'ব পাৰে।"</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"আপোনাৰ প্ৰশাসকে নেটৱৰ্ক লগিং অন কৰিছে, যিয়ে আপোনাৰ ডিভাইচটোত নেটৱৰ্ক ট্ৰেফিক পৰ্যবেক্ষণ কৰে।\n\nএই সম্পৰ্কে অধিক জানিবলৈ আপোনাৰ প্ৰশাসকৰ সৈতে যোগাযোগ কৰক।"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"আপুনি এটা এপক ভিপিএন সংযোগ ছেট আপ কৰিবলৈ অনুমতি দিছে। \n\n এই এপটোৱে ইমেইল, এপ্ আৰু ৱেবছাইটকে ধৰি আপোনাৰ নেটৱর্কৰ কাৰ্যকলাপ পৰ্যবেক্ষণ কৰিব পাৰে।"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g>য়ে আপোনাৰ কৰ্মস্থানৰ প্ৰ\'ফাইল পৰিচালনা কৰে।\n\nআপোনাৰ প্ৰশাসকে ইমেইল, এপসমূহ আৰু আপুনি চোৱা ৱেবছাইটকে ধৰি আপোনাৰ নেটৱৰ্কৰ সকলো কাৰ্যকলাপ পৰ্যবেক্ষণ কৰিব পাৰে। \n\nঅধিক তথ্যৰ বাবে আপোনাৰ প্ৰশাসকৰ সৈতে যোগাযোগ কৰক।\n\nইয়াৰ উপৰি, আপুনি এটা ভিপিএনৰ সৈতে সংযুক্ত হৈ আছে, যিয়ে আপোনাৰ নেটৱৰ্কৰ কাৰ্যকলাপ পৰ্যবেক্ষণ কৰিব পাৰে।"</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"এই ডিভাইচটো আপোনাৰ অভিভাৱকে পৰিচালনা কৰে। আপোনাৰ অভিভাৱকে আপুনি ব্যৱহাৰ কৰা এপ্‌, আপোনাৰ অৱস্থান আৰু আপুনি ডিভাইচত অতিবাহিত কৰা সময়ৰ দৰে তথ্য চাব আৰু পৰিচালনা কৰিব পাৰে।"</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"ভিপিএন"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"আপুনি <xliff:g id="APPLICATION">%1$s</xliff:g>ৰে সংযুক্ত হৈ আছে যিয়ে আপোনাৰ ইমেইল, এপ্ আৰু ৱেবছাইটকে ধৰি নেটৱর্কৰ কাৰ্যকলাপ পৰ্যবেক্ষণ কৰিব পাৰে।"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"আপুনি <xliff:g id="APPLICATION">%1$s</xliff:g>ৰে সংযুক্ত হৈ আছে, যি ইমেইল, এপ্ আৰু ৱেবছাইটসমূহকে ধৰি আপোনাৰ ব্যক্তিগত নেটৱর্কৰ কাৰ্যকলাপ নিৰীক্ষণ কৰিব পাৰে।"</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"নতুন ডিভাইচ পেয়াৰ কৰক"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"বিল্ডৰ নম্বৰ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ক্লিপব’ৰ্ডলৈ বিল্ডৰ নম্বৰ প্ৰতিলিপি কৰা হ’ল।"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 4cefd8426ed4..f97b33459b40 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Batareya iki xətdir."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batareya üç xətdir."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batareya doludur"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Telefon yoxdur."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Şəbəkə bir xətdir."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Şəbəkə iki xətdir."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil izlənə bilər"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Şəbəkə nəzərdən keçirilə bilər"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Şəbəkə nəzərdən keçirilə bilər"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Bu cihaz valideyniniz tərəfindən idarə olunur"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Təşkilatınız bu cihazın sahibidir və şəbəkə trafikinə nəzarət edə bilər"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> bu cihazın sahibidir və şəbəkə trafikinə nəzarət edə bilər"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Bu cihaz təşkilatınıza məxsusdur və <xliff:g id="VPN_APP">%1$s</xliff:g> şəbəkəsinə qoşulub"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN-i deaktiv edin"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN-i bağlantıdan ayırın"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Siyasətlərə Baxın"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Nizamlayıcılara baxın"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> təşkilatına məxsusdur.\n\nIT admininiz cihaz və cihaz məkan məlumatı ilə əlaqəli ayarlara, korporativ girişə, tətbiqə və dataya nəzarət edə və idarə edə bilər.\n\nƏtraflı məlumat üçün IT admini ilə əlaqə saxlayın."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Bu cihaz təşkilatınıza məxsusdur.\n\nIT admininiz cihaz və cihaz məkan məlumatı ilə əlaqəli ayarlara, korporativ girişə, tətbiqə və dataya nəzarət edə və idarə edə bilər.\n\nƏtraflı məlumat üçün IT admini ilə əlaqə saxlayın."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Təşkilat bu cihazda sertifikat səlahiyyəti quraşdırdı. Təhlükəsiz şəbəkə ötürülməsinə nəzarət edilə və ya dəyişdirilə bilər."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Admin, cihazdakı trafikə nəzarət edən şəbəkə loqlarını aktiv etdi.\n\nƏtraflı məlumat üçün administrator ilə əlaqə saxlayın."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"VPN bağlantısı quraşdırmağa icazə vermisiniz.\n\nBu tətbiq cihazınızı və şəbəkə fəaliyyətinizi, həmçinin, e-məktubları, tətbiq və veb saytları izləyə bilər."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"İş profiliniz <xliff:g id="ORGANIZATION">%1$s</xliff:g> tərəfindən idarə olunur.\n\nAdmin e-poçt, tətbiq və veb saytlar daxil olmaqla şəbəkə fəaliyətinizə nəzarət etməyə qadirdir.\n\nƏtraflı məlumat üçün administrator ilə əlaqə saxlayın.\n\nEyni zamanda, şəbəkə fəaliyyətinizə nəzarət edən VPN\'ə qoşulusunuz."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Bu cihaz valideyniniz tərəfindən idarə olunur. Valideyniniz istifadə etdiyiniz tətbiqlər, məkanınız və ekran vaxtınız kimi məlumatları görə və idarə edə bilər."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN (Virtual Şəxsi Şəbəkələr)"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"E-poçt, tətbiq və veb saytlar da daxil olmaqla şəbəkə fəaliyyətinə nəzarət edən <xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə qoşulusunuz."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə qoşulmusunuz və o, e-məktublar, tətbiq və veb saytlar daxil olmaqla şəxsi şəbəkə fəaliyyətinizə nəzarət edə bilər."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yeni cihazı qoşalaşdırın"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versiya nömrəsi"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versiya nömrəsi mübadilə buferinə kopyalandı."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 68ef1a31eb4e..48e5b72961e3 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Baterija od dve crte."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterija od tri crte."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Baterija je puna."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Nema telefona."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Signal telefona ima jednu crtu."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Signal telefona od dve crte."</string>
@@ -523,6 +525,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil se možda nadgleda"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Mreža se možda nadgleda"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Mreža se možda nadgleda"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Ovim uređajem upravlja roditelj"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organizacija je vlasnik uređaja i može da nadgleda mrežni saobraćaj"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> je vlasnik ovog uređaja i može da nadgleda mrežni saobraćaj"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Ovaj uređaj pripada organizaciji i povezan je sa aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -547,6 +550,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Onemogući VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Prekini vezu sa VPN-om"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Prikaži smernice"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Prikaži kontrole"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nIT administrator može da nadgleda podešavanja, korporativni pristup, aplikacije, podatke povezane sa uređajem i informacije o lokaciji uređaja, kao i da upravlja njima.\n\nViše informacija potražite od IT administratora."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Ovaj uređaj pripada organizaciji.\n\nIT administrator može da nadgleda podešavanja, korporativni pristup, aplikacije, podatke povezane sa uređajem i informacije o lokaciji uređaja, kao i da upravlja njima.\n\nViše informacija potražite od IT administratora."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organizacija je na ovom uređaju instalirala autoritet za izdavanje sertifikata. Bezbedni mrežni saobraćaj može da se prati ili menja."</string>
@@ -570,6 +574,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Administrator je uključio evidentiranje mreže, koje prati saobraćaj na uređaju.\n\nKontaktirajte administratora za više informacija."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Dali ste dozvolu aplikaciji da podešava VPN vezu.\n\nTa aplikacija može da nadgleda aktivnosti na uređaju i mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> upravlja poslovnim profilom.\n\nAdministrator može da prati aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove.\n\nKontaktirajte administratora za više informacija.\n\nPovezani ste i sa VPN-om, koji može da prati aktivnosti na mreži."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Ovim uređajem upravlja roditelj. Roditelj može da vidi informacije, kao što su aplikacije koje koristiš, tvoju lokaciju i vreme ispred ekrana, i da upravlja njima."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Povezani ste sa aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može da nadgleda aktivnosti na mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Povezani ste sa aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može da nadgleda aktivnosti na ličnoj mreži, uključujući imejlove, aplikacije i veb-sajtove."</string>
@@ -1095,4 +1100,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Upari novi uređaj"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Broj verzije je kopiran u privremenu memoriju."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 6396cbeb1299..ed57fb392155 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"2 планкі акумулятара."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Тры планкі акумулятара."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Акумулятар поўны."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Няма тэлефона."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Адна планка на тэлефоне."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"2 планкі тэлефона."</string>
@@ -526,6 +528,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"За профілем могуць назіраць"</string>
<string name="vpn_footer" msgid="3457155078010607471">"За сеткай могуць назіраць"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"За сеткай могуць назіраць"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Гэта прылада знаходзіцца пад кантролем вашых бацькоў"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Ваша арганізацыя валодае гэтай прыладай і можа кантраляваць сеткавы трафік"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> валодае гэтай прыладай і можа кантраляваць сеткавы трафік"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Гэта прылада належыць вашай арганізацыі і падключана да праграмы \"<xliff:g id="VPN_APP">%1$s</xliff:g>\""</string>
@@ -550,6 +553,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Адключыць VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Адлучыць VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Праглядзець палітыку"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Праглядзець даныя пра кантроль"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Гэта прылада належыць арганізацыі \"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>\".\n\nВаш ІТ-адміністратар можа адсочваць налады, карпаратыўны доступ, праграмы, даныя, звязаныя з вашай прыладай, і звесткі пра яе месцазнаходжанне, а таксама кіраваць імі.\n\nПа дадатковую інфармацыю звярніцеся да ІТ-адміністратара."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Гэта прылада належыць вашай арганізацыі.\n\nВаш ІТ-адміністратар можа адсочваць налады, карпаратыўны доступ, праграмы, даныя, звязаныя з вашай прыладай, і звесткі пра яе месцазнаходжанне, а таксама кіраваць імі.\n\nПа дадатковую інфармацыю звярніцеся да ІТ-адміністратара."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Ваша арганізацыя ўсталявала на гэтай прыладзе цэнтр сертыфікацыі. Ваш абаронены сеткавы трафік могуць праглядваць ці змяняць."</string>
@@ -573,6 +577,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Ваш адміністратар уключыў вядзенне журнала сеткі, з дапамогай якога адсочваецца трафік на вашай прыладзе.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Вы далі праграме дазвол на наладжванне злучэння VPN.\n\nГэта праграма можа сачыць за актыўнасцю вашай прылады і вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Ваш працоўны профіль знаходзіцца пад кіраваннем <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nВаш адміністратар можа сачыць за вашай сеткавай дзейнасцю, уключаючы электронную пошту, праграмы і вэб-сайты.\n\nДля атрымання дадатковай інфармацыі звярніцеся да адміністратара.\n\nВы таксама падключаны да сеткі VPN, якая можа сачыць за вашай сеткавай дзейнасцю."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Гэта прылада знаходзіцца пад кантролем вашых бацькоў. Бацькі могуць праглядаць і кантраляваць вашу інфармацыю, напрыклад пра праграмы, якія вы выкарыстоўваеце, даныя пра ваша месцазнаходжанне і час карыстання прыладай."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Вы падключаны да праграмы <xliff:g id="APPLICATION">%1$s</xliff:g>, якая можа сачыць за вашай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Вы падлучаны да праграмы <xliff:g id="APPLICATION">%1$s</xliff:g>, якая сачыць за вашай асабістай сеткавай актыўнасцю, уключаючы электронную пошту, праграмы і вэб-сайты."</string>
@@ -1101,4 +1106,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Спалучыць з новай прыладай"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Нумар зборкі"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Нумар зборкі скапіраваны ў буфер абмену."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 26a313ad0a11..c968e6d25e3e 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Батерията е с две чертички."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Батерията е с три чертички."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Батерията е пълна."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Няма телефон."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Телефонът е с една чертичка."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Телефонът е с две чертички."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Възможно е потребителският профил да се наблюдава"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Мрежата може да се наблюдава"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Мрежата може да се наблюдава"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Това устройство се управлява от родителя ви"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Организацията ви притежава това устройство и може да наблюдава трафика в мрежата"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> притежава това устройство и може да наблюдава трафика в мрежата"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Това устройство принадлежи на организацията ви и е свързано с(ъс) <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Деактивиране на VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Прекратяване на връзката с VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Преглед на правилата"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Преглед на контролите"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Това устройство принадлежи на <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nСистемният ви администратор може да наблюдава и управлява настройките, корпоративния достъп, приложенията, свързаните с устройството данни и информацията за местоположението му.\n\nЗа повече информация се обърнете към него."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Това устройство принадлежи на организацията ви.\n\nСистемният ви администратор може да наблюдава и управлява настройките, корпоративния достъп, приложенията, свързаните с устройството данни и информацията за местоположението му.\n\nЗа повече информация се обърнете към него."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Организацията ви е инсталирала сертифициращ орган на това устройство. Трафикът в защитената ви мрежа може да бъде наблюдаван или променян."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Администраторът ви е включил функцията за регистриране на мрежовата активност, която следи трафика на устройството ви.\n\nЗа повече информация се свържете с администратора си."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Разрешихте на приложение да настрои връзка с виртуална частна мрежа (VPN).\n\nТова приложение може да наблюдава активността ви на устройството и в мрежата, включително имейли, приложения и уебсайтове."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Служебният ви потребителски профил се управлява от <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nАдминистраторът ви може да наблюдава активността ви в мрежата, включително имейли, приложения и уебсайтове.\n\nЗа повече информация се свържете с администратора си.\n\nСъщо така е установена връзка с виртуална частна мрежа (VPN) и активността ви в нея може да се наблюдава."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Това устройство се управлява от родителя ви. Той може да вижда и управлява информация, като например приложенията, които използвате, местоположението ви и времето на ползване."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Установена е връзка с приложението <xliff:g id="APPLICATION">%1$s</xliff:g>, което може да наблюдава активността ви в мрежата, включително имейли, приложения и уебсайтове."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Установена е връзка с приложението <xliff:g id="APPLICATION">%1$s</xliff:g>, което може да наблюдава личната ви активност в мрежата, включително имейли, приложения и уебсайтове."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Сдвояване на ново устройство"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер на компилацията"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Номерът на компилацията е копиран в буферната памет."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index c4c6a0c3e2d9..c225fd304c94 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"দুই দন্ড ব্যাটারি রয়েছে৷"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"তিন দন্ড ব্যাটারি রয়েছে৷"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ব্যাটারি পূর্ণ রয়েছে৷"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"কোনো ফোনের সংকেত নেই৷"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"এক দন্ড ফোনের সংকেত রয়েছে৷"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"দুই দন্ড ফোনের সংকেত রয়েছে৷"</string>
@@ -520,6 +522,8 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"প্রোফাইল পর্যবেক্ষণ করা হতে পারে"</string>
<string name="vpn_footer" msgid="3457155078010607471">"নেটওয়ার্ক নিরীক্ষণ করা হতে পারে"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"নেটওয়ার্ক নিরীক্ষণ করা হতে পারে"</string>
+ <!-- no translation found for quick_settings_disclosure_parental_controls (2114102871438223600) -->
+ <skip />
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"এই ডিভাইসটি আপনার প্রতিষ্ঠানের এবং এরা ডিভাইসের নেটওয়ার্ক ট্রাফিক মনিটর করতে পারে"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> এই ডিভাইসের মালিক এবং এটির নেটওয়ার্ক ট্রাফিক মনিটর করতে পারে"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"এই ডিভাইসটি আপনার প্রতিষ্ঠানের এবং <xliff:g id="VPN_APP">%1$s</xliff:g>-এ কানেক্ট করা আছে"</string>
@@ -544,6 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN অক্ষম করুন"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN এর সংযোগ বিচ্ছিন্ন করুন"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"নীতিগুলি দেখুন"</string>
+ <!-- no translation found for monitoring_button_view_controls (8316440345340701117) -->
+ <skip />
<string name="monitoring_description_named_management" msgid="505833016545056036">"এই ডিভাইসটি <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>-এর।\n\nআপনার আইটি অ্যাডমিন এই ডিভাইসের সেটিংস, কর্পোরেট অ্যাক্সেস, অ্যাপ, ডিভাইসের সাথে সম্পর্কিত ডেটা এবং ডিভাইসের লোকেশন সম্পর্কিত ডেটা মনিটর ও ম্যানেজ করতে পারে।\n\nআরও তথ্যের জন্য আপনার আইটি অ্যাডমিনের সাথে যোগাযোগ করুন।"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"এই ডিভাইসটি আপনার প্রতিষ্ঠানের।\n\nআপনার আইটি অ্যাডমিন এই ডিভাইসের সেটিংস, কর্পোরেট অ্যাক্সেস, অ্যাপ, ডিভাইসের সাথে সম্পর্কিত ডেটা এবং ডিভাইসের লোকেশন সম্পর্কিত ডেটা মনিটর ও ম্যানেজ করতে পারে।\n\nআরও তথ্যের জন্য আপনার আইটি অ্যাডমিনের সাথে যোগাযোগ করুন।"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"আপনার প্রতিষ্ঠান আপনার অফিস প্রোফাইলে একটি সার্টিফিকেট কর্তৃপক্ষ ইনস্টল করেছে।আপনার সুরক্ষিত নেটওয়ার্ক ট্রাফিক নিরীক্ষণ বা পরিবর্তন করা হতে পারে।"</string>
@@ -567,6 +573,8 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"আপনার প্রশাসক নেটওয়ার্ক লগিং চালু করেছেন, যা আপনার ডিভাইসের ট্রাফিক নিরীক্ষণ করে।\n\nআরও তথ্যের জন্য আপনার প্রশাসকের সাথে যোগাযোগ করুন।"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"আপনি VPN সংযোগ সেট-আপ করার জন্য একটি অ্যাপ্লিকেশানকে অনুমতি দিন৷\n\nএই অ্যাপ্লিকেশানটি ইমেল, অ্যাপ্লিকেশান ও ওয়েবসাইটগুলি সহ আপনার ডিভাইস এবং নেটওয়ার্কের অ্যাক্টিভিটি নিরীক্ষণ করতে পারে।"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"আপনার কর্মস্থলের প্রোফাইলটি <xliff:g id="ORGANIZATION">%1$s</xliff:g> দ্বারা পরিচালিত হয়।\n\nআপনার প্রশাসক আপনার ইমেল, অ্যাপ্স ও ওয়েবসাইট সহ কর্মস্থলের নেটওয়ার্ক অ্যাক্টিভিটি নিরীক্ষণ করতে পারেন।\n\nআরও তথ্যের জন্য আপনার প্রশাসকের সঙ্গে যোগাযোগ করুন।\n\nএছাড়া আপনি একটি VPN এর সাথেও সংযুক্ত যা আপনার নেটওয়ার্ক অ্যাক্টিভিটি নিরীক্ষণ করতে পারে।"</string>
+ <!-- no translation found for monitoring_description_parental_controls (8184693528917051626) -->
+ <skip />
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"আপনি <xliff:g id="APPLICATION">%1$s</xliff:g> এর সাথে সংযুক্ত রয়েছেন, যেটি ইমেল, অ্যাপ, এবং ওয়েবসাইট সহ আপনার নেটওয়ার্ক কার্যকলাপে নজর রাখতে পারে৷"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"আপনি <xliff:g id="APPLICATION">%1$s</xliff:g> -এ সংযুক্ত হয়েছেন, যা ইমেল, অ্যাপ্লিকেশান এবং ওয়েবসাইটগুলি সমেত আপনার ব্যক্তিগত নেটওয়ার্ক অ্যাক্টিভিটি নিরীক্ষণ করতে পারে৷"</string>
@@ -1089,4 +1097,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"নতুন ডিভাইস পেয়ার করুন"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"বিল্ড নম্বর"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"বিল্ড নম্বর ক্লিপবোর্ডে কপি করা হয়েছে।"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 75a2d1cc4ea8..344bb63daa7c 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Baterija na dvije crtice."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterija na tri crtice."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Baterija je puna."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Nema telefonskog signala."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefonski signal na jednoj crtici."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefonski signal na dvije crtice."</string>
@@ -523,6 +525,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil može biti nadziran"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Mreža može biti nadzirana"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Mreža može biti nadzirana"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Ovim uređajem upravlja tvoj roditelj"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Vaša organizacija je vlasnik ovog uređaja i može nadzirati mrežni saobraćaj"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> upravlja ovim uređajem i može nadzirati mrežni saobraćaj"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Ovaj uređaj pripada vašoj organizaciji i povezan je s aplikacijom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -547,6 +550,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Isključi VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Prekini VPN vezu"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Prikaži pravila"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Prikaži kontrole"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nVaš IT administrator može nadzirati postavke, korporativni pristup, aplikacije, podatke povezane s vašim uređajem i informacije o lokaciji uređaja te njima upravljati.\n\nZa više informacija kontaktirajte IT administratora."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Ovaj uređaj pripada vašoj organizaciji.\n\nVaš IT administrator može nadzirati postavke, korporativni pristup, aplikacije, podatke povezane s vašim uređajem i informacije o lokaciji uređaja te njima upravljati.\n\nZa više informacija kontaktirajte IT administratora."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Vaša organizacija je instalirala CA certifikat na ovom uređaju. Vaš saobraćaj preko sigurne mreže može se pratiti."</string>
@@ -570,6 +574,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Vaš administrator je uključio zapisivanje na mreži, čime se prati saobraćaj na vašem uređaju.\n\nZa više informacija, obratite se administratoru."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Jednoj aplikaciji ste dali odobrenje da uspostavi VPN vezu.\n\nTa aplikacija može pratiti vašu aktivnost na uređaju i mreži, uključujući e-poštu, aplikacije i web-lokacije."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Vašim radnim profilom upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nVaš administrator može pratiti vašu aktivnost na radnoj mreži, uključujući e-poruke, aplikacije i web lokacije.\n\nZa više informacija, obratite se administratoru.\n\nPovezani ste i na VPN, koji može pratiti vašu aktivnost na mreži."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Ovim uređajem upravlja tvoj roditelj. Roditelj može vidjeti i upravljati informacijama kao što su aplikacije koje koristiš, lokacija i vrijeme korištenja uređaja."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Povezani ste s aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može pratiti vašu aktivnost na mreži, uključujući e-poruke, aplikacije i web lokacije."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Povezani ste sa aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g>, koja može pratiti vašu aktivnost na privatnoj mreži, uključujući e-mailove, aplikacije i web-lokacije."</string>
@@ -1095,4 +1100,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uparite novi uređaj"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj verzije"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Broj verzije je kopiran u međumemoriju."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 2b6dfd577616..0ed3ac1d306e 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Bateria: dues barres."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Bateria: tres barres."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria carregada."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"No hi ha senyal de telèfon."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Senyal de telèfon: una barra"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Senyal de telèfon: dues barres."</string>
@@ -446,7 +448,7 @@
<string name="zen_priority_introduction" msgid="3159291973383796646">"No t\'interromprà cap so ni cap vibració, tret dels de les alarmes, recordatoris, esdeveniments i trucades de les persones que especifiquis. Continuaràs sentint tot allò que decideixis reproduir, com ara música, vídeos i jocs."</string>
<string name="zen_alarms_introduction" msgid="3987266042682300470">"No t\'interromprà cap so ni cap vibració, tret dels de les alarmes. Continuaràs sentint tot allò que decideixis reproduir, com ara música, vídeos i jocs."</string>
<string name="zen_priority_customize_button" msgid="4119213187257195047">"Personalitza"</string>
- <string name="zen_silence_introduction_voice" msgid="853573681302712348">"Es bloquejaran TOTS els sons i totes les vibracions, inclosos els de vídeos, jocs, alarmes i música. Encara podràs fer trucades."</string>
+ <string name="zen_silence_introduction_voice" msgid="853573681302712348">"Es bloquejaran TOTS els sons i totes les vibracions, inclosos els de vídeos, jocs, alarmes i música. Encara podràs fer trucades telefòniques."</string>
<string name="zen_silence_introduction" msgid="6117517737057344014">"Es bloquejaran TOTS els sons i totes les vibracions, inclosos els de vídeos, jocs, alarmes i música."</string>
<string name="keyguard_more_overflow_text" msgid="5819512373606638727">"+<xliff:g id="NUMBER_OF_NOTIFICATIONS">%d</xliff:g>"</string>
<string name="speed_bump_explanation" msgid="7248696377626341060">"Notificacions menys urgents a continuació"</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"El perfil es pot supervisar"</string>
<string name="vpn_footer" msgid="3457155078010607471">"És possible que la xarxa estigui supervisada."</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"És possible que la xarxa estigui supervisada"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"El teu pare o la teva mare gestionen aquest dispositiu"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"La teva organització és propietària del dispositiu i és possible que supervisi el trànsit de xarxa"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> és propietària d\'aquest dispositiu i és possible que supervisi el trànsit de xarxa"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Aquest dispositiu pertany a la teva organització i està connectat a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Desactiva la VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Desconnecta la VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Consulta les polítiques"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Mostra els controls"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"El dispositiu pertany a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nL\'administrador de TI pot supervisar i gestionar la configuració, l\'accés corporatiu, les aplicacions, les dades associades al dispositiu i la informació d\'ubicació.\n\nPer obtenir més informació, contacta amb l\'administrador de TI."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"El dispositiu pertany a la teva organització.\n\nL\'administrador de TI pot supervisar i gestionar la configuració, l\'accés corporatiu, les aplicacions, les dades associades al dispositiu i la informació d\'ubicació.\n\nPer obtenir més informació, contacta amb l\'administrador de TI."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"La teva organització ha instal·lat una autoritat de certificació en aquest dispositiu. És possible que el trànsit a la xarxa segura se supervisi o es modifiqui."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"L\'administrador ha activat el registre de xarxa, que supervisa el trànsit del teu dispositiu.\n\nPer obtenir més informació, contacta amb l\'administrador."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Has donat permís a una aplicació per configurar una connexió VPN.\n\nAquesta aplicació pot supervisar el dispositiu i l\'activitat a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> gestiona el teu perfil de treball.\n\nL\'administrador pot supervisar la teva activitat a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web.\n\nPer obtenir més informació, contacta amb l\'administrador.\n\nA més, estàs connectat a una VPN, que també pot supervisar la teva activitat a la xarxa."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"El teu pare o la teva mare gestionen aquest dispositiu, i poden veure i gestionar informació com ara les aplicacions que utilitzes, la teva ubicació i el teu temps de connexió."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Estàs connectat a <xliff:g id="APPLICATION">%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_app_personal" msgid="1970094872688265987">"Estàs connectat a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pot supervisar la teva activitat personal a la xarxa, com ara els correus electrònics, les aplicacions i els llocs web."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincula un dispositiu nou"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilació"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"El número de compilació s\'ha copiat al porta-retalls."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index f00c279b6b58..156b65d41dea 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Dvě čárky baterie."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Tři čárky baterie."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Baterie je nabitá."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Žádná telefonní síť."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Jedna čárka signálu telefonní sítě."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dvě čárky signálu telefonní sítě."</string>
@@ -526,6 +528,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil může být monitorován"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Síť může být sledována"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Síť může být monitorována"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Toto zařízení spravuje rodič"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Toto zařízení vlastní vaše organizace, která může sledovat síťový provoz"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Toto zařízení spravuje organizace <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, která může sledovat síťový provoz"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Toto zařízení patří vaší organizaci a je připojené k síti <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -550,6 +553,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Deaktivovat VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Odpojit VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Zobrazit zásady"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Zobrazit ovládací prvky"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Toto zařízení patří organizaci <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nVáš administrátor IT může sledovat a spravovat nastavení, firemní přístup, aplikace, data přidružená k tomuto zařízení a jeho polohu.\n\nDalší informace vám poskytne váš administrátor IT."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Toto zařízení patří vaší organizaci\n\nVáš administrátor IT může sledovat a spravovat nastavení, firemní přístup, aplikace, data přidružená k tomuto zařízení a jeho polohu.\n\nDalší informace vám poskytne váš administrátor IT."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organizace do tohoto zařízení nainstalovala certifikační autoritu. Zabezpečený síťový provoz může být sledován nebo upravován."</string>
@@ -573,6 +577,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Administrátor zapnul protokolování sítě, které monitoruje síťový provoz v zařízení.\n\nDalší informace vám poskytne administrátor."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Udělili jste aplikaci oprávnění k nastavení připojení VPN.\n\nTato aplikace může sledovat vaši aktivitu v zařízení a v síti, včetně e-mailů, aplikací a webů."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Váš pracovní profil spravuje organizace <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministrátor může monitorovat vaši síťovou aktivitu, včetně e-mailů, aplikací a webů.\n\nDalší informace vám poskytne administrátor.\n\nJste také připojeni k síti VPN, která může sledovat vaši aktivitu v síti."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Toto zařízení spravuje rodič. Rodič může zobrazit údaje, jako jsou používané aplikace, tvá poloha a čas strávený na zařízení."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Jste připojeni k aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g>, která může sledovat vaši aktivitu v síti, včetně e-mailů, aplikací a webů."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Jste připojeni k aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g>, která může sledovat vaši osobní aktivitu v síti, včetně e-mailů, aplikací a webů."</string>
@@ -1101,4 +1106,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Spárovat nové zařízení"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo sestavení"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Číslo sestavení bylo zkopírováno do schránky."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 9d365c33fa39..d4761d504dfe 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Batteri to bjælker."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batteri tre bjælker."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batteri fuldt."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Ingen telefon."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon en bjælke."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon to bjælker."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profilen kan overvåges"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Netværket kan være overvåget"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Netværket kan være overvåget"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Denne enhed administreres af din forælder"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Din organisation ejer denne enhed og overvåger muligvis netværkstrafikken"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ejer denne enhed og overvåger muligvis netværkstrafikken"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Denne enhed tilhører din organisation og har forbindelse til <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Deaktiver VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Afbryd VPN-forbindelse"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Se politikker"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Se styringselementer"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Denne enhed tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nDin it-administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er tilknyttet din enhed, og din enheds placeringsdata.\n\nKontakt din it-administrator for at få mere at vide."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Denne enhed tilhører din organisation.\n\nDin it-administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er tilknyttet din enhed, og din enheds placeringsdata.\n\nKontakt din it-administrator for at få mere at vide."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Din organisation har installeret et nøglecenter på denne enhed. Din sikre netværkstrafik kan overvåges eller ændres."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Din administrator har aktiveret netværksregistrering, som overvåger trafik på din enhed.\n\nKontakt din administrator for at få flere oplysninger."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Du gav en app tilladelse til at konfigurere en VPN-forbindelse.\n\nDenne app kan overvåge din enhed og netværksaktivitet, bl.a. e-mails, apps og websites."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Din arbejdsprofil administreres af <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nDin administrator kan overvåge din netværksaktivitet, bl.a. e-mails, apps og websites.\n\nKontakt din administrator for at få flere oplysninger.\n\nDu har også forbindelse til et VPN, som kan overvåge din netværksaktivitet."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Denne enhed administreres af din forælder. Din forælder kan se og administrere oplysninger såsom de apps, du bruger, din placering og din skærmtid."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Du har forbindelse til <xliff:g id="APPLICATION">%1$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. mails, apps og websites."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Du har forbindelse til <xliff:g id="APPLICATION">%1$s</xliff:g>, som kan overvåge din private netværksaktivitet, bl.a. e-mails, apps og websites."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Par ny enhed"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildnummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Buildnummeret blev kopieret til udklipsholderen."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 55e7d17c84d2..3aff4c89c162 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Akku - zwei Balken"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Akku - drei Balken"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Akku voll"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Kein Telefon"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefonsignal - ein Balken"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefonsignal - zwei Balken"</string>
@@ -520,6 +522,8 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil wird eventuell überwacht."</string>
<string name="vpn_footer" msgid="3457155078010607471">"Das Netzwerk wird eventuell überwacht."</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Das Netzwerk wird eventuell überwacht"</string>
+ <!-- no translation found for quick_settings_disclosure_parental_controls (2114102871438223600) -->
+ <skip />
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Deine Organisation verwaltet dieses Gerät und kann den Netzwerkverkehr überwachen"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ist der Eigentümer dieses Geräts und kann den Netzwerkverkehr überwachen"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Dieses Gerät gehört deiner Organisation und ist mit <xliff:g id="VPN_APP">%1$s</xliff:g> verbunden"</string>
@@ -544,6 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN deaktivieren"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN-Verbindung trennen"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Richtlinien ansehen"</string>
+ <!-- no translation found for monitoring_button_view_controls (8316440345340701117) -->
+ <skip />
<string name="monitoring_description_named_management" msgid="505833016545056036">"Dieses Gerät gehört <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nDein IT-Administrator kann Einstellungen, Zugriffsrechte im Unternehmen, Apps, mit diesem Gerät verknüpfte Daten und die Standortdaten deines Geräts sehen und verwalten.\n\nWeitere Informationen erhältst du von deinem IT-Administrator."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Dieses Gerät gehört deiner Organisation.\n\nDein IT-Administrator kann Einstellungen, Zugriffsrechte im Unternehmen, Apps, mit diesem Gerät verknüpfte Daten und die Standortdaten deines Geräts sehen und verwalten.\n\nWeitere Informationen erhältst du von deinem IT-Administrator."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Deine Organisation hat ein Zertifikat einer Zertifizierungsstelle auf deinem Gerät installiert. Eventuell wird dein sicherer Netzwerkverkehr überwacht oder bearbeitet."</string>
@@ -567,6 +573,8 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Dein Administrator hat die Netzwerkprotokollierung aktiviert. Damit wird der Verkehr auf deinem Gerät erfasst.\n\nWeitere Informationen erhältst du von deinem Administrator."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Du hast einer App gestattet, eine VPN-Verbindung einzurichten.\n\nDiese App kann dein Gerät und deine Netzwerkaktivitäten überwachen, einschließlich E-Mails, Apps und Websites."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Dein Arbeitsprofil wird von <xliff:g id="ORGANIZATION">%1$s</xliff:g> verwaltet.\n\nDein Administrator kann deine Netzwerkaktivitäten einschließlich E-Mails, Apps und Websites überwachen.\n\nWeitere Informationen erhältst du von deinem Administrator.\n\nAußerdem bist du mit einem VPN verbunden, das deine Netzwerkaktivitäten erfassen kann."</string>
+ <!-- no translation found for monitoring_description_parental_controls (8184693528917051626) -->
+ <skip />
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Du bist mit <xliff:g id="APPLICATION">%1$s</xliff:g> verbunden, die deine Netzwerkaktivitäten überwachen kann, einschließlich E-Mails, Apps und Websites."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Du bist mit der App <xliff:g id="APPLICATION">%1$s</xliff:g> verbunden, die deine persönliche Netzwerkaktivität überwachen kann, einschließlich E-Mails, Apps und Websites."</string>
@@ -1089,4 +1097,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Neues Gerät koppeln"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build-Nummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build-Nummer in Zwischenablage kopiert."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 3bb15ffff775..1a6998e52d23 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Δύο γραμμές μπαταρίας."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Τρεις γραμμές μπαταρίας."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Πλήρης μπαταρία."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Δεν υπάρχει τηλέφωνο."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Μία γραμμή τηλεφώνου."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Δύο γραμμές τηλεφώνου."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Το προφίλ ενδέχεται να παρακολουθείται"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Το δίκτυο ενδέχεται να παρακολουθείται"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Το δίκτυο ενδέχεται να παρακολουθείται"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Αυτή η συσκευή είναι διαχειριζόμενη από τον γονέα σου"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Ο οργανισμός σας κατέχει αυτήν τη συσκευή και μπορεί να παρακολουθεί την επισκεψιμότητα δικτύου."</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Ο οργανισμός <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> κατέχει αυτήν τη συσκευή και μπορεί να παρακολουθεί την επισκεψιμότητα δικτύου."</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Αυτή η συσκευή ανήκει στον οργανισμό σας και είναι συνδεδεμένη στην εφαρμογή <xliff:g id="VPN_APP">%1$s</xliff:g>."</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Απενεργοποίηση VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Αποσύνδεση VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Προβολή πολιτικών"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Προβολή στοιχείων ελέγχου"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Αυτή η συσκευή ανήκει στον οργανισμό <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nΟ διαχειριστής IT μπορεί να παρακολουθεί και να διαχειρίζεται τις ρυθμίσεις, την εταιρική πρόσβαση, τις εφαρμογές, τα δεδομένα που σχετίζονται με τη συσκευή καθώς και τις πληροφορίες τοποθεσίας της συσκευής σας.\n\nΓια περισσότερες πληροφορίες, επικοινωνήστε με τον διαχειριστή IT."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Αυτή η συσκευή ανήκει στον οργανισμό σας.\n\nΟ διαχειριστής IT μπορεί να παρακολουθεί και να διαχειρίζεται τις ρυθμίσεις, την εταιρική πρόσβαση, τις εφαρμογές, τα δεδομένα που σχετίζονται με τη συσκευή καθώς και τις πληροφορίες τοποθεσίας της συσκευής σας.\n\nΓια περισσότερες πληροφορίες, επικοινωνήστε με τον διαχειριστή IT."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Ο οργανισμός σας εγκατέστησε μια αρχή έκδοσης πιστοποιητικών σε αυτήν τη συσκευή. Η ασφαλής επισκεψιμότητα δικτύου σας μπορεί να παρακολουθείται ή να τροποποιείται."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Ο διαχειριστής σας έχει ενεργοποιήσει την καταγραφή δικτύου, η οποία παρακολουθεί την επισκεψιμότητα στη συσκευή σας.\n\nΓια περισσότερες πληροφορίες, επικοινωνήστε με τον διαχειριστή σας."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Παραχωρήσατε σε μια εφαρμογή άδεια για τη ρύθμιση σύνδεσης VPN.\n\nΑυτή η εφαρμογή μπορεί να παρακολουθεί τη δραστηριότητα της συσκευής και του δικτύου σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Η διαχείριση του προφίλ εργασίας γίνεται από τον οργανισμό <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nΟ διαχειριστής έχει τη δυνατότητα παρακολούθησης της δραστηριότητας του δικτύου σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων.\n\nΓια περισσότερες πληροφορίες, επικοινωνήστε με τον διαχειριστή.\n\nΕπίσης, είστε συνδεδεμένοι σε VPN, το οποίο μπορεί να παρακολουθεί τη δραστηριότητα του δικτύου σας."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Αυτή η συσκευή είναι διαχειριζόμενη από τον γονέα σου. Ο γονέας σου μπορεί να βλέπει και να διαχειρίζεται πληροφορίες όπως οι εφαρμογές που χρησιμοποιείς, η τοποθεσία σου και ο χρόνος χρήσης."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Έχετε συνδεθεί στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα του δικτύου σας, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Έχετε συνδεθεί στην εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g>, η οποία μπορεί να παρακολουθεί τη δραστηριότητα του προσωπικού σας δικτύου, συμπεριλαμβανομένων μηνυμάτων ηλεκτρονικού ταχυδρομείου, εφαρμογών και ιστοτόπων."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Σύζευξη νέας συσκευής"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Αριθμός έκδοσης"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Ο αριθμός έκδοσης αντιγράφηκε στο πρόχειρο."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index a743bbe1d58c..fe1d8419274b 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -182,6 +182,7 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Battery two bars."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery three bars."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Battery full."</string>
+ <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
<string name="accessibility_no_phone" msgid="8828412144430247025">"No phone."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Phone one bar."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Phone two bars."</string>
@@ -520,6 +521,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profile may be monitored"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Network may be monitored"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Network may be monitored"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"This device is managed by your parent"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Your organisation owns this device and may monitor network traffic"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> owns this device and may monitor network traffic"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"This device belongs to your organisation and is connected to <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +546,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Disable VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Disconnect VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"View Policies"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"View controls"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"This device belongs to your organisation.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Your organisation installed a certificate authority on this device. Your secure network traffic may be monitored or modified."</string>
@@ -567,6 +570,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information, contact your admin."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"You gave an app permission to set up a VPN connection.\n\nThis app can monitor your device and network activity, including emails, apps and websites."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Your work profile is managed by <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nYour admin is capable of monitoring your network activity including emails, apps and websites.\n\nFor more information, contact your admin.\n\nYou\'re also connected to a VPN, which can monitor your network activity."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps that you use, your location and your screen time."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"You\'re connected to <xliff:g id="APPLICATION">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"You\'re connected to <xliff:g id="APPLICATION">%1$s</xliff:g>, which can monitor your personal network activity, including emails, apps and websites."</string>
@@ -1089,4 +1093,6 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
+ <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problem reading your battery meter"</string>
+ <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Tap for more information"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 3fe7a6a04e6b..a2307e73790d 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -182,6 +182,7 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Battery two bars."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery three bars."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Battery full."</string>
+ <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Battery percentage unknown."</string>
<string name="accessibility_no_phone" msgid="8828412144430247025">"No phone."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Phone one bar."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Phone two bars."</string>
@@ -520,6 +521,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profile may be monitored"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Network may be monitored"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Network may be monitored"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"This device is managed by your parent"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Your organisation owns this device and may monitor network traffic"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> owns this device and may monitor network traffic"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"This device belongs to your organisation and is connected to <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +546,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Disable VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Disconnect VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"View Policies"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"View controls"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"This device belongs to your organisation.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Your organisation installed a certificate authority on this device. Your secure network traffic may be monitored or modified."</string>
@@ -567,6 +570,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information, contact your admin."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"You gave an app permission to set up a VPN connection.\n\nThis app can monitor your device and network activity, including emails, apps and websites."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Your work profile is managed by <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nYour admin is capable of monitoring your network activity including emails, apps and websites.\n\nFor more information, contact your admin.\n\nYou\'re also connected to a VPN, which can monitor your network activity."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps that you use, your location and your screen time."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"You\'re connected to <xliff:g id="APPLICATION">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"You\'re connected to <xliff:g id="APPLICATION">%1$s</xliff:g>, which can monitor your personal network activity, including emails, apps and websites."</string>
@@ -1089,4 +1093,6 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
+ <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"Problem reading your battery meter"</string>
+ <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"Tap for more information"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index a743bbe1d58c..50288b2d5879 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Battery two bars."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery three bars."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Battery full."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"No phone."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Phone one bar."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Phone two bars."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profile may be monitored"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Network may be monitored"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Network may be monitored"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"This device is managed by your parent"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Your organisation owns this device and may monitor network traffic"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> owns this device and may monitor network traffic"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"This device belongs to your organisation and is connected to <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Disable VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Disconnect VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"View Policies"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"View controls"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"This device belongs to your organisation.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Your organisation installed a certificate authority on this device. Your secure network traffic may be monitored or modified."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information, contact your admin."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"You gave an app permission to set up a VPN connection.\n\nThis app can monitor your device and network activity, including emails, apps and websites."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Your work profile is managed by <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nYour admin is capable of monitoring your network activity including emails, apps and websites.\n\nFor more information, contact your admin.\n\nYou\'re also connected to a VPN, which can monitor your network activity."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps that you use, your location and your screen time."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"You\'re connected to <xliff:g id="APPLICATION">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"You\'re connected to <xliff:g id="APPLICATION">%1$s</xliff:g>, which can monitor your personal network activity, including emails, apps and websites."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index a743bbe1d58c..50288b2d5879 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Battery two bars."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Battery three bars."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Battery full."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"No phone."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Phone one bar."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Phone two bars."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profile may be monitored"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Network may be monitored"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Network may be monitored"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"This device is managed by your parent"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Your organisation owns this device and may monitor network traffic"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> owns this device and may monitor network traffic"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"This device belongs to your organisation and is connected to <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Disable VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Disconnect VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"View Policies"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"View controls"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"This device belongs to <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"This device belongs to your organisation.\n\nYour IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.\n\nFor more information, contact your IT admin."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Your organisation installed a certificate authority on this device. Your secure network traffic may be monitored or modified."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information, contact your admin."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"You gave an app permission to set up a VPN connection.\n\nThis app can monitor your device and network activity, including emails, apps and websites."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Your work profile is managed by <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nYour admin is capable of monitoring your network activity including emails, apps and websites.\n\nFor more information, contact your admin.\n\nYou\'re also connected to a VPN, which can monitor your network activity."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"This device is managed by your parent. Your parent can see and manage information such as the apps that you use, your location and your screen time."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"You\'re connected to <xliff:g id="APPLICATION">%1$s</xliff:g>, which can monitor your network activity, including emails, apps and websites."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"You\'re connected to <xliff:g id="APPLICATION">%1$s</xliff:g>, which can monitor your personal network activity, including emails, apps and websites."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Pair new device"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build number"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build number copied to clipboard."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 78006fda8683..fe7f4e05138b 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -182,6 +182,7 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‏‏‎‎‎‏‏‏‎‏‎‏‎‎‎‏‎‏‏‏‎‎‏‏‎‏‎‎‏‏‏‏‎Battery two bars.‎‏‎‎‏‎"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‎‎‏‎‎‎‏‏‎‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‎‏‏‎‎‎‎‎‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎‏‏‎Battery three bars.‎‏‎‎‏‎"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‎‎‎‏‏‎‏‏‏‏‎‏‎‎‎‎‏‎‎‏‎‎‎‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‎‎Battery full.‎‏‎‎‏‎"</string>
+ <string name="accessibility_battery_unknown" msgid="1807789554617976440">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‎‎‏‏‏‏‎‎‎‎Battery percentage unknown.‎‏‎‎‏‎"</string>
<string name="accessibility_no_phone" msgid="8828412144430247025">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‎‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‎‎‏‏‏‎‎‎‏‎No phone.‎‏‎‎‏‎"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‏‎‎‏‎‏‎‏‏‎‏‎‎‎‏‎‏‏‎‎‏‎‏‏‏‎‎‏‏‏‏‎‎‏‏‏‎‏‎‎‎Phone one bar.‎‏‎‎‏‎"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‏‎‎‎‎‎‎‎‎‏‏‏‏‎‏‏‏‎‎‎‎‎‎‎‏‎‏‏‎‎‎‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‎‎‏‎‎Phone two bars.‎‏‎‎‏‎"</string>
@@ -520,6 +521,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‎‎‎‏‎‎‎‎‎‎‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‏‎‏‏‎‎‎Profile may be monitored‎‏‎‎‏‎"</string>
<string name="vpn_footer" msgid="3457155078010607471">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‎‎‎‏‎‏‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎Network may be monitored‎‏‎‎‏‎"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‏‏‎‎‏‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‎‏‎‎‎‏‎‎Network may be monitored‎‏‎‎‏‎"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‏‎‏‎‏‎‏‏‏‎‎‎‏‎‎‏‏‏‎‏‎‏‏‎‏‎‏‎‏‏‎‏‎‎‎‏‏‏‏‎‎‎‎‎This device is managed by your parent‎‏‎‎‏‎"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‏‎‏‎‏‎‏‎‎‎‏‏‎‏‏‏‎‏‏‎‏‏‏‎‏‏‏‎‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎Your organization owns this device and may monitor network traffic‎‏‎‎‏‎"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‎‏‏‏‎‏‏‎‏‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‎‏‏‎<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ owns this device and may monitor network traffic‎‏‎‎‏‎"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‎‎‏‎‏‎‎‎‏‏‏‏‎‏‎‎‎‏‎‏‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‎This device belongs to your organization and is connected to ‎‏‎‎‏‏‎<xliff:g id="VPN_APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
@@ -544,6 +546,7 @@
<string name="disable_vpn" msgid="482685974985502922">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‏‏‎‎‏‎‏‏‎‏‏‎‎‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‎‏‎‎Disable VPN‎‏‎‎‏‎"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‎‏‏‏‎‏‎‏‏‎‎‎‏‏‏‏‎‎‎‎‎‎‎‎‏‏‎‏‏‏‎‎‏‏‎‏‏‏‎‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‎Disconnect VPN‎‏‎‎‏‎"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‏‎‎‎‎‎‎‎‏‏‎‎‎‏‏‏‏‎‎‎‏‎‎‏‎‏‏‏‎‎‎‏‏‏‎‎‎‎‎‎‏‏‏‏‏‎‎‏‎‏‎‎View Policies‎‏‎‎‏‎"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‏‎‎‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‎‏‎‎‎‎‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‏‎‏‎View controls‎‏‎‎‏‎"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‏‎‏‎‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎‏‎‏‏‎‏‎‏‎‏‎‎‎‏‎‏‎‏‎‎‏‎‎‏‎‎‎This device belongs to ‎‏‎‎‏‏‎<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Your IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎For more information, contact your IT admin.‎‏‎‎‏‎"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‎‎‏‏‎‎‎‎‏‏‎‏‏‎‏‎‏‎‏‎‎‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‎This device belongs to your organization.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Your IT admin can monitor and manage settings, corporate access, apps, data associated with your device, and your device\'s location information.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎For more information, contact your IT admin.‎‏‎‎‏‎"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‏‎‎‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎‎‎‎‏‎‎‎‎‏‎‏‎‎‎‎‎‏‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‎Your organization installed a certificate authority on this device. Your secure network traffic may be monitored or modified.‎‏‎‎‏‎"</string>
@@ -567,6 +570,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‏‏‎‎‎‎‎‎‎‎‏‏‏‏‎‎‏‎‎‏‏‎‎‎Your admin has turned on network logging, which monitors traffic on your device.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎For more information, contact your admin.‎‏‎‎‏‎"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‏‎‎‎‏‏‏‏‎‏‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‎‏‏‏‎‏‏‎‎You gave an app permission to set up a VPN connection.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎This app can monitor your device and network activity, including emails, apps, and websites.‎‏‎‎‏‎"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‎‎‏‎‎‏‎‎‎‎‎‏‏‎‏‎‎‏‎‎‎‎‎‏‏‎‏‎‎‏‎‎‏‎‏‏‏‏‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎Your work profile is managed by ‎‏‎‎‏‏‎<xliff:g id="ORGANIZATION">%1$s</xliff:g>‎‏‎‎‏‏‏‎.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Your admin is capable of monitoring your network activity including emails, apps, and websites.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎For more information, contact your admin.‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎You\'re also connected to a VPN, which can monitor your network activity.‎‏‎‎‏‎"</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‎‏‎‏‏‏‎‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎‎‎‎‏‎‎‎‏‏‏‎‏‎‏‎‎This device is managed by your parent. Your parent can see and manage information such as the apps you use, your location, and your screen time.‎‏‎‎‏‎"</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‎‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‏‎‏‎‎‏‎VPN‎‏‎‎‏‎"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‏‎‏‏‏‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‏‏‎‏‏‎‎‏‏‎‎‎‎‏‏‏‏‎‎‎‏‎You\'re connected to ‎‏‎‎‏‏‎<xliff:g id="APPLICATION">%1$s</xliff:g>‎‏‎‎‏‏‏‎, which can monitor your network activity, including emails, apps, and websites.‎‏‎‎‏‎"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‎‏‎‏‏‏‎‎‏‎‏‏‏‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‎‎‎‏‏‎‎‏‏‏‎‎‎‎‏‎‏‏‎‎‎‎‎‎‏‏‎You\'re connected to ‎‏‎‎‏‏‎<xliff:g id="APPLICATION">%1$s</xliff:g>‎‏‎‎‏‏‏‎, which can monitor your personal network activity, including emails, apps, and websites.‎‏‎‎‏‎"</string>
@@ -1089,4 +1093,6 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‎‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‎‏‏‎‏‎‎‏‏‎‎Pair new device‎‏‎‎‏‎"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‎‎‎‎‎‏‏‏‎‎‎‎‎‎‏‎‎‏‏‎‏‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‎‎‏‎‎‏‎‎Build number‎‏‎‎‏‎"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‎‏‎‏‏‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‏‏‎‎‏‎‏‏‏‏‎‎‎‎‏‎‎‎‏‏‎‎Build number copied to clipboard.‎‏‎‎‏‎"</string>
+ <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‎‏‎‏‎‏‏‎‎‎‏‏‏‎‎‏‏‏‏‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‎‎‎‎‏‏‏‎‎Problem reading your battery meter‎‏‎‎‏‎"</string>
+ <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‎‎‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎‏‎‎‎‏‎‎‎‏‏‎Tap for more information‎‏‎‎‏‎"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index d30a39529051..d6c5e15f7eb7 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Dos barras de batería"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Tres barras de batería"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batería completa"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Sin teléfono"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Una barra de teléfono"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dos barras de teléfono"</string>
@@ -520,6 +522,8 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Es posible que se supervise el perfil."</string>
<string name="vpn_footer" msgid="3457155078010607471">"Es posible que la red esté supervisada."</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Es posible que la red esté supervisada"</string>
+ <!-- no translation found for quick_settings_disclosure_parental_controls (2114102871438223600) -->
+ <skip />
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Tu organización es propietaria de este dispositivo y podría controlar el tráfico de red"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> es la organización propietaria de este dispositivo y podría controlar el tráfico de red"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Este dispositivo pertenece a tu organización y está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Inhabilitar VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Desconectar VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Ver políticas"</string>
+ <!-- no translation found for monitoring_button_view_controls (8316440345340701117) -->
+ <skip />
<string name="monitoring_description_named_management" msgid="505833016545056036">"Este dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nTu administrador de TI puede controlar y administrar la configuración, el acceso corporativo, las apps, los datos asociados al dispositivo y la información de ubicación.\n\nPara obtener más información, comunícate con el administrador de TI."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Este dispositivo pertenece a tu organización.\n\nTu administrador de TI puede controlar y administrar la configuración, el acceso corporativo, las apps, los datos asociados al dispositivo y la información de ubicación.\n\nPara obtener más información, comunícate con el administrador de TI."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Tu organización instaló una autoridad de certificación en este dispositivo. Es posible que se controle o modifique el tráfico de tu red segura."</string>
@@ -567,6 +573,8 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Tu administrador activó el registro de red, que controla el tráfico en tu dispositivo.\n\nComunícate con él para obtener más información."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Permitiste que una aplicación configurara una conexión VPN.\n\nEsta aplicación puede supervisar la actividad de la red y del dispositivo, incluidos los correos electrónicos, las aplicaciones y los sitios web."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> administra tu perfil de trabajo.\n\nTu administrador puede controlar tu actividad en la red, como los correos electrónicos, las apps y los sitios web.\n\nComunícate con él para obtener más información.\n\nTambién estás conectado a una VPN, que puede controlar tu actividad en la red."</string>
+ <!-- no translation found for monitoring_description_parental_controls (8184693528917051626) -->
+ <skip />
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Estás conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que puede controlar la actividad de la red, incluidos los correos electrónicos, las apps y los sitios web."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Tienes conexión a la aplicación <xliff:g id="APPLICATION">%1$s</xliff:g>, que puede supervisar la actividad de la red personal, incluidos los correos electrónicos, las aplicaciones y los sitios web."</string>
@@ -1089,4 +1097,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular dispositivo nuevo"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Se copió el número de compilación en el portapapeles."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 875c310eb133..9726134d4158 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Dos barras de batería"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Tres barras de batería"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batería completa"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Sin teléfono"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Una barra de cobertura"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dos barras de cobertura"</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Es posible que se supervise el perfil"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Puede que la red esté supervisada"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Puede que la red esté supervisada"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo lo gestionan tu padre o tu madre"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"El dispositivo pertenece a tu organización, que puede monitorizar su tráfico de red"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"El dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, que puede monitorizar su tráfico de red"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Este dispositivo pertenece a tu organización y está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Inhabilitar VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Desconectar VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Ver políticas"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Ver controles"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"El dispositivo pertenece a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nEl administrador de TI puede monitorizar y gestionar los ajustes, el acceso corporativo, las aplicaciones, la información de ubicación del dispositivo y los datos asociados a él.\n\nPara obtener más información, ponte en contacto con el administrador de TI."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"El dispositivo pertenece a tu organización.\n\nEl administrador de TI puede monitorizar y gestionar los ajustes, el acceso corporativo, las aplicaciones, la información de ubicación del dispositivo y los datos asociados a él.\n\nPara obtener más información, ponte en contacto con el administrador de TI."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Tu organización ha instalado una entidad de certificación en este dispositivo. Es posible que se supervise o se modifique tu tráfico de red seguro."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Tu administrador ha activado el registro de la red para supervisar el tráfico en tu dispositivo.\n\nPonte en contacto con él para obtener más información."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Has concedido permiso a una aplicación para configurar una conexión VPN.\n\nEsta aplicación puede controlar tu dispositivo y tu actividad de red, como correos electrónicos, aplicaciones y sitios web."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"El administrador de tu perfil de trabajo es <xliff:g id="ORGANIZATION">%1$s</xliff:g>,\n\n que puede supervisar tu actividad de red, como correos electrónicos, aplicaciones y sitios web.\n\nPara obtener más información, ponte en contacto con tu administrador.\n\nTambién estás conectado a una red VPN, que puede supervisar tu actividad de red."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Tu padre o madre gestionan este dispositivo y pueden ver y controlar cierta información, como las aplicaciones que utilizas, tu ubicación y tu tiempo de pantalla."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Te has conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que puede supervisar tu actividad de red, como los correos electrónicos, las aplicaciones y los sitios web."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Estas conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que puede controlar tu actividad de red personal, como correos electrónicos, aplicaciones y sitios web."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular nuevo dispositivo"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número de compilación copiado en el portapapeles."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index f9940a30fcaa..d8ec8be5d922 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Aku: kaks pulka."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Aku: kolm pulka."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Aku täis."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Telefonisignaal puudub"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefonisignaal: üks pulk."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefonisignaal: kaks pulka."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profiili võidakse jälgida"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Võrku võidakse jälgida"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Võrku võidakse jälgida"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Seda seadet haldab sinu vanem"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Teie organisatsioon on selle seadme omanik ja võib jälgida võrguliiklust"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> on selle seadme omanik ja võib jälgida võrguliiklust"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"See seade kuulub teie organisatsioonile ja on ühendatud rakendusega <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Keela VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Katkesta VPN-i ühendus"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Kuva eeskirjad"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Kuva järelevalve haldamine"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"See seade kuulub organisatsioonile <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nIT-administraator saab jälgida ning hallata seadeid, ettevõttesisest juurdepääsu, rakendusi, seadmega seotud andmeid ja seadme asukohateavet.\n\nLisateabe saamiseks võtke ühendust IT-administraatoriga."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"See seade kuulub teie organisatsioonile.\n\nIT-administraator saab jälgida ning hallata seadeid, ettevõttesisest juurdepääsu, rakendusi, seadmega seotud andmeid ja seadme asukohateavet.\n\nLisateabe saamiseks võtke ühendust IT-administraatoriga."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Teie organisatsioon installis sellesse seadmesse sertifikaadi volituse. Teie turvalist võrguliiklust võidakse jälgida ja muuta."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Teie administraator on sisse lülitanud võrgu logimise funktsiooni, mis jälgib teie seadmes liiklust.\n\nLisateabe saamiseks võtke ühendust administraatoriga."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Andsite rakendusele loa VPN-i ühenduse seadistamiseks.\n\nSee rakendus võib jälgida teie seadet ja võrgutegevusi, sh meile, rakendusi ja veebisaite."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Teie tööprofiili haldab <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministraator saab jälgida teie töökoha võrgutegevusi, sh meile, rakendusi ja veebisaite.\n\nLisateabe saamiseks võtke ühendust administraatoriga.\n\nTeil on ühendus ka VPN-iga, mis saab teie võrgutegevusi jälgida."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Seda seadet haldab sinu vanem. Sinu vanem näeb ja saab hallata teavet, näiteks kasutatavaid rakendusi, asukohta ja ekraaniaega."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Olete ühendatud rakendusega <xliff:g id="APPLICATION">%1$s</xliff:g>, mis võib jälgida teie võrgutegevusi, sh meile, rakendusi ja veebisaite."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Teie seade on ühendatud rakendusega <xliff:g id="APPLICATION">%1$s</xliff:g>, mis võib jälgida teie isiklikke võrgutegevusi, sh meile, rakendusi ja veebisaite."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Uue seadme sidumine"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Järgunumber"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Järgunumber kopeeriti lõikelauale."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index cb86a16122c0..8aa247f64591 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Bateriak bi barra ditu."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Bateriak hiru barra ditu."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria beteta dago."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Ez dago telefono-zenbakirik."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefono-seinaleak barra bat du."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefono-seinaleak bi barra ditu."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Baliteke profila kontrolatuta egotea"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Baliteke sarea kontrolatuta egotea"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Baliteke sarea kontrolatuta egotea"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Zure gurasoak kudeatzen du gailua"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Gailu hau zure erakundearena da, eta baliteke hark sareko trafikoa gainbegiratzea"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Gailu hau <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> erakundearena da, eta baliteke sareko trafikoa gainbegiratzea"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Gailu hau zure erakundearena da, eta <xliff:g id="VPN_APP">%1$s</xliff:g> sarera dago konektatuta"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Desgaitu VPN konexioa"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Deskonektatu VPN sarea"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Ikusi gidalerroak"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Ikusi kontrolatzeko aukerak"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Gailu hau <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> erakundearena da.\n\nIKT saileko administratzaileak gainbegiratu eta kudeatu egin ditzake ezarpenak, enpresa-sarbidea, aplikazioak, gailuarekin erlazionatutako datuak eta gailuaren kokapen-informazioa.\n\nInformazio gehiago lortzeko, jarri IKT saileko administratzailearekin harremanetan."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Gailu hau zure erakundearena da.\n\nIKT saileko administratzaileak gainbegiratu eta kudeatu egin ditzake ezarpenak, enpresa-sarbidea, aplikazioak, gailuarekin erlazionatutako datuak eta gailuaren kokapen-informazioa.\n\nInformazio gehiago lortzeko, jarri IKT saileko administratzailearekin harremanetan."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Erakundeak ziurtagiri-emaile bat instalatu du gailuan. Baliteke sareko trafiko segurua gainbegiratzea edo aldatzea."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Administratzaileak sare-erregistroak aktibatu ditu; horrela, zure gailuko trafikoa gainbegira dezake.\n\nInformazio gehiago lortzeko, jarri administratzailearekin harremanetan."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Aplikazio bati VPN konexio bat konfiguratzeko baimena eman diozu.\n\nAplikazio horrek gailuko eta sareko jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> erakundeak kudeatzen du zure laneko profila.\n\nAdministratzaileak sareko jarduerak kontrola diezazkizuke, besteak beste, posta elektronikoa, aplikazioak eta webguneak.\n\nInformazio gehiago lortzeko, jarri administratzailearekin harremanetan.\n\nHorrez gain, VPN batera zaude konektatuta, eta hark ere kontrola ditzake zure sareko jarduerak."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Zure gurasoak kudeatzen du gailua. Zure gurasoak gailuko informazioa ikus eta kudea dezake; besteak beste, zer aplikazio erabiltzen dituzun, zure kokapena zein den eta pantaila aurrean zenbat eta noiz egoten zaren."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN konexioa"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"<xliff:g id="APPLICATION">%1$s</xliff:g> aplikaziora konektatuta zaude. Aplikazio horrek sarean egiten dituzun jarduerak kontrola ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"<xliff:g id="APPLICATION">%1$s</xliff:g> aplikaziora konektatuta zaude. Aplikazio horrek sarean egiten dituzun jarduera pertsonalak kontrola ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parekatu beste gailu batekin"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Konpilazio-zenbakia"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Kopiatu da konpilazio-zenbakia arbelean."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index afa0759e90a2..d4f62520cfe8 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"دو نوار برای باتری."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"سه نوار برای باتری."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"باتری پر است."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"بدون تلفن."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"یک نوار برای تلفن."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"دو نوار برای تلفن."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"شاید نمایه کنترل شود"</string>
<string name="vpn_footer" msgid="3457155078010607471">"ممکن است شبکه کنترل شود"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ممکن است شبکه کنترل شود"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"این دستگاه را ولی‌تان مدیریت می‌کند"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"مالک این دستگاه سازمان شما است و ممکن است ترافیک شبکه را پایش کند"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"مالک این دستگاه <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> است و ممکن است ترافیک شبکه را پایش کند"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"این دستگاه به سازمان شما تعلق دارد و به <xliff:g id="VPN_APP">%1$s</xliff:g> متصل است"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"‏غیرفعال کردن VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"‏قطع اتصال VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"مشاهده خط‌مشی‌ها"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"مشاهده کنترل‌ها"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"این دستگاه به <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> تعلق دارد.\n\nسرپرست فناوری اطلاعات می‌تواند تنظیمات، دسترسی شرکتی، برنامه‌ها، داده‌های مرتبط با دستگاه، و اطلاعات مکان دستگاهتان را کنترل و مدیریت کند.\n\nبرای اطلاعات بیشتر، با سرپرست فناوری و اطلاعات تماس بگیرید."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"این دستگاه به سازمان شما تعلق دارد.\n\nسرپرست فناوری اطلاعات می‌تواند تنظیمات، دسترسی شرکتی، برنامه‌ها، و داده‌های مرتبط با دستگاه و اطلاعات مکان دستگاهتان را کنترل و مدیریت کند.\n\nبرای اطلاعات بیشتر، با سرپرست فناوری و اطلاعات تماس بگیرید."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"سازمان شما مرجع گواهینامه‌ای در این دستگاه نصب کرده است. ممکن است ترافیک امن شبکه شما پایش یا تغییر داده شود."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"سرپرست سیستم شما گزارش‌گیری شبکه را (که بر ترافیک دستگاهتان نظارت می‌کند) روشن کرده است.\n\nبرای اطلاعات بیشتر، با سرپرست خود تماس بگیرید."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"‏شما به برنامه‌ای برای تنظیم اتصال VPN اجازه دادید.\n\n این برنامه می‌تواند دستگاه و فعالیت شبکه‌تان را کنترل کند، از جمله ایمیل‌، برنامه‌ و وب‌سایت‌ها."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"‏نمایه کاری شما توسط <xliff:g id="ORGANIZATION">%1$s</xliff:g> مدیریت می‌شود.\n\nسرپرست سیستم شما می‌تواند بر فعالیت شبکه شما (ازجمله ایمیل‌ها، برنامه‌ها و وب‌سایت‌ها) نظارت داشته باشد.\n\nبرای اطلاعات بیشتر، با سرپرست خود تماس بگیرید.\n\nهمچنین به VPN متصل هستید که می‌تواند بر فعالیت شبکه شما نظارت داشته باشد."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"این دستگاه را ولی‌تان مدیریت می‌کند. ولی‌تان می‌تواند اطلاعاتی مثل برنامه‌هایی که استفاده می‌کنید، مکانتان، و مدت تماشای صفحه‌تان را ببیند و مدیریت کند."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"شما به <xliff:g id="APPLICATION">%1$s</xliff:g> متصل هستید، که می‌تواند فعالیت شما در شبکه (ازجمله ایمیل‌، برنامه‌ و وب‌سایت‌ها) را پایش کند."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"شما به <xliff:g id="APPLICATION">%1$s</xliff:g> وصل شده‌اید، که می‌تواند فعالیت شبکه شخصی شما از جمله ایمیل‌، برنامه‌ و وب‌سایت‌ها را کنترل کند."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"مرتبط کردن دستگاه جدید"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"شماره ساخت"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"شماره ساخت در بریده‌دان کپی شد."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 11c7e19be208..0ed15093096e 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Akun virta - kaksi palkkia."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Akun virta - kolme palkkia."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Akku täynnä."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Ei puhelinverkkoyhteyttä."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Puhelinverkkosignaali - yksi palkki."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Puhelinverkkosignaali - kaksi palkkia."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profiilia saatetaan valvoa"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Verkkoa saatetaan valvoa"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Verkkoa saatetaan valvoa"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Vanhempasi ylläpitää tätä laitetta"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organisaatiosi omistaa laitteen ja voi valvoa verkkoliikennettä"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> omistaa laitteen ja voi valvoa verkkoliikennettä"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Organisaatiosi omistaa laitteen, joka on yhdistetty tähän: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Poista VPN käytöstä"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Katkaise VPN-yhteys"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Näytä säännöt"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Katso asetukset"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> omistaa tämän laitteen.\n\nJärjestelmänvalvoja voi valvoa ja muuttaa asetuksia, yrityskäyttöä, sovelluksia sekä laitteeseen yhdistettyjä tietoja ja sen sijaintitietoja.\n\nSaat lisätietoja järjestelmänvalvojalta."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Organisaatiosi omistaa tämän laitteen.\n\nJärjestelmänvalvoja voi valvoa ja muuttaa asetuksia, yrityskäyttöä, sovelluksia sekä laitteeseen yhdistettyjä tietoja ja sen sijaintitietoja.\n\nSaat lisätietoja järjestelmänvalvojalta."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organisaatiosi asensi laitteeseen varmenteen myöntäjän. Suojattua verkkoliikennettäsi voidaan valvoa tai muuttaa."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Järjestelmänvalvoja on ottanut käyttöön verkkolokitietojen tallentamisen. Sen avulla seurataan laitteellasi tapahtuvaa liikennettä.\n\nPyydä lisätietoja järjestelmänvalvojalta."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Olet myöntänyt sovellukselle oikeuden VPN-yhteyden muodostamiseen.\n\nSovellus voi valvoa laitettasi ja toimintaasi verkossa, esimerkiksi avaamiasi sähköposteja, sovelluksia ja verkkosivustoja."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Työprofiiliasi hallitsee <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nJärjestelmänvalvoja voi valvoa sähköpostin, sovellusten ja verkkosivustojen käyttöä sekä muuta toimintaasi verkossa.\n\nPyydä lisätietoja järjestelmänvalvojalta.\n\nOlet myös yhteydessä VPN:ään, joka voi valvoa toimintaasi verkossa."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Vanhempasi ylläpitää tätä laitetta. Vanhempasi voi nähdä ja ylläpitää tietoja, esim. käyttämiäsi sovelluksia, sijaintiasi ja käyttöaikaasi."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Olet muodostanut yhteyden sovellukseen <xliff:g id="APPLICATION">%1$s</xliff:g>, joka voi valvoa toimintaasi verkossa, esimerkiksi sähköposteja, sovelluksia ja verkkosivustoja."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Olet muodostanut yhteyden sovellukseen <xliff:g id="APPLICATION">%1$s</xliff:g>, joka voi valvoa henkilökohtaista toimintaasi verkossa. Sovellus voi seurata esimerkiksi avaamiasi sähköposteja, sovelluksia ja verkkosivustoja."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Muodosta uusi laitepari"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Koontiversion numero"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Koontiversion numero kopioitu leikepöydälle"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index b8ea6ac31c77..c7e827fbce21 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Niveau de batterie : moyen"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Niveau de batterie : bon"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batterie pleine"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Aucun signal"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Signal : faible"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Signal : moyen"</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"le profil peut être contrôlé"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Le réseau peut être surveillé"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Le réseau peut être surveillé"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Cet appareil est géré par votre parent"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Votre organisation possède cet appareil et peut contrôler le trafic réseau"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> possède cet appareil et peut contrôler le trafic réseau"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Cet appareil appartient à votre organisation et est connecté à <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Désactiver le RPV"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Déconnecter le RPV"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Afficher les politiques"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Afficher les commandes"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Votre appareil appartient à <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nVotre administrateur informatique peut contrôler et gérer les paramètres, l\'accès aux données d\'entreprise, les applications, les données associées à l\'appareil et les renseignements sur sa position.\n\nPour obtenir plus d\'information, communiquez avec votre administrateur informatique."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Cet appareil appartient à votre organisation.\n\nVotre administrateur informatique peut contrôler et gérer les paramètres, l\'accès aux données d\'entreprise, les applications, les données associées à votre appareil et les renseignements sur sa position.\n\nPour obtenir plus d\'information, communiquez avec votre administrateur informatique."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Votre entreprise a installé une autorité de certification sur cet appareil. Votre trafic sur le réseau sécurisé peut être contrôlé ou modifié."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Votre administrateur a activé la journalisation réseau, qui surveille le trafic sur votre appareil.\n\nPour en savoir plus, communiquez avec lui."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Vous avez autorisé une application à configurer une connexion RPV.\n\nCette application peut contrôler l\'activité de votre appareil et votre activité sur le réseau, y compris les courriels, les applications et les sites Web."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Votre profil professionnel est géré par <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nVotre administrateur peut surveiller votre activité sur le réseau, y compris les courriels que vous échangez, les applications que vous utilisez et les sites Web que vous visitez.\n\nPour en savoir plus, communiquez avec votre administrateur.\n\nVous êtes aussi connecté à un RPV, qui peut surveiller votre activité sur le réseau."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Cet appareil est géré par ton parent. Ton parent peut voir et gérer de l\'information, comme les applications que tu utilises, ta position et ton temps d\'utilisation des écrans."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"RPV"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Vous êtes connecté à <xliff:g id="APPLICATION">%1$s</xliff:g>. Cette application peut contrôler votre activité sur le réseau, y compris les courriels, les applications et les sites Web."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Vous êtes connecté à <xliff:g id="APPLICATION">%1$s</xliff:g>. Cette application peut contrôler votre activité personnelle sur le réseau, y compris les courriels, les applications et les sites Web."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Associer un autre appareil"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de version"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Le numéro de version a été copié dans le presse-papiers."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 289ce40d2ce7..781a43cefce1 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Niveau de batterie : moyen"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Niveau de batterie : bon"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batterie pleine"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Aucun signal"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Signal : faible"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Signal : moyen"</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Le profil peut être contrôlé."</string>
<string name="vpn_footer" msgid="3457155078010607471">"Il est possible que le réseau soit surveillé."</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Il est possible que le réseau soit surveillé."</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Cet appareil est géré par tes parents"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Cet appareil appartient à votre organisation, qui peut contrôler votre trafic réseau"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Cet appareil appartient à <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, qui peut contrôler votre trafic réseau"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Cet appareil appartient à votre organisation et il est connecté à <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Désactiver le VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Déconnecter le VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Afficher les règles"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Afficher les commandes"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Cet appareil appartient à <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nVotre administrateur informatique peut contrôler et gérer les paramètres, l\'accès aux données d\'entreprise, les applications, les données associées à l\'appareil et les informations sur sa localisation.\n\nPour plus d\'informations, contactez votre administrateur informatique."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Cet appareil appartient à votre organisation.\n\nVotre administrateur informatique peut contrôler et gérer les paramètres, l\'accès aux données d\'entreprise, les applications, les données associées à l\'appareil et les informations sur sa localisation.\n\nPour plus d\'informations, contactez votre administrateur informatique."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Votre entreprise a installé une autorité de certification sur cet appareil. Votre trafic sur le réseau sécurisé peut être contrôlé ou modifié."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Votre administrateur a activé la journalisation réseau, qui surveille le trafic sur votre appareil.\n\nPour en savoir plus, contactez-le."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Vous avez autorisé une application à configurer une connexion VPN.\n\nCette application peut contrôler l\'activité de votre appareil et votre activité sur le réseau, y compris votre activité relative aux e-mails, aux applications et aux sites Web."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Votre profil professionnel est géré par <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nVotre administrateur peut contrôler votre activité sur le réseau, y compris au niveau des e-mails, des applications et des sites Web.\n\nPour en savoir plus, contactez-le.\n\nVous êtes également connecté à un VPN qui peut contrôler votre activité sur le réseau."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Cet appareil est géré par tes parents. Ils peuvent voir et gérer certaines informations, telles que les applications que tu utilises, ta position et ton temps d\'utilisation de l\'appareil."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Vous êtes connecté à <xliff:g id="APPLICATION">%1$s</xliff:g>. Cette application peut contrôler votre activité sur le réseau, y compris l\'activité relative aux e-mails, aux applications et aux sites Web."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Vous êtes connecté à <xliff:g id="APPLICATION">%1$s</xliff:g>. Cette application peut contrôler votre activité personnelle sur le réseau, y compris votre activité relative aux e-mails, aux applications et aux sites Web."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Associer un nouvel appareil"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numéro de build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numéro de build copié dans le presse-papiers."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index e3d3755d4f68..80fb4027a6a5 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Dúas barras de batería"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Tres barras de batería"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batería cargada"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Sen teléfono"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Unha barra de cobertura"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dúas barras de cobertura"</string>
@@ -520,6 +522,8 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"O perfil pódese supervisar"</string>
<string name="vpn_footer" msgid="3457155078010607471">"É posible que se supervise a rede"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"É posible que se supervise a rede"</string>
+ <!-- no translation found for quick_settings_disclosure_parental_controls (2114102871438223600) -->
+ <skip />
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"A túa organización é propietaria deste dispositivo e pode controlar o tráfico de rede"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é a organización propietaria deste dispositivo e pode controlar o tráfico de rede"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Este dispositivo pertence á túa organización e está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"Desactivar VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Desconectar VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Ver políticas"</string>
+ <!-- no translation found for monitoring_button_view_controls (8316440345340701117) -->
+ <skip />
<string name="monitoring_description_named_management" msgid="505833016545056036">"Este dispositivo pertence a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nO teu administrador de TI pode supervisar e xestionar a configuración, o acceso corporativo, as aplicacións, os datos asociados co teu dispositivo e a información de localización deste último.\n\nPara obter máis información, contacta co teu administrador de TI."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Este dispositivo pertence á túa organización.\n\nO teu administrador de TI pode supervisar e xestionar a configuración, o acceso corporativo, as aplicacións, os datos asociados co teu dispositivo e a información de localización deste último.\n\nPara obter máis información, contacta co teu administrador de TI."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"A túa organización instalou unha autoridade de certificación neste dispositivo. É posible que se controle ou se modifique o teu tráfico de rede segura."</string>
@@ -567,6 +573,8 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"O administrador activou o rexistro na rede, que controla o tráfico do teu dispositivo.\n\nPara obter máis información, contacta co administrador."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Outorgaches permiso a unha aplicación para configurar unha conexión VPN.\n\nEsta aplicación pode supervisar a túa actividade na rede, incluídos os correos electrónicos, as aplicacións e os sitios web."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> xestiona o teu perfil de traballo.\n\nO administrador pode controlar a túa actividade na rede, mesmo os correos electrónicos, as aplicacións e os sitios web.\n\nPara obter máis información, ponte en contacto co administrador.\n\nTamén estás conectado a unha VPN, que pode controlar a túa actividade na rede."</string>
+ <!-- no translation found for monitoring_description_parental_controls (8184693528917051626) -->
+ <skip />
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Estás conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode controlar a túa actividade na rede, mesmo os correos electrónicos, as aplicacións e os sitios web."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Estás conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode supervisar a túa actividade persoal na rede, incluídos os correos electrónicos, as aplicacións e os sitios web."</string>
@@ -1089,4 +1097,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Vincular dispositivo novo"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número de compilación"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Copiouse o número de compilación no portapapeis."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 02c72dbbc7a6..85a084d10389 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"બૅટરી બે બાર."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"બૅટરી ત્રણ બાર."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"બૅટરી પૂર્ણ."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"કોઈ ફોન નથી."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ફોન એક બાર."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ફોન બે બાર."</string>
@@ -331,10 +333,10 @@
<string name="notification_summary_message_format" msgid="5158219088501909966">"<xliff:g id="CONTACT_NAME">%1$s</xliff:g>: <xliff:g id="MESSAGE_CONTENT">%2$s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="6818779631806163080">"સૂચનાઓની સેટિંગ્સ"</string>
<string name="status_bar_notification_app_settings_title" msgid="5050006438806013903">"<xliff:g id="APP_NAME">%s</xliff:g> સેટિંગ"</string>
- <string name="accessibility_rotation_lock_off" msgid="3880436123632448930">"સ્ક્રીન આપમેળે ફરશે."</string>
+ <string name="accessibility_rotation_lock_off" msgid="3880436123632448930">"સ્ક્રીન ઑટોમૅટિક રીતે ફરશે."</string>
<string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"સ્ક્રીન લેન્ડસ્કેપ ઓરિએન્ટેશનમાં લૉક કરેલ છે."</string>
<string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"સ્ક્રીન પોટ્રેટ ઓરિએન્ટેશનમાં લૉક કરેલ છે."</string>
- <string name="accessibility_rotation_lock_off_changed" msgid="5772498370935088261">"સ્ક્રીન હવે આપમેળે ફરશે."</string>
+ <string name="accessibility_rotation_lock_off_changed" msgid="5772498370935088261">"સ્ક્રીન હવે ઑટોમૅટિક રીતે ફરશે."</string>
<string name="accessibility_rotation_lock_on_landscape_changed" msgid="5785739044300729592">"સ્ક્રીન હવે લેન્ડસ્કેપ ઓરિએન્ટેશનમાં લૉક કરેલ છે."</string>
<string name="accessibility_rotation_lock_on_portrait_changed" msgid="5580170829728987989">"સ્ક્રીન હવે પોટ્રેટ ઓરિએન્ટેશનમાં લૉક કરેલ છે."</string>
<string name="dessert_case" msgid="9104973640704357717">"ડેઝર્ટ કેસ"</string>
@@ -520,6 +522,8 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"પ્રોફાઇલ મૉનિટર કરી શકાય છે"</string>
<string name="vpn_footer" msgid="3457155078010607471">"નેટવર્ક મૉનિટર કરી શકાય છે"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"નેટવર્ક મૉનિટર કરવામાં આવી શકે છે"</string>
+ <!-- no translation found for quick_settings_disclosure_parental_controls (2114102871438223600) -->
+ <skip />
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"તમારી સંસ્થા આ ડિવાઇસની માલિકી ધરાવે છે અને નેટવર્ક ટ્રાફિકનું નિરીક્ષણ કરી શકે છે"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"આ ડિવાઇસ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>ની માલિકીનું છે અને નેટવર્ક ટ્રાફિકનું નિરીક્ષણ કરી શકે છે"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"આ ડિવાઇસ તમારી સંસ્થાની માલિકીનું છે અને <xliff:g id="VPN_APP">%1$s</xliff:g>થી કનેક્ટ કરેલું છે"</string>
@@ -544,6 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN અક્ષમ કરો"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN ડિસ્કનેક્ટ કરો"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"નીતિઓ જુઓ"</string>
+ <!-- no translation found for monitoring_button_view_controls (8316440345340701117) -->
+ <skip />
<string name="monitoring_description_named_management" msgid="505833016545056036">"આ ડિવાઇસ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>ની માલિકીનું છે.\n\nતમારા IT વ્યવસ્થાપક સેટિંગ, કૉર્પોરેટ ઍક્સેસ, ઍપ, તમારા ડિવાઇસ સાથે સંકળાયેલો ડેટા અને તમારા ડિવાઇસની સ્થાન માહિતીનું નિરીક્ષણ તેમજ તેને મેનેજ કરી શકે છે.\n\nવધુ માહિતી માટે, તમારા IT વ્યવસ્થાપકનો સંપર્ક કરો."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"આ ડિવાઇસ તમારી સંસ્થાની માલિકીનું છે.\n\nતમારા IT વ્યવસ્થાપક સેટિંગ, કૉર્પોરેટ ઍક્સેસ, ઍપ, તમારા ડિવાઇસ સાથે સંકળાયેલો ડેટા અને તમારા ડિવાઇસની સ્થાન માહિતીનું નિરીક્ષણ તેમજ તેને મેનેજ કરી શકે છે.\n\nવધુ માહિતી માટે, તમારા IT વ્યવસ્થાપકનો સંપર્ક કરો."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"તમારી સંસ્થાએ આ ઉપકરણ પર પ્રમાણપત્ર સત્તાધિકારી ઇન્સ્ટૉલ કર્યું છે. તમારા સુરક્ષિત નેટવર્ક ટ્રાફિકનું નિયમન થઈ શકે છે અથવા તેમાં ફેરફાર કરવામાં આવી શકે છે."</string>
@@ -567,6 +573,8 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"તમારા વ્યવસ્થાપકે નેટવર્ક લૉગિંગ ચાલુ કર્યુ છે, જે તમારા ઉપકરણ પર ટ્રાફિકનું નિરીક્ષણ કરે છે.\n\nવધુ માહિતી માટે, તમારા વ્યવસ્થાપકનો સંપર્ક કરો."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"તમે VPN કનેક્શન સેટ કરવા માટે ઍપ્લિકેશન પરવાનગી આપી.\n\nઆ ઍપ્લિકેશન ઇમેઇલ્સ, ઍપ્લિકેશનો અને વેબસાઇટ્સ સહિત તમારા ઉપકરણ અને નેટવર્ક પ્રવૃત્તિને મૉનિટર કરી શકે છે."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"તમારી કાર્ય પ્રોફાઇલનું સંચાલન <xliff:g id="ORGANIZATION">%1$s</xliff:g> દ્વારા કરવામાં આવે છે.\n\n તમારા વ્યવસ્થાપક ઇમેઇલ, ઍપ્લિકેશનો, અને વેબસાઇટો સહિતની તમારી કાર્ય નેટવર્ક પ્રવૃત્તિનું નિરીક્ષણ કરવામાં સક્ષમ છે.\n\nવધુ માહિતી માટે, તમારા વ્યવસ્થાપકનો સંપર્ક કરો.\n\nતમે VPN સાથે પણ કનેક્ટ કરેલ છે, જે તમારી નેટવર્ક પ્રવૃત્તિનું નિરીક્ષણ કરી શકે છે."</string>
+ <!-- no translation found for monitoring_description_parental_controls (8184693528917051626) -->
+ <skip />
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"તમે <xliff:g id="APPLICATION">%1$s</xliff:g> સાથે કનેક્ટ થયા છો, જે ઇમેઇલ, ઍપ્લિકેશનો અને વેબસાઇટો સહિતની તમારી નેટવર્ક પ્રવૃત્તિનું નિયમન કરી શકે છે."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"તમે <xliff:g id="APPLICATION">%1$s</xliff:g> સાથે કનેક્ટ થયાં છો, જે ઇમેઇલ્સ, ઍપ્લિકેશનો અને વેબસાઇટ્સ સહિતની તમારી વ્યક્તિગત નેટવર્ક પ્રવૃત્તિને મૉનિટર કરી શકે છે."</string>
@@ -585,7 +593,7 @@
<string name="accessibility_volume_settings" msgid="1458961116951564784">"સાઉન્ડ સેટિંગ"</string>
<string name="accessibility_volume_expand" msgid="7653070939304433603">"વિસ્તૃત કરો"</string>
<string name="accessibility_volume_collapse" msgid="2746845391013829996">"સંકુચિત કરો"</string>
- <string name="volume_odi_captions_tip" msgid="8825655463280990941">"મીડિયામાં કૅપ્શન આપમેળે ઉમેરો"</string>
+ <string name="volume_odi_captions_tip" msgid="8825655463280990941">"મીડિયામાં કૅપ્શન ઑટોમૅટિક રીતે ઉમેરો"</string>
<string name="accessibility_volume_close_odi_captions_tip" msgid="8924753283621160480">"કૅપ્શન ટિપ બંધ કરો"</string>
<string name="volume_odi_captions_content_description" msgid="4172765742046013630">"કૅપ્શન ઓવરલે"</string>
<string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ચાલુ કરો"</string>
@@ -903,11 +911,11 @@
<string name="tuner_lock_screen" msgid="2267383813241144544">"લૉક સ્ક્રીન"</string>
<string name="thermal_shutdown_title" msgid="2702966892682930264">"ફોન વધુ પડતી ગરમીને લીધે બંધ થઇ ગયો છે"</string>
<string name="thermal_shutdown_message" msgid="6142269839066172984">"તમારો ફોન હવે સામાન્યપણે કાર્ય કરી રહ્યો છે.\nવધુ માહિતી માટે ટૅપ કરો"</string>
- <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"તમારો ફોન અત્યંત ગરમ હતો, તેથી તે ઠંડો થવા આપમેળે બંધ થઇ ગયો છે. તમારો ફોન હવે સામાન્યપણે કાર્ય કરી રહ્યો છે.\n\nતમારો ફોન અત્યંત ગરમ થઇ શકે છે, જો તમે:\n • એવી ઍપ્લિકેશન વાપરતા હો જે સંસાધન સઘન રીતે વાપરતી હોય (જેમ કે ગેમિંગ, વીડિઓ, અથવા નેવિગેટ કરતી ઍપ્લિકેશનો)\n • મોટી ફાઇલો અપલોડ અથવા ડાઉનલોડ કરતા હો\n • તમારા ફોનનો ઉપયોગ ઉચ્ચ તાપમાનમાં કરતા હો"</string>
+ <string name="thermal_shutdown_dialog_message" msgid="6745684238183492031">"તમારો ફોન અત્યંત ગરમ હતો, તેથી તે ઠંડો થવા ઑટોમૅટિક રીતે બંધ થઈ ગયો છે. તમારો ફોન હવે સામાન્યપણે કાર્ય કરી રહ્યો છે.\n\nતમારો ફોન અત્યંત ગરમ થઈ શકે છે, જો તમે:\n • એવી ઍપ વાપરતા હો જે સંસાધન સઘન રીતે વાપરતી હોય (જેમ કે ગેમિંગ, વીડિયો, અથવા નેવિગેટ કરતી ઍપ)\n • મોટી ફાઇલો અપલોડ અથવા ડાઉનલોડ કરતા હો\n • તમારા ફોનનો ઉપયોગ ઉચ્ચ તાપમાનમાં કરતા હો"</string>
<string name="thermal_shutdown_dialog_help_text" msgid="6413474593462902901">"સારસંભાળના પગલાં જુઓ"</string>
<string name="high_temp_title" msgid="2218333576838496100">"ફોન ગરમ થઈ રહ્યો છે"</string>
<string name="high_temp_notif_message" msgid="1277346543068257549">"ફોન ઠંડો થાય ત્યાં સુધી અમુક સુવિધાઓ મર્યાદિત હોય છે.\nવધુ માહિતી માટે ટૅપ કરો"</string>
- <string name="high_temp_dialog_message" msgid="3793606072661253968">"તમારો ફોન આપમેળે ઠંડો થવાનો પ્રયાસ કરશે. તમે હજી પણ તમારા ફોનનો ઉપયોગ કરી શકો છો, પરંતુ તે કદાચ થોડો ધીમો ચાલે.\n\nતમારો ફોન ઠંડો થઈ જવા પર, તે સામાન્ય રીતે ચાલશે."</string>
+ <string name="high_temp_dialog_message" msgid="3793606072661253968">"તમારો ફોન ઑટોમૅટિક રીતે ઠંડો થવાનો પ્રયાસ કરશે. તમે હજી પણ તમારા ફોનનો ઉપયોગ કરી શકો છો, પરંતુ તે કદાચ થોડો ધીમો ચાલે.\n\nતમારો ફોન ઠંડો થઈ જવા પર, તે સામાન્ય રીતે ચાલશે."</string>
<string name="high_temp_dialog_help_text" msgid="7380171287943345858">"સારસંભાળના પગલાં જુઓ"</string>
<string name="high_temp_alarm_title" msgid="2359958549570161495">"ચાર્જરને અનપ્લગ કરો"</string>
<string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"આ ડિવાઇસને ચાર્જ કરવામાં કોઈ સમસ્યા છે. પાવર અડૅપ્ટર અનપ્લગ કરો અને કાળજી લેજો કદાચ કેબલ થોડો ગરમ થયો હોઈ શકે છે."</string>
@@ -1089,4 +1097,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"નવા ડિવાઇસ સાથે જોડાણ કરો"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"બિલ્ડ નંબર"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"બિલ્ડ નંબર ક્લિપબૉર્ડ પર કૉપિ કર્યો."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 3f497e750b77..9eeba1724393 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"बैटरी दो बार."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"बैटरी तीन बार."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"बैटरी पूरी है."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"कोई फ़ोन नहीं."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"फ़ोन एक बार."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"फ़ोन दो बार."</string>
@@ -522,6 +524,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"प्रोफ़ाइल को मॉनीटर किया जा सकता है"</string>
<string name="vpn_footer" msgid="3457155078010607471">"नेटवर्क को मॉनीटर किया जा सकता है"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"नेटवर्क को मॉनिटर किया जा सकता है"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"इस डिवाइस का प्रबंधन आपके अभिभावक करते हैं"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"इस डिवाइस का मालिकाना हक आपके संगठन के पास है. आपका संगठन, नेटवर्क के ट्रैफ़िक की निगरानी कर सकता है"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"इस डिवाइस का मालिकाना हक <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> के पास है. आपका संगठन, नेटवर्क के ट्रैफ़िक की निगरानी कर सकता है"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"इस डिवाइस का मालिकाना हक आपके संगठन के पास है. इस डिवाइस को <xliff:g id="VPN_APP">%1$s</xliff:g> से कनेक्ट किया गया है"</string>
@@ -546,6 +549,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN अक्षम करें"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN डिस्‍कनेक्‍ट करें"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"नीतियां देखें"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"कंट्रोल देखें"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"इस डिवाइस का मालिकाना हक <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> के पास है.\n\nआपके संगठन का आईटी एडमिन कुछ चीज़ों की निगरानी और उन्हें प्रबंधित कर सकता है, जैसे कि सेटिंग, कॉर्पोरेट ऐक्सेस, ऐप्लिकेशन, आपके डिवाइस से जुड़ा डेटा, और आपके डिवाइस की जगह की जानकारी.\n\nज़्यादा जानकारी के लिए, अपने आईटी एडमिन से संपर्क करें."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"इस डिवाइस का मालिकाना हक आपके संगठन के पास है.\n\nआपके संगठन का आईटी एडमिन कुछ चीज़ों की निगरानी और उन्हें प्रबंधित कर सकता है, जैसे कि सेटिंग, कॉर्पोरेट ऐक्सेस, ऐप्लिकेशन, आपके डिवाइस से जुड़ा डेटा, और आपके डिवाइस की जगह की जानकारी.\n\nज़्यादा जानकारी के लिए, अपने आईटी एडमिन से संपर्क करें."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"आपके संगठन ने इस डिवाइस पर एक प्रमाणपत्र अनुमति इंस्टॉल की है. आपके सुरक्षित नेटवर्क पर ट्रेफ़िक की निगरानी या उसमें बदलाव किया जा सकता है."</string>
@@ -569,6 +573,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"आपके एडमिन ने नेटवर्क लॉग करना चालू कर दिया है, जो आपके डिवाइस पर ट्रैफ़िक की निगरानी करता है.\n\nज़्यादा जानकारी के लिए अपने एडमिन से संपर्क करें."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"आपने किसी ऐप को VPN कनेक्‍शन सेट करने की अनुमति दी है.\n\nयह ऐप ईमेल, ऐप्‍स और सुरक्षित वेबसाइटों सहित आपके डिवाइस और नेटवर्क की गतिविधि की निगरानी कर सकता है."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> आपकी वर्क प्रोफ़ाइल को प्रबंधित करता है.\n\n आपका एडमिन ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है.\n\nऔर जानकारी के लिए अपने एडमिन से संपर्क करें.\n\nआप ऐसे VPN से भी कनेक्‍ट हैं, जो आपकी नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"इस डिवाइस का प्रबंधन आपके अभिभावक करते हैं. अभिभावक आपके डिवाइस से जुड़ी जानकारी देख सकते हैं और उस जानकारी को प्रबंधित कर सकते हैं. इनमें, आपके इस्तेमाल किए गए ऐप्लिकेशन की जानकारी, आपकी जगह की जानकारी, और डिवाइस के इस्तेमाल में बिताए गए समय जैसी जानकारी शामिल हैं."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"वीपीएन"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्ट हैं, जो ईमेल, ऐप्लिकेशन और वेबसाइटों सहित आपकी नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> से कनेक्‍ट हैं, जो ईमेल, ऐप्‍स और वेबसाइटों सहित आपकी व्‍यक्‍तिगत नेटवर्क गतिविधि की निगरानी कर सकता है."</string>
@@ -1091,4 +1096,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नया डिवाइस जोड़ें"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नंबर को क्लिपबोर्ड पर कॉपी किया गया."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 9958a2c65998..86523ece41c2 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Baterija dva stupca."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterija tri stupca."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Baterija je puna."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Nema telefona."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefonski signal jedan stupac."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefonski signal dva stupca."</string>
@@ -523,6 +525,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil se možda nadzire"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Mreža se možda nadzire"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Mreža se možda nadzire"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Ovim uređajem upravlja vaš roditelj"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Vaša je organizacija vlasnik ovog uređaja i može nadzirati mrežni promet"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Organizacija <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> vlasnik je ovog uređaja i može nadzirati mrežni promet"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Ovaj uređaj pripada vašoj organizaciji i povezan je s mrežom <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -547,6 +550,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Onemogući VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Prekini vezu s VPN-om"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Prikaži pravila"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Prikaz kontrola"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Ovaj uređaj pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nVaš IT administrator može nadzirati postavke, korporacijski pristup, aplikacije, podatke o uređaju i lokaciji uređaja te upravljati njima.\n\nZa više informacija obratite se IT administratoru."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Ovaj uređaj pripada vašoj organizaciji.\n\nVaš IT administrator može nadzirati postavke, korporacijski pristup, aplikacije, podatke o uređaju i lokaciji uređaja te upravljati njima.\n\nZa više informacija obratite se IT administratoru."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Vaša je organizacija instalirala izdavač certifikata na ovom uređaju. Vaš sigurni mrežni promet možda se nadzire ili modificira."</string>
@@ -570,6 +574,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Administrator je uključio mrežni zapisnik koji prati promet na vašem uređaju.\n\nViše informacija možete saznati od administratora."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Dali ste dopuštenje aplikaciji za postavljanje VPN veze.\n\nTa aplikacija može nadzirati vašu aktivnost na uređaju i mreži, uključujući e-poštu, aplikacije i web-lokacije."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Vašim radnim profilom upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nVaš administrator može nadzirati vašu mrežnu aktivnost, uključujući e-poštu, aplikacije i web-lokacije.\n\nViše informacija možete saznati od administratora.\n\nPovezani ste i s VPN-om koji može nadzirati vašu mrežnu aktivnost."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Ovim uređajem upravlja vaš roditelj. Vaš roditelj može vidjeti podatke, kao što su aplikacije koje koristite, lokacija i vrijeme upotrebe te upravljati njima."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Povezani ste s aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g> koja može nadzirati vašu aktivnost na mreži, uključujući e-poruke, aplikacije i web-lokacije."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Povezani ste s aplikacijom <xliff:g id="APPLICATION">%1$s</xliff:g> koja može nadzirati vašu osobnu aktivnost na mreži, uključujući e-poštu, aplikacije i web-lokacije."</string>
@@ -1095,4 +1100,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Upari novi uređaj"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Broj međuverzije"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Broj međuverzije kopiran je u međuspremnik."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 0159ec617bf2..32ca37d1a321 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Akkumulátor két sáv."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Akkumulátor három sáv."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Akkumulátor feltöltve."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Nincs telefon."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon egy sáv."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon két sáv."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profilját felügyelhetik"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Lehet, hogy a hálózatot figyelik"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Lehet, hogy a hálózat felügyelt"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Az eszközt a szülőd felügyeli"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Az eszköz az Ön szervezetének tulajdonában van, és lehetséges, hogy a hálózati forgalmat is figyelik"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Az eszköz a(z) <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> tulajdonában van, és lehetséges, hogy a hálózati forgalmat is figyelik"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Ez az eszköz az Ön szervezetének tulajdonában van, és össze van kapcsolva a(z) <xliff:g id="VPN_APP">%1$s</xliff:g> alkalmazással"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN letiltása"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN-kapcsolat bontása"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Házirendek megtekintése"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Vezérlők megtekintése"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Ez az eszköz a(z) <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> tulajdonában van.\n\nA rendszergazda figyelheti és kezelheti az eszköz beállításait, vállalati hozzáférését, alkalmazásait, adatait és helyadatait.\n\nHa további információra van szüksége, vegye fel a kapcsolatot a rendszergazdával."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Ez az eszköz az Ön szervezetének tulajdonában van.\n\nA rendszergazda figyelheti és kezelheti az eszköz beállításait, vállalati hozzáférését, alkalmazásait, adatait és helyadatait.\n\nHa további információra van szüksége, vegye fel a kapcsolatot a rendszergazdával."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Szervezete tanúsítványkibocsátót telepített az eszközre. Ezáltal figyelhetik és befolyásolhatják az Ön biztonságos hálózati forgalmát."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"A rendszergazda bekapcsolta az eszköz forgalmát figyelő hálózati naplózást.\n\nHa további információra van szüksége, forduljon a rendszergazdához."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Engedélyezte egy alkalmazásnak, hogy VPN-kapcsolatot létesítsen.\n\nEz az alkalmazás (az e-mailekre, alkalmazásokra és a webhelyekre is kiterjedően) figyelemmel kísérheti az Ön eszközét és hálózati tevékenységét."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Munkaprofilját a(z) <xliff:g id="ORGANIZATION">%1$s</xliff:g> kezeli.\n\nA rendszergazda figyelheti hálózati tevékenységét, köztük az e-maileket, az alkalmazásokat és a webhelyeket.\n\nHa további információra van szüksége, forduljon a rendszergazdához.\n\nVPN-hez is kapcsolódik, amely szintén figyelheti hálózati tevékenységét."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Az eszközt a szülőd felügyeli. A szülőd megtekintheti és kezelheti például a használt alkalmazásokra, a tartózkodási helyre és a képernyőidőre vonatkozó adatokat."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Ön csatlakozik a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazáshoz, amely figyelheti hálózati tevékenységét, beleértve az e-maileket, az alkalmazásokat és a webhelyeket."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Csatlakoztatta a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazást, amely figyelheti személyes hálózati tevékenységét, beleértve az e-maileket, az alkalmazásokat és a webhelyeket."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Új eszköz párosítása"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Buildszám"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Buildszám a vágólapra másolva."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 1d8019206cb5..15fbf706f9c1 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Մարտկոցի երկու գիծ:"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Մարտկոցի երեք գիծ:"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Մարտկոցը լիքն է:"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Հեռախոս չկա:"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Հեռախոսի մեկ գիծ:"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Հեռախոսի երկու գիծ:"</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Պրոֆիլը կարող է վերահսկվել"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Ցանցը կարող է վերահսկվել"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Ցանցը կարող է վերահսկվել"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Այս սարքը կառավարում է ձեր ծնողը"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Ձեր կազմակերպությունը այս սարքի սեփականատերն է և կարող է վերահսկել ցանցային թրաֆիկը"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"«<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>» կազմակերպությունը այս սարքի սեփականատերն է և կարող է վերահսկել ցանցային թրաֆիկը"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Այս սարքը պատկանում է ձեր կազմակերպությանը և միացված է <xliff:g id="VPN_APP">%1$s</xliff:g> ցանցին"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Անջատել VPN-ը"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Անջատել VPN-ը"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Դիտել քաղաքականությունները"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Դիտել կառավարման տարրերը"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Այս սարքը պատկանում է «<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>» կազմակերպությանը։\n\nՁեր ՏՏ ադմինիստրատորը կարող է վերահսկել և կառավարել կարգավորումները, կորպորատիվ ռեսուրսներից օգտվելու թույլտվությունները, հավելվածները, սարքի հետ կապված տվյալները և սարքի տեղադրության տվյալները։\n\nԼրացուցիչ տեղեկությունների համար դիմեք ձեր ՏՏ ադմինիստրատորին։"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Այս սարքը պատկանում է ձեր կազմակերպությանը։\n\nՁեր ՏՏ ադմինիստրատորը կարող է վերահսկել և կառավարել կարգավորումները, կորպորատիվ ռեսուրսներից օգտվելու թույլտվությունները, հավելվածները, սարքի հետ կապված տվյալները և սարքի տեղադրության տվյալները։\n\nԼրացուցիչ տեղեկությունների համար դիմեք ձեր ՏՏ ադմինիստրատորին։"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Ձեր կազմակերպությունը այս սարքում տեղադրել է վկայագրման կենտրոն։ Ձեր ցանցի ապահով թրաֆիկը կարող է վերահսկվել կամ փոփոխվել։"</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Ձեր ադմինիստրատորը միացրել է ցանցային իրադարձությունների գրանցումը, որը վերահսկում է ձեր սարքի թրաֆիկը։\n\nԼրացուցիչ տեղեկություններ ստանալու համար դիմեք ձեր ադմինիստրատորին։"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Ինչ-որ հավելվածի թույլ եք տվել հաստատել VPN կապակցում:\n\nԱյդ հավելվածը կարող է վերահսկել ձեր սարքի և ցանցի գործունեությունը, այդ թվում նաև էլփոստի հաշիվները, հավելվածները և կայքերը:"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Ձեր աշխատանքային պրոֆիլի կառավարիչն է <xliff:g id="ORGANIZATION">%1$s</xliff:g> կազմակերպությունը։\n\nԱդմինիստրատորը կարող է վերահսկել ձեր ցանցային գործունեությունը, այդ թվում նաև էլփոստը, հավելվածները և կայքերը։\n\nԼրացուցիչ տեղեկությունների համար դիմեք ադմինիստրատորին։\n\nԴուք կապակցված են նաև VPN ցանցին, որը կարող է վերահսկել ձեր ցանցային գործունեությունը։"</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Այս սարքը կառավարում է ձեր ծնողը։ Նա կարող է տեսնել և կառավարել որոշակի տեղեկություններ, օրինակ՝ հավելվածները, որոնք դուք օգտագործում եք, ձեր տեղադրությունը և սարքի օգտագործման ժամանակը։"</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Դուք կապակցված եք <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին, որը կարող է վերահսկել ձեր ցանցային գործունեությունը, այդ թվում նաև էլփոստի հաշիվները, հավելվածները և կայքերը:"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Դուք կապակցված եք <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին, որը կարող է վերահսկել անձնական ցանցում կատարած ձեր գործողությունները, այդ թվում նաև էլփոստի հաշիվները, հավելվածները և կայքերը:"</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Նոր սարքի զուգակցում"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Կառուցման համարը"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Կառուցման համարը պատճենվեց սեղմատախտակին։"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 9aaf2705e657..cf6a20dd7ba1 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Baterai dua batang."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterai tiga batang."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Baterai penuh."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Tidak dapat melakukan panggilan."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Ponsel satu batang."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Ponsel dua batang."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil dapat dipantau"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Jaringan mungkin dipantau"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Jaringan mungkin dipantau"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Perangkat ini dikelola oleh orang tua"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organisasi Anda memiliki perangkat ini dan mungkin memantau traffic jaringan"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> memiliki perangkat ini dan mungkin memantau traffic jaringan"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Perangkat ini milik organisasi Anda dan terhubung ke <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Nonaktifkan VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Putuskan sambungan VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Lihat Kebijakan"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Lihat kontrol"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Perangkat ini milik <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nAdmin IT Anda dapat memantau dan mengelola setelan, akses perusahaan, aplikasi, data yang terkait dengan perangkat, dan informasi lokasi perangkat.\n\nUntuk informasi selengkapnya, hubungi admin IT Anda."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Perangkat ini milik organisasi Anda.\n\nAdmin IT Anda dapat memantau dan mengelola setelan, akses perusahaan, aplikasi, data yang terkait dengan perangkat, dan informasi lokasi perangkat.\n\nUntuk informasi selengkapnya, hubungi admin IT Anda."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organisasi Anda menginstal otoritas sertifikat di perangkat ini. Traffic jaringan aman Anda mungkin dipantau atau diubah."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Admin telah mengaktifkan pencatatan log jaringan, yang memantau traffic di perangkat.\n\nUntuk informasi selengkapnya, hubungi admin."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Anda memberikan izin kepada aplikasi untuk menyiapkan sambungan VPN.\n\nAplikasi ini ini dapat memantau aktivitas perangkat dan jaringan, termasuk email, aplikasi, dan situs web."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Profil kerja dikelola oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdmin dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs web.\n\nUntuk informasi selengkapnya, hubungi admin.\n\nAnda juga tersambung ke VPN, yang dapat memantau aktivitas jaringan."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Perangkat ini dikelola oleh orang tua. Orang tua Anda dapat melihat dan mengelola informasi, seperti aplikasi yang digunakan, lokasi, dan waktu pemakaian perangkat."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Anda tersambung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan, termasuk email, aplikasi, dan situs."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Anda tersambung ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang dapat memantau aktivitas jaringan pribadi, termasuk email, aplikasi, dan situs web."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sambungkan perangkat baru"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nomor versi"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nomor versi disalin ke papan klip."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index bf49e97785c4..ca40b6f63cf5 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Tvö strik á rafhlöðu."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Þrjú strik á rafhlöðu."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Rafhlaða fullhlaðin."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Ekkert símasamband."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Styrkur símasambands er eitt strik."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Styrkur símasambands er tvö strik."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Hugsanlega er fylgst með þessu sniði"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Hugsanlega er fylgst með netinu"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Hugsanlega er fylgst með netinu"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Foreldri þitt stjórnar þessu tæki"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Fyrirtækið þitt á þetta tæki og fylgist hugsanlega með netumferð"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> á þetta tæki og fylgist hugsanlega með netumferð"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Þetta tæki tilheyrir fyrirtækinu þínu og er tengt við <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Slökkva á VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Aftengja VPN-net"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Skoða stefnur"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Skoða stýringar"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Þetta tæki tilheyrir <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nKerfisstjórinn getur fylgst með og breytt stillingum, fyrirtækjaaðgangi, forritum, gögnum sem tengjast tækinu þínu og staðsetningarupplýsingum tækisins.\n\nHafðu samband við kerfisstjórann til að fá frekari upplýsingar."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Þetta tæki tilheyrir fyrirtækinu þínu.\n\nKerfisstjórinn getur fylgst með og breytt stillingum, fyrirtækjaaðgangi, forritum, gögnum sem tengjast tækinu þínu og staðsetningarupplýsingum tækisins.\n\nHafðu samband við kerfisstjórann til að fá frekari upplýsingar."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Fyrirtækið þitt setti upp CA-vottorð á þessu tæki. Eftirlit kann að vera haft með öruggri netnotkun þinni eða henni kann að vera breytt."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Kerfisstjóri hefur kveikt á eftirliti netkerfa, sem fylgist með netumferð á tækinu þínu.\n\nHafðu samband við kerfisstjóra til að fá frekari upplýsingar."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Þú veittir forriti heimild til að koma á VPN-tengingu.\n\nÞetta forrit getur fylgst með virkni þinni í tækinu og á netinu, þar á meðal tölvupósti, forritum og vefsvæðum."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> stýrir vinnusniðinu þínu.\n\nKerfisstjórinn getur fylgst með virkni þinni á netinu, þ.m.t. tölvupósti, forritum og vefsvæðum.\n\nHafðu samband við kerfisstjórann til að fá frekari upplýsingar.\n\nÞú ert einnig með VPN-tengingu, sem getur fylgst með virkni þinni á netinu."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Foreldri þitt stjórnar þessu tæki. Foreldri þitt getur séð og stjórnað upplýsingum eins og forritunum sem þú notar, staðsetningu þinni og skjátímanum."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Þú ert með tengingu við <xliff:g id="APPLICATION">%1$s</xliff:g>, sem getur fylgst með netnotkun þinni, þ. á m. tölvupósti, forritum og vefsvæðum."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Þú ert með tengingu við <xliff:g id="APPLICATION">%1$s</xliff:g>, sem getur fylgst með persónulegri netnotkun þinni, þ. á m. tölvupósti, forritum og vefsvæðum."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Para nýtt tæki"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Útgáfunúmer smíðar"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Útgáfunúmer smíðar afritað á klippiborð."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 8e665ec31ba0..f3436e97b3e7 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Batteria: due barre."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batteria: tre barre."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batteria carica."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Nessun telefono."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefono: una barra."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefono: due barre."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Il profilo potrebbe essere monitorato"</string>
<string name="vpn_footer" msgid="3457155078010607471">"La rete potrebbe essere monitorata"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"La rete potrebbe essere monitorata"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Questo dispositivo è gestito da uno dei tuoi genitori"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Questo dispositivo appartiene alla tua organizzazione, che potrebbe monitorare il traffico di rete"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Questo dispositivo appartiene a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, che potrebbe monitorare il traffico di rete"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Questo dispositivo appartiene alla tua organizzazione ed è collegato a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Disattiva VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Scollega VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Visualizza le norme"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Visualizza controlli"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Questo dispositivo appartiene a <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nIl tuo amministratore IT può monitorare e gestire impostazioni, accesso aziendale, app, dati associati al dispositivo e informazioni sulla posizione del dispositivo.\n\nPer ulteriori informazioni, contatta il tuo amministratore IT."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Questo dispositivo appartiene alla tua organizzazione.\n\nIl tuo amministratore IT può monitorare e gestire impostazioni, accesso aziendale, app, dati associati al dispositivo e informazioni sulla posizione del dispositivo.\n\nPer ulteriori informazioni, contatta il tuo amministratore IT."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"La tua organizzazione ha installato un\'autorità di certificazione sul dispositivo. Il tuo traffico di rete protetto potrebbe essere monitorato o modificato."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"L\'amministratore ha attivato i log di rete, che consentono di monitorare il traffico sul dispositivo.\n\nPer ulteriori informazioni, contatta l\'amministratore."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Hai autorizzato l\'app a configurare una connessione VPN.\n\nQuesta app può monitorare il tuo dispositivo e l\'attività di rete, inclusi email, app e siti web."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Il tuo profilo di lavoro è gestito da <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nL\'amministratore può monitorare la tua attività di rete, inclusi siti web, email e app.\n\nPer ulteriori informazioni, contatta l\'amministratore.\n\nSei inoltre connesso a una VPN, da cui è possibile monitorare la tua attività di rete."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Questo dispositivo è gestito da uno dei tuoi genitori. Il genitore può visualizzare e gestire informazioni quali le app che usi, la tua posizione e il tuo tempo di utilizzo."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Sei collegato a <xliff:g id="APPLICATION">%1$s</xliff:g>, da cui è possibile monitorare la tua attività di rete, inclusi siti web, email e app."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Sei connesso a <xliff:g id="APPLICATION">%1$s</xliff:g>, da cui è possibile monitorare la tua attività di rete personale, inclusi email, app e siti web."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Accoppia nuovo dispositivo"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numero build copiato negli appunti."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 052b721b6eef..fc915a13ffbb 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"שני פסים של סוללה."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"שלושה פסים של סוללה."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"סוללה מלאה."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"אין טלפון."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"פס אחד של טלפון."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"שני פסים של טלפון."</string>
@@ -526,6 +528,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"ייתכן שהפרופיל נתון למעקב"</string>
<string name="vpn_footer" msgid="3457155078010607471">"ייתכן שהרשת נמצאת במעקב"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ייתכן שהרשת מנוטרת"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"מכשיר זה מנוהל על ידי ההורה שלך"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"הארגון שלך הוא הבעלים של מכשיר זה והוא עשוי לנטר את התנועה ברשת"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"הארגון <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> הוא הבעלים של מכשיר זה והוא עשוי לנטר את התנועה ברשת"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"המכשיר הזה שייך לארגון שלך, והוא מחובר ל-<xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -550,6 +553,7 @@
<string name="disable_vpn" msgid="482685974985502922">"‏השבת VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"‏נתק את ה-VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"הצג מדיניות"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"לצפייה באמצעי בקרת ההורים"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"‏המכשיר הזה שייך לארגון <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nמנהל ה-IT יכול לנטר ולנהל הגדרות, גישה ארגונית, אפליקציות, נתונים המשויכים למכשיר ומידע על מיקום המכשיר.\n\nלמידע נוסף, יש לפנות למנהל ה-IT."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"‏המכשיר הזה שייך לארגון שלך.\n\nמנהל ה-IT יכול לנטר ולנהל הגדרות, גישה ארגונית, אפליקציות, נתונים המשויכים למכשיר ומידע על מיקום המכשיר.\n\nלמידע נוסף, יש לפנות למנהל ה-IT."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"הארגון שלך התקין רשות אישורים במכשיר. ניתן לעקוב אחר התנועה ברשת המאובטחת או לשנות אותה."</string>
@@ -573,6 +577,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"מנהל המערכת הפעיל את תכונת רישום התנועה ברשת, שמנטרת את תנועת הנתונים במכשיר.\n\nלמידע נוסף, צור קשר עם מנהל המערכת."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"‏נתת לאפליקציה כלשהי הרשאה להגדיר חיבור ‏VPN‏.\n\nהאפליקציה הזו יכולה לעקוב אחר הפעילות שלך ברשת ובמכשיר, כולל הודעות אימייל, אפליקציות ואתרים."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"‏פרופיל העבודה שלך מנוהל על-ידי <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\n מנהל המערכת שלך יכול לעקוב אחרי הפעילות שלך ברשת, כולל פעילות באימייל, באפליקציות ובאתרים.\n\n למידע נוסף, צור קשר עם מנהל המערכת.\n\nבנוסף, אתה מחובר ל-VPN, שגם באמצעותו ניתן לעקוב אחרי הפעילות שלך ברשת."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"מכשיר זה מנוהל על ידי ההורה שלך. להורה שלך יש אפשרות לצפות בפרטים כמו האפליקציות שבשימוש, המיקום וזמן המסך שלך, ולנהל אותם."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"אתה מחובר לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת, כולל הודעות אימייל, אפליקציות ואתרים."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"אתה מחובר לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g>, שיכולה לעקוב אחר הפעילות שלך ברשת הפרטית, כולל הודעות אימייל, אפליקציות ואתרים."</string>
@@ -1101,4 +1106,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"התאמה של מכשיר חדש"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"‏מספר Build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"‏מספר ה-Build הועתק ללוח."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 7e64155fae63..74fd16afe655 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"電池残量:レベル2"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"電池残量:レベル3"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"電池残量:満"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"電波状態:なし"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"電波状態:レベル1"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"電波状態:レベル2"</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"プロファイルが監視されている可能性があります"</string>
<string name="vpn_footer" msgid="3457155078010607471">"ネットワークが監視されている可能性があります"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ネットワークが監視されている可能性があります"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"このデバイスは保護者によって管理されています"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"これは組織が所有するデバイスで、ネットワーク トラフィックが監視されることもあります"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"これは <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> が所有するデバイスで、ネットワーク トラフィックが監視されることもあります"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"これは組織が所有するデバイスで、<xliff:g id="VPN_APP">%1$s</xliff:g> に接続しています"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPNを無効にする"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPNを切断"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"ポリシーを見る"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"使用制限を表示"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"これは <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> が所有するデバイスです。\n\nIT 管理者が、このデバイスに関連付けられている設定、コーポレート アクセス、アプリ、データのほか、デバイスの位置情報を監視、管理できます。\n\n詳しくは、IT 管理者にお問い合わせください。"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"これは組織が所有するデバイスです。\n\nIT 管理者が、このデバイスに関連付けられている設定、コーポレート アクセス、アプリ、データのほか、デバイスの位置情報を監視、管理できます。\n\n詳しくは、IT 管理者にお問い合わせください。"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"組織によってこのデバイスに認証局がインストールされました。保護されたネットワーク トラフィックが監視、変更される場合があります。"</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"管理者がネットワーク ログを有効にしているため、このデバイスのトラフィックは監視されています。\n\n詳しくは管理者にお問い合わせください。"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"アプリにVPN接続の設定を許可しました。\n\nこのアプリはあなたのデバイスやネットワークアクティビティ(メール、アプリ、ウェブサイトなど)を監視できます。"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"この仕事用プロファイルは、<xliff:g id="ORGANIZATION">%1$s</xliff:g> により管理されています。\n\n管理者は、このプロファイルでのネットワーク アクティビティ(メール、アプリ、ウェブサイトなど)を監視できます。\n\n詳しくは管理者にお問い合わせください。\n\nまた、VPN に接続しているため、このネットワークでのあなたのネットワーク アクティビティも監視されます。"</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"このデバイスは保護者によって管理されています。使用しているアプリ、現在地、利用時間などの情報を保護者が確認、管理できます。"</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"<xliff:g id="APPLICATION">%1$s</xliff:g> に接続しています。このアプリはあなたのネットワーク アクティビティ(メール、アプリ、ウェブサイトなど)を監視できます。"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"<xliff:g id="APPLICATION">%1$s</xliff:g>に接続しています。このアプリはあなたの個人のネットワークアクティビティ(メール、アプリ、ウェブサイトなど)を監視できます。"</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"新しいデバイスとのペア設定"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ビルド番号"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ビルド番号をクリップボードにコピーしました。"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 97aea295c68d..b32937ef7c8a 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"ბატარეა ორ ზოლზე."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ბატარეა სამ ზოლზე."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ბატარეა სავსეა."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"ტელეფონი არ არის."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ტელეფონის სიგნალი ერთ ზოლზეა."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ტელეფონის სიგნალი ორ ზოლზეა."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"შესაძლოა პროფილზე ხორციელდებოდეს მონიტორინგი"</string>
<string name="vpn_footer" msgid="3457155078010607471">"შესაძლოა ქსელზე ხორციელდება მონიტორინგი"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ქსელზე შესაძლოა მონიტორინგი ხორციელდებოდეს"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ამ მოწყობილობას თქვენი მშობელი მართავს"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ამ მოწყობილობას ფლობს თქვენი ორგანიზაცია და მას ქსელის ტრაფიკის მონიტორინგი შეუძლია"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"ამ მოწყობილობას ფლობს <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> და მას ქსელის ტრაფიკის მონიტორინგი შეუძლია"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ამ მოწყობილობას ფლობს თქვენი ორგანიზაცია და ის დაკავშირებულია <xliff:g id="VPN_APP">%1$s</xliff:g>-თან"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN-ის გაუქმება"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN-ის გათიშვა"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"წესების ნახვა"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"მართვის საშუალებების ნახვა"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"ეს მოწყობილობას ფლობს <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nთქვენს IT ადმინისტრატორს შეუძლია მოწყობილობასთან დაკავშირებული პარამეტრების, კორპორაციული წვდომის, აპებისა და მონაცემების (მათ შორის, თქვენი მოწყობილობის მდებარეობის ინფორმაციის) მონიტორინგი და მართვა.\n\nდამატებითი ინფორმაციისთვის დაუკავშირდით თქვენს IT ადმინისტრატორს."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"ამ მოწყობილობას ფლობს თქვენი ორგანიზაცია.\n\nთქვენს IT ადმინისტრატორს შეუძლია მოწყობილობასთან დაკავშირებული პარამეტრების, კორპორაციული წვდომის, აპებისა და მონაცემების (მათ შორის, თქვენი მოწყობილობის მდებარეობის ინფორმაციის) მონიტორინგი და მართვა.\n\nდამატებითი ინფორმაციისთვის დაუკავშირდით თქვენს IT ადმინისტრატორს."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"თქვენმა ორგანიზაციამ ამ მოწყობილობაზე სერტიფიცირების ორგანო დააინსტალირა. თქვენი ქსელის დაცული ტრაფიკი შეიძლება შეიცვალოს, ან მასზე მონიტორინგი განხორციელდეს."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"თქვენმა ადმინისტრატორმა ქსელის ჟურნალირება ჩართო, რომელიც თქვენი მოწყობილობის ტრაფიკის მონიტორინგს ახორციელებს.\n\nდამატებითი ინფორმაციისთვის დაუკავშირდით თქვენს ადმინისტრატორს."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"თქვენ მიეცით ნებართვა აპს, დააყენოს VPN კავშირი.\n\nამ აპს შეუძლია თქვენი მოწყობილობის და ქსელის აქტივობის, მათ შორის, ელფოსტის, აპებისა და ვებსაიტების მონიტორინგი."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"თქვენს სამსახურის პროფილს მართავს <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nთქვენს ადმინისტრატორს შეუძლია თქვენი ქსელის აქტივობის (მათ შორის, ელფოსტის, აპებისა და ვებსაიტების) მონიტორინგი.\n\nდამატებითი ინფორმაციისთვის დაუკავშირდით თქვენს ადმინისტრატორს.\n\nგარდა ამისა, თქვენ დაკავშირებული ხართ VPN-თან, რომელსაც ასევე შეუძლია თქვენი ქსელის აქტივობის მონიტორინგი."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ამ მოწყობილობას თქვენი მშობელი მართავს. თქვენი მშობელი ხედავს და მართავს ისეთ ინფორმაციას, როგორიც არის თქვენ მიერ გამოყენებული აპები, თქვენი მდებარეობა და თქვენ მიერ ეკრანთან გატარებული დრო."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"თქვენ დაკავშირებული ხართ <xliff:g id="APPLICATION">%1$s</xliff:g>-თან, რომელსაც შეუძლია თქვენი ქსელის აქტივობის (მათ შორის, ელფოსტის, აპებისა და ვებსაიტების) მონიტორინგი."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"თქვენ დაუკავშირდით <xliff:g id="APPLICATION">%1$s</xliff:g>-ს, რომელსაც შეუძლია თქვენი პირადი ქსელის აქტივობის, მათ შორის, ელფოსტის, აპებისა და ვებსაიტების მონიტორინგი."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ახალი მოწყობილობის დაწყვილება"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ანაწყობის ნომერი"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ანაწყობის ნომერი დაკოპირებულია გაცვლის ბუფერში."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index a6376e37741d..c01af11d24bc 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Батарея екі баған."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Батарея үш баған."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Батарея толы."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Телефон жоқ."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Телефон бір баған."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Телефон екі баған."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Профиль бақылануы мүмкін"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Желі бақылауда болуы мүмкін"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Желі бақылауда болуы мүмкін"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Бұл құрылғыны ата-анаңыз басқарады."</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Ұйымыңыз осы құрылғыны басқарады және желі трафигін бақылауы мүмкін."</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> осы құрылғыны басқарады және желі трафигін бақылауы мүмкін."</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Бұл құрылғы ұйымыңызға тиесілі және <xliff:g id="VPN_APP">%1$s</xliff:g> қолданбасына қосылған."</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN функциясын өшіру"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN желісін ажырату"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Саясаттарды көру"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Басқару элементтерін көру"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Бұл құрылғы <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ұйымына тиесілі.\n\nӘкімші параметрлерді, корпоративтік кіру құқығын, қолданбаларды, құрылғыңызбен байланысты деректерді және құрылғыңыздың орналасқан жері туралы ақпаратты бақылай және басқара алады.\n\nҚосымша ақпарат алу үшін әкімшіге хабарласыңыз."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Бұл құрылғы ұйымыңызға тиесілі.\n\nӘкімші параметрлерді, корпоративтік кіру құқығын, қолданбаларды, құрылғыңызбен байланысты деректерді және құрылғыңыздың орналасқан жері туралы ақпаратты бақылай және басқара алады.\n\nҚосымша ақпарат алу үшін әкімшіге хабарласыңыз."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Ұйымыңыз осы құрылғыда сертификат орнатқан. Қорғалған желі трафигіңіз бақылануы немесе өзгертілуі мүмкін."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Әкімші құрылғыдағы трафикті қадағалау үшін желі журналын жүргізуді қосып қойған.\n\nТолығырақ ақпарат алу үшін әкімшімен хабарласыңыз."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Қолданбаға VPN байланысын орнату рұқсатын бердіңіз.\n\nБұл қолданба құрылғыңызды және желідегі белсенділігіңізді, соның ішінде электрондық пошталарды, қолданбаларды және веб-сайттарды бақылай алады."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Жұмыс профиліңізді <xliff:g id="ORGANIZATION">%1$s</xliff:g> басқарады.\n\nӘкімші желідегі белсенділігіңізді, соның ішінде электрондық пошталарды, қолданбаларды және вебсайттарды бақылай алады.\n\nҚосымша ақпарат алу үшін әкімшіге хабарласыңыз.\n\nСондай-ақ сіз желідегі белсенділігіңізді бақылай алатын VPN желісіне қосылғансыз."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Бұл құрылғыны ата-анаңыз басқарады. Ата-анаңыз сіз пайдаланатын қолданбалар, геодерегіңіз және пайдалану уақытыңыз сияқты ақпаратты көре және басқара алады."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Сіз желідегі белсенділігіңізді, соның ішінде электрондық хабарларды, қолданбаларды және веб-сайттарды бақылай алатын <xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына қосылғансыз."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Сіз жеке желідегі белсенділігіңізді, соның ішінде электрондық пошталарды, қолданбаларды және веб-сайттарды бақылай алатын <xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына қосылғансыз."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Жаңа құрылғыны жұптау"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Құрама нөмірі"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Құрама нөмірі буферге көшірілді."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index b8d2fa8a04ba..652bf25b54bf 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -28,15 +28,15 @@
<string name="battery_low_percent_format" msgid="4276661262843170964">"នៅ​សល់ <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
<string name="battery_low_percent_format_hybrid" msgid="3985614339605686167">"នៅសល់ <xliff:g id="PERCENTAGE">%1$s</xliff:g> អាច​ប្រើ​បាន​ប្រហែល <xliff:g id="TIME">%2$s</xliff:g> ទៀត​ផ្អែកលើ​ការប្រើប្រាស់​របស់អ្នក"</string>
<string name="battery_low_percent_format_hybrid_short" msgid="5917433188456218857">"នៅសល់ <xliff:g id="PERCENTAGE">%1$s</xliff:g> អាច​ប្រើ​បាន​ប្រហែល <xliff:g id="TIME">%2$s</xliff:g> ទៀត"</string>
- <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"នៅ​សល់ <xliff:g id="PERCENTAGE">%s</xliff:g> ។ កម្មវិធី​សន្សំ​ថ្ម​បានបើក។"</string>
+ <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"នៅ​សល់ <xliff:g id="PERCENTAGE">%s</xliff:g>។ មុខងារ​សន្សំ​ថ្មត្រូវបានបើក។"</string>
<string name="invalid_charger" msgid="4370074072117767416">"មិន​អាច​សាក​តាម USB បានទេ។ សូម​ប្រើ​ឆ្នាំង​សាក​ដែល​ភ្ជាប់​មក​ជាមួយ​ឧបករណ៍​របស់អ្នក។"</string>
<string name="invalid_charger_title" msgid="938685362320735167">"មិន​អាច​សាក​តាម USB បានទេ"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"សូមប្រើ​ឆ្នាំង​សាក​ដែល​ភ្ជាប់​មក​ជាមួយ​ឧបករណ៍​របស់អ្នក"</string>
<string name="battery_low_why" msgid="2056750982959359863">"ការកំណត់"</string>
- <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"បើក​កម្មវិធី​សន្សំ​ថ្ម?"</string>
- <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"អំពី​កម្មវិធីសន្សំថ្ម"</string>
+ <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"បើក​មុខងារ​សន្សំ​ថ្ម?"</string>
+ <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"អំពី​មុខងារ​សន្សំ​ថ្ម"</string>
<string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"បើក"</string>
- <string name="battery_saver_start_action" msgid="4553256017945469937">"បើក​កម្មវិធី​សន្សំ​ថ្ម​"</string>
+ <string name="battery_saver_start_action" msgid="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>
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"ថ្ម​ពីរ​កាំ។"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ថ្ម​ទាំង​បី​​កាំ​។"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ថ្ម​ពេញ​ហើយ។"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"គ្មាន​ទូរស័ព្ទ។"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"សេវា​ទូរស័ព្ទ​មួយ​កាំ។"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"សេវា​ទូរស័ព្ទ​ពីរ​កាំ។"</string>
@@ -498,9 +500,9 @@
<string name="user_remove_user_title" msgid="9124124694835811874">"យកអ្នកប្រើចេញ?"</string>
<string name="user_remove_user_message" msgid="6702834122128031833">"កម្មវិធី និងទិន្នន័យទាំងអស់របស់អ្នកប្រើនេះនឹងត្រូវបានលុប។"</string>
<string name="user_remove_user_remove" msgid="8387386066949061256">"យកចេញ"</string>
- <string name="battery_saver_notification_title" msgid="8419266546034372562">"កម្មវិធីសន្សំថ្មបានបើក"</string>
+ <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="battery_saver_notification_action_text" msgid="6022091913807026887">"បិទ​មុខងារ​សន្សំ​ថ្ម"</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>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"ចាប់ផ្ដើម​ថត ឬបញ្ជូន​មែនទេ?"</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"ប្រវត្តិរូបអាចត្រូវបានតាមដាន"</string>
<string name="vpn_footer" msgid="3457155078010607471">"បណ្ដាញ​អាច​ត្រូវ​បាន​ត្រួតពិនិត្យ"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"បណ្ដាញអាចត្រូវបានត្រួតពិនិត្យ"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ឧបករណ៍​នេះ​ស្ថិត​ក្រោម​ការ​គ្រប់គ្រង​របស់មាតាបិតាអ្នក"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ស្ថាប័ន​របស់អ្នក​ជាម្ចាស់​ឧបករណ៍​នេះ ហើយ​អាចនឹង​តាមដាន​ចរាចរណ៍បណ្តាញ"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ជាម្ចាស់​ឧបករណ៍​នេះ ហើយ​អាចនឹង​តាមដាន​ចរាចរណ៍​បណ្តាញ"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ឧបករណ៍​នេះគឺជា​កម្មសិទ្ធិរបស់​ស្ថាប័នអ្នក និងត្រូវបានភ្ជាប់ទៅ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"បិទ VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"ផ្ដាច់ VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"មើល​គោលការណ៍"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"មើលការគ្រប់គ្រង"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"ឧបករណ៍នេះ​ជាគឺកម្មសិទ្ធិ​របស់ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>។\n\nអ្នកគ្រប់គ្រង​ផ្នែកព័ត៌មានវិទ្យា​របស់អ្នក​អាចតាមដាន និងគ្រប់គ្រង​ការកំណត់ ការចូលប្រើជាលក្ខណៈក្រុមហ៊ុន កម្មវិធី ទិន្នន័យដែលពាក់ព័ន្ធ​នឹង​ឧបករណ៍​របស់អ្នក និងព័ត៌មាន​ទីតាំង​របស់​ឧបករណ៍​អ្នក។\n\nសម្រាប់​ព័ត៌មាន​បន្ថែម សូម​ទាក់ទង​អ្នកគ្រប់គ្រង​ផ្នែកព័ត៌មានវិទ្យា​របស់អ្នក។"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"ឧបករណ៍នេះ​គឺជាកម្មសិទ្ធិ​របស់ស្ថាប័នអ្នក។\n\nអ្នកគ្រប់គ្រង​ផ្នែកព័ត៌មានវិទ្យា​របស់អ្នក​អាចតាមដាន និងគ្រប់គ្រង​ការកំណត់ ការចូលប្រើជាលក្ខណៈក្រុមហ៊ុន កម្មវិធី ទិន្នន័យដែលពាក់ព័ន្ធ​នឹង​ឧបករណ៍​របស់អ្នក និងព័ត៌មាន​ទីតាំង​របស់ឧបករណ៍​អ្នក។\n\nសម្រាប់​ព័ត៌មាន​បន្ថែម សូម​ទាក់ទង​អ្នកគ្រប់គ្រង​ផ្នែកព័ត៌មានវិទ្យា​របស់អ្នក។"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ស្ថាប័ន​របស់អ្នក​បានដំឡើង​អាជ្ញាធរវិញ្ញាបនបត្រនៅលើ​ឧបករណ៍​នេះ។ ចរាចរណ៍​បណ្តាញដែលមាន​សុវត្ថិភាព​របស់អ្នក​អាច​ត្រូវបាន​តាមដាន ឬ​កែសម្រួល។"</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"អ្នក​គ្រប់គ្រង​របស់អ្នក​បាន​បើក​ការ​ធ្វើ​កំណត់ហេតុ​បណ្តាញ​ ដែល​នឹង​តាមដាន​ចរាចរណ៍​នៅលើ​ឧបករណ៍​របស់អ្នក។\n\nសម្រាប់​ព័ត៌មាន​បន្ថែម​ សូម​ទាក់ទង​អ្នក​គ្រប់គ្រង​របស់អ្នក។"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"អ្នកបានអនុញ្ញាតឲ្យកម្មវិធីដំឡើងការតភ្ជាប់ VPN។\n\nកម្មវិធីនេះអាចឃ្លាំមើលឧបករណ៍ និងសកម្មភាពបណ្តាញរបស់អ្នក រាប់បញ្ចូលទាំងអ៊ីមែល កម្មវិធី និងគេហទំព័រ។"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"កម្រង​ព័ត៌មាន​ការងារ​របស់អ្នក​ស្ថិត​ក្រោម​ការ​គ្រប់គ្រង​របស់ <xliff:g id="ORGANIZATION">%1$s</xliff:g> ។\n\nអ្នក​គ្រប់គ្រង​របស់អ្នក​មាន​លទ្ធភាព​តាមដាន​សកម្មភាព​នៅលើ​បណ្តាញ​របស់អ្នក រួមទាំងអ៊ីមែល កម្មវិធី និងគេហទំព័រ។\n\nសម្រាប់​ព័ត៌មាន​បន្ថែម​ សូម​ទាក់ទង​អ្នក​គ្រប់គ្រង​របស់អ្នក។\n\nអ្នក​ក៏​ត្រូវ​បាន​ភ្ជាប់​ទៅ VPN ដែល​អាច​តាមដាន​សកម្មភាព​នៅលើ​បណ្តាញ​របស់អ្នក​ផងដែរ។"</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ឧបករណ៍​នេះ​ស្ថិត​ក្រោម​ការ​គ្រប់គ្រង​របស់មាតាបិតាអ្នក។ មាតាបិតារបស់អ្នកអាចមើល និងគ្រប់គ្រងព័ត៌មាន​ដូចជា កម្មវិធីដែលអ្នកប្រើ ទីតាំងរបស់អ្នក និងរយៈពេលប្រើប្រាស់ឧបករណ៍របស់អ្នកជាដើម។"</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"អ្នកត្រូវ​បាន​តភ្ជាប់ទៅ <xliff:g id="APPLICATION">%1$s</xliff:g> ដែល​អាច​តាមដាន​សកម្មភាព​បណ្តាញ​របស់អ្នក រួមទាំង​អ៊ីមែល កម្មវិធី និង​គេហទំព័រ​ផងដែរ។"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"អ្នកត្រូវបានតភ្ជាប់ទៅ <xliff:g id="APPLICATION">%1$s</xliff:g> ដែលអាចឃ្លាំមើលសកម្មភាពបណ្តាញរបស់អ្នក រាប់បញ្ចូលទាំងអ៊ីមែល កម្មវិធី និងគេហទំព័រ។"</string>
@@ -774,7 +779,7 @@
<item quantity="one">%d នាទី</item>
</plurals>
<string name="battery_panel_title" msgid="5931157246673665963">"ការប្រើប្រាស់ថ្ម"</string>
- <string name="battery_detail_charging_summary" msgid="8821202155297559706">"កម្មវិធីសន្សំថ្មមិនអាចប្រើបានអំឡុងពេលសាកថ្មទេ"</string>
+ <string name="battery_detail_charging_summary" msgid="8821202155297559706">"មិនអាចប្រើមុខងារ​សន្សំ​ថ្មបានទេក្នុងអំឡុងពេលសាកថ្ម"</string>
<string name="battery_detail_switch_title" msgid="6940976502957380405">"មុខងារ​សន្សំ​ថ្ម"</string>
<string name="battery_detail_switch_summary" msgid="3668748557848025990">"កាត់បន្ថយប្រតិបត្តិការ និងទិន្នន័យផ្ទៃខាងក្រោយ"</string>
<string name="keyboard_key_button_template" msgid="8005673627272051429">"ប៊ូតុង <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -962,11 +967,11 @@
<string name="slice_permission_checkbox" msgid="4242888137592298523">"អនុញ្ញាត​ឱ្យ <xliff:g id="APP">%1$s</xliff:g> បង្ហាញ​ស្ថិតិ​ប្រើប្រាស់​ពី​កម្មវិធី​នានា"</string>
<string name="slice_permission_allow" msgid="6340449521277951123">"អនុញ្ញាត"</string>
<string name="slice_permission_deny" msgid="6870256451658176895">"បដិសេធ"</string>
- <string name="auto_saver_title" msgid="6873691178754086596">"ចុច​ដើម្បី​កំណត់​កាលវិភាគ​កម្មវិធី​សន្សំ​ថ្ម"</string>
+ <string name="auto_saver_title" msgid="6873691178754086596">"ចុច​ដើម្បី​កំណត់​កាលវិភាគ​មុខងារ​សន្សំ​ថ្ម"</string>
<string name="auto_saver_text" msgid="3214960308353838764">"បើក​នៅពេល​ថ្ម​ទំនងជា​អស់"</string>
<string name="no_auto_saver_action" msgid="7467924389609773835">"ទេ អរគុណ"</string>
- <string name="auto_saver_enabled_title" msgid="4294726198280286333">"កាលវិភាគ​កម្មវិធី​សន្សំ​ថ្ម​បាន​បើក​ហើយ"</string>
- <string name="auto_saver_enabled_text" msgid="7889491183116752719">"កម្មវិធី​សន្សំ​ថ្ម​នឹង​បើក​ដោយ​ស្វ័យ​ប្រវត្តិ​ នៅពេល​ថ្ម​នៅ​សល់​តិច​ជាង <xliff:g id="PERCENTAGE">%d</xliff:g>%% ។"</string>
+ <string name="auto_saver_enabled_title" msgid="4294726198280286333">"កាលវិភាគ​មុខងារ​សន្សំ​ថ្មបាន​បើក​ហើយ"</string>
+ <string name="auto_saver_enabled_text" msgid="7889491183116752719">"មុខងារ​សន្សំ​ថ្មនឹង​បើក​ដោយ​ស្វ័យ​ប្រវត្តិ​ នៅពេល​ថ្ម​នៅ​សល់​តិច​ជាង <xliff:g id="PERCENTAGE">%d</xliff:g>%%។"</string>
<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>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ផ្គូផ្គង​ឧបករណ៍ថ្មី"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"លេខ​កំណែបង្កើត"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"បានចម្លងលេខ​កំណែបង្កើតទៅឃ្លីបបត។"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 5c502acc1e50..aa6c34ed4806 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"ಬ್ಯಾಟರಿ ಎರಡು ಪಟ್ಟಿಗಳು."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ಬ್ಯಾಟರಿ ಮೂರು ಪಟ್ಟಿಗಳು."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ಬ್ಯಾಟರಿ ಭರ್ತಿಯಾಗಿದೆ."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"ಯಾವುದೇ ಫೋನ್ ಇಲ್ಲ."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ಪೋನ್ ಒಂದು ಪಟ್ಟಿ."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ಫೋನ್ ಎರಡು ಪಟ್ಟಿಗಳು."</string>
@@ -520,6 +522,8 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"ಪ್ರೊಫೈಲ್ ಅನ್ನು ಪರಿವೀಕ್ಷಿಸಬಹುದಾಗಿದೆ"</string>
<string name="vpn_footer" msgid="3457155078010607471">"ನೆಟ್‌ವರ್ಕ್ ಅನ್ನು ವೀಕ್ಷಿಸಬಹುದಾಗಿ"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ನೆಟ್‌ವರ್ಕ್ ಅನ್ನು ವೀಕ್ಷಿಸಬಹುದಾಗಿರುತ್ತದೆ"</string>
+ <!-- no translation found for quick_settings_disclosure_parental_controls (2114102871438223600) -->
+ <skip />
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಈ ಸಾಧನದ ಮಾಲೀಕತ್ವವನ್ನು ಹೊಂದಿದೆ ಮತ್ತು ಅದು ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್‌ನ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ಈ ಸಾಧನದ ಮಾಲೀಕತ್ವವನ್ನು ಹೊಂದಿದೆ ಮತ್ತು ಅದು ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್‌ನ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ಈ ಸಾಧನವು ನಿಮ್ಮ ಸಂಸ್ಥೆಗೆ ಸೇರಿದೆ ಮತ್ತು <xliff:g id="VPN_APP">%1$s</xliff:g> ಗೆ ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
@@ -544,6 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN ಸಂಪರ್ಕಕಡಿತಗೊಳಿಸಿ"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"ಕಾರ್ಯನೀತಿಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
+ <!-- no translation found for monitoring_button_view_controls (8316440345340701117) -->
+ <skip />
<string name="monitoring_description_named_management" msgid="505833016545056036">"ಈ ಸಾಧನವು <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ಗೆ ಸೇರಿದೆ.\n\nಸೆಟ್ಟಿಂಗ್‌ಗಳು, ಕಾರ್ಪೊರೇಟ್ ಪ್ರವೇಶ, ಆ್ಯಪ್‌ಗಳು, ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಡೇಟಾ ಮತ್ತು ನಿಮ್ಮ ಸಾಧನದ ಸ್ಥಳದ ಮಾಹಿತಿಯನ್ನು ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು ಮತ್ತು ನಿರ್ವಹಿಸಬಹುದು.\n\nಹೆಚ್ಚಿನ ಮಾಹಿತಿಗಾಗಿ ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"ಈ ಸಾಧನವು ನಿಮ್ಮ ಸಂಸ್ಥೆಗೆ ಸೇರಿದೆ.\n\nಸೆಟ್ಟಿಂಗ್‌ಗಳು, ಕಾರ್ಪೊರೇಟ್ ಪ್ರವೇಶ, ಆ್ಯಪ್‌ಗಳು, ನಿಮ್ಮ ಸಾಧನಕ್ಕೆ ಸಂಬಂಧಿಸಿದ ಡೇಟಾ ಮತ್ತು ನಿಮ್ಮ ಸಾಧನದ ಸ್ಥಳದ ಮಾಹಿತಿಯನ್ನು ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು ಮತ್ತು ನಿರ್ವಹಿಸಬಹುದು.\n\nಹೆಚ್ಚಿನ ಮಾಹಿತಿಗಾಗಿ ನಿಮ್ಮ IT ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ನಿಮ್ಮ ಸಂಸ್ಥೆಯು ಈ ಸಾಧನದಲ್ಲಿ ಪ್ರಮಾಣಪತ್ರ ಅಂಗೀಕಾರವನ್ನು ಸ್ಥಾಪಿಸಿದೆ. ನಿಮ್ಮ ಸುರಕ್ಷಿತ ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು ಅಥವಾ ಮಾರ್ಪಡಿಸಬಹುದು."</string>
@@ -567,6 +573,8 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ನೆಟ್‌ವರ್ಕ್ ಲಾಗಿಂಗ್ ಆನ್ ಮಾಡಿದ್ದಾರೆ. ಇದು ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿನ ಟ್ರಾಫಿಕ್ ಮೇಲೆ ನಿಗಾ ಇರಿಸುತ್ತದೆ.\n\nಹೆಚ್ಚಿನ ಮಾಹಿತಿಗೆ ನಿಮ್ಮ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"ನೀವು VPN ಸಂಪರ್ಕ ಹೊಂದಿಸಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿ ನೀಡಿರುವಿರಿ.\n\nಈ ಅಪ್ಲಿಕೇಶನ್ ಇಮೇಲ್‌ಗಳು, ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ವೆಬ್‌ಸೈಟ್‌ಗಳನ್ನು ಒಳಗೊಂಡಂತೆ ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್ ಚಟುವಟಿಕೆಯ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಅನ್ನು <xliff:g id="ORGANIZATION">%1$s</xliff:g> ನಿರ್ವಹಿಸುತ್ತಿದೆ.\n\nಇಮೇಲ್‌ಗಳು, ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ವೆಬ್‌ಸೈಟ್‌ಗಳೂ ಸೇರಿದಂತೆ ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್‌ ಚಟುವಟಿಕೆಯ ಮೇಲೆ ನಿಮ್ಮ ನಿರ್ವಾಹಕರು ನಿಗಾ ಇರಿಸಬಲ್ಲರು.\n\nಹೆಚ್ಚಿನ ಮಾಹಿತಿಗಾಗಿ, ನಿಮ್ಮ ನಿರ್ವಾಹಕರನ್ನು ಸಂಪರ್ಕಿಸಿ.\n\nಅಲ್ಲದೇ, ನಿಮ್ಮ ನೆಟ್‌ವರ್ಕ್‌ ಚಟುವಟಿಕೆಯ ನಿಗಾ ವಹಿಸುವ VPN ಗೂ ಸಹ ನೀವು ಸಂಪರ್ಕಗೊಂಡಿರುವಿರಿ."</string>
+ <!-- no translation found for monitoring_description_parental_controls (8184693528917051626) -->
+ <skip />
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"ನೀವು <xliff:g id="APPLICATION">%1$s</xliff:g> ಗೆ ಸಂಪರ್ಕಗೊಂಡಿರುವಿರಿ. ಇದು ನಿಮ್ಮ ಇಮೇಲ್‌ಗಳು, ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ವೆಬ್‌ಸೈಟ್‌ಗಳೂ ಸೇರಿದಂತೆ ನೆಟ್‌ವರ್ಕ್ ಚಟುವಟಿಕೆಯನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದು."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"ನೀವು ಇಮೇಲ್‌ಗಳು, ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ವೆಬ್‌ಸೈಟ್‌ಗಳು ಸೇರಿದಂತೆ ನಿಮ್ಮ ವೈಯಕ್ತಿಕ ನೆಟ್‌ವರ್ಕ್ ಚಟುವಟಿಕೆಯ ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಬಹುದಾದ <xliff:g id="APPLICATION">%1$s</xliff:g> ಗೆ ಸಂಪರ್ಕಗೊಂಡಿರುವಿರಿ."</string>
@@ -1089,4 +1097,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ಹೊಸ ಸಾಧನವನ್ನು ಜೋಡಿಸಿ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ಬಿಲ್ಡ್ ಸಂಖ್ಯೆ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ಬಿಲ್ಡ್ ಸಂಖ್ಯೆಯನ್ನು ಕ್ಲಿಪ್‌ಬೋರ್ಡ್‌ನಲ್ಲಿ ನಕಲಿಸಲಾಗಿದೆ."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index cef515827b7d..38648d0f5198 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"배터리 막대가 두 개입니다."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"배터리 막대가 세 개입니다."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"배터리 충전이 완료되었습니다."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"휴대전화의 신호가 없습니다."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"휴대전화 신호 막대가 하나입니다."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"휴대전화 신호 막대가 두 개입니다."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"프로필이 모니터링될 수 있음"</string>
<string name="vpn_footer" msgid="3457155078010607471">"네트워크가 모니터링될 수 있음"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"네트워크가 모니터링될 수 있음"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"부모님이 관리하는 기기입니다."</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"내 조직에서 이 기기를 소유하며 네트워크 트래픽을 모니터링할 수 있습니다."</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>에서 이 기기를 소유하며 네트워크 트래픽을 모니터링할 수 있습니다."</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"내 조직에 속한 기기이며 <xliff:g id="VPN_APP">%1$s</xliff:g>에 연결되었습니다."</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN 사용 중지"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN 연결 해제"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"정책 보기"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"제어 기능 보기"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>에 속한 기기입니다.\n\nIT 관리자가 설정, 기업 액세스, 앱, 기기와 연결된 데이터, 기기 위치 정보를 모니터링 및 관리할 수 있습니다.\n\n자세한 정보를 확인하려면 IT 관리자에게 문의하세요."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"내 조직에 속한 기기입니다.\n\nIT 관리자가 설정, 기업 액세스, 앱, 기기와 연결된 데이터, 기기 위치 정보를 모니터링 및 관리할 수 있습니다.\n\n자세한 정보를 확인하려면 IT 관리자에게 문의하세요."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"조직에서 이 기기에 인증기관을 설치했습니다. 보안 네트워크 트래픽을 모니터링 또는 수정할 수 있습니다."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"관리자가 기기에서 발생하는 트래픽을 모니터링하는 네트워크 로깅을 사용 설정했습니다.\n\n자세한 정보는 관리자에게 문의하세요."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"VPN 연결을 설정할 수 있는 권한을 앱에 부여했습니다.\n\n이 앱에서 이메일, 앱, 웹사이트와 같은 내 네트워크 활동 및 기기를 모니터링할 수 있습니다."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g>에서 직장 프로필을 관리합니다.\n\n관리자가 이메일, 앱, 웹사이트를 비롯한 네트워크 활동을 모니터링할 수 있습니다.\n\n자세한 정보는 관리자에게 문의하세요.\n\n또한 VPN에 연결되어 있으며, VPN에서 네트워크 활동을 모니터링할 수 있습니다."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"부모님이 관리하는 기기입니다. 부모님이 내가 사용하는 앱, 위치, 기기 사용 시간과 같은 정보를 보고 관리할 수 있습니다."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"<xliff:g id="APPLICATION">%1$s</xliff:g>에 연결되었습니다. 이 앱은 이메일, 앱, 웹사이트와 같은 내 네트워크 활동을 모니터링할 수 있습니다."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"<xliff:g id="APPLICATION">%1$s</xliff:g>에 연결되었습니다. 이 앱은 이메일, 앱, 웹사이트와 같은 내 네트워크 활동을 모니터링할 수 있습니다."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"새 기기와 페어링"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"빌드 번호"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"빌드 번호가 클립보드에 복사되었습니다."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 572c3e7944c8..2a4e077046f7 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Эки таякча батарея."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Үч таякча батарея."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Батарея толук."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Телефон сигналы жок."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Телефон сигналы бир таякча."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Телефон сигналы эки таякча."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Профилди көзөмөлдөсө болот"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Тармак көзөмөлдөнүшү мүмкүн"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Тармак көзөмөлдөнүшү мүмкүн"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Бул түзмөктү ата-энең башкарат"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Бул түзмөк уюмуңузга таандык. Уюмуңуз тармактын трафигин көзөмөлдөй алат"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Бул түзмөк <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> уюмуна таандык. Уюм тармактын трафигин көзөмөлдөй алат"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Бул түзмөк уюмуңузга таандык жана <xliff:g id="VPN_APP">%1$s</xliff:g> колдонмосуна туташтырылган"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN\'ди өчүрүү"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN\'ди ажыратуу"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Саясаттарды карап көрүү"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Башкаруу элементтерин көрүү"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Бул түзмөк <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> уюмуна таандык.\n\nIT администраторуңуз жөндөөлөрдү, корпоративдик мүмкүнчүлүктү, колдонмолорду, түзмөгүңүзгө байланыштуу дайын-даректерди жана түзмөгүңүздүн жайгашкан жери тууралуу маалыматты көзөмөлдөп жана башкара алат.\n\nТолугураак маалымат алуу үчүн, IT администраторуңузга кайрылыңыз."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Бул түзмөк уюмуңузга таандык.\n\nIT администраторуңуз жөндөөлөрдү, корпоративдик мүмкүнчүлүктү, колдонмолорду, түзмөгүңүзгө байланыштуу дайын-даректерди жана түзмөгүңүздүн жайгашкан жери тууралуу маалыматты көзөмөлдөп жана башкара алат.\n\nТолугураак маалымат алуу үчүн, IT администраторуңузга кайрылыңыз."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Ишканаңыз бул түзмөккө тастыктоочу борборду орнотту. Коопсуз тармагыңыздын трафиги көзөмөлдөнүп же өзгөртүлүшү мүмкүн."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Администраторуңуз тармактын таржымалын алууну иштетти, андыктан түзмөгүңүздөгү трафик көзөмөлгө алынды.\n\nКеңири маалымат алуу үчүн администраторуңузга кайрылыңыз."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Колдонмого VPN туташуусун орнотууга уруксат бердиңиз.\n\nБул колдонмо түзмөгүңүздү жана электрондук почталар, колдонмолор жана вебсайттар сыяктуу тармактагы аракеттериңизди көзөмөлдөй алат."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Жумуш профилиңизди <xliff:g id="ORGANIZATION">%1$s</xliff:g> башкарат.\n\nАдминистраторуңуздун тармактагы аракетиңизди, анын ичинде электрондук почталар, колдонмолор жана вебсайттарды көзөмөлдөө мүмкүнчүлүгү бар.\n\nКөбүрөөк маалымат үчүн, администраторуңузга кайрылыңыз.\n\nСиз тармактагы жеке аракетиңизди көзөмөлдөй турган VPN\'ге да туташкансыз."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Бул түзмөктү ата-энең башкарат. Ата-энең сен иштеткен колдонмолорду, кайда жүргөнүңдү жана түзмөктү канча убакыт колдонгонуңду көрүп, башкарып турат."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Электрондук почта, колдонмолор жана вебсайттар сыяктуу тармактык аракеттерди көзөмөлдөй турган <xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосуна туташып турасыз."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Электрондук почта, колдонмолор жана вебсайттар сыяктуу тармактагы жеке аракеттериңизди көзөмөлдөй турган <xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосуна туташып турасыз."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Жаңы түзмөктү жупташтыруу"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Курама номери"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Курама номери алмашуу буферине көчүрүлдү."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 1cc1b4e4b6df..93ecff09d6c4 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -182,6 +182,7 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"ແບັດເຕີຣີສອງຂີດ."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ແບັດເຕີຣີສາມຂີດ."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ແບັດເຕີຣີເຕັມ."</string>
+ <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ບໍ່ຮູ້ເປີເຊັນແບັດເຕີຣີ."</string>
<string name="accessibility_no_phone" msgid="8828412144430247025">"ບໍ່ມີໂທລະສັບ."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ສັນຍານນຶ່ງຂີດ."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ສັນຍານສອງຂີດ."</string>
@@ -520,6 +521,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"ໂປຣ​ໄຟລ໌​ອາດ​ຖືກ​ເຝົ້າ​ຕິດ​ຕາມ​ຢູ່"</string>
<string name="vpn_footer" msgid="3457155078010607471">"​ເຄືອ​ຂ່າຍ​ອາດ​ມີ​ການ​ເຝົ້າ​ຕິດ​ຕາມ"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ການນຳໃຊ້ເຄືອຂ່າຍອາດມີການກວດສອບຕິດຕາມ"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ອຸປະກອນນີ້ແມ່ນຈັດການໂດຍພໍ່ແມ່ຂອງທ່ານ"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ອົງການຂອງທ່ານເປັນເຈົ້າຂອງອຸປະກອນນີ້ ແລະ ສາມາດຕິດຕາມທຣາບຟິກເຄືອຂ່າຍໄດ້"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ເປັນເຈົ້າຂອງອຸປະກອນນີ້ ແລະ ສາມາດຕິດຕາມທຣາບຟິກເຄືອຂ່າຍໄດ້"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ອຸປະກອນນີ້ເປັນຂອງອົງການທ່ານ ແລະ ເຊື່ອມຕໍ່ຫາ <xliff:g id="VPN_APP">%1$s</xliff:g> ແລ້ວ"</string>
@@ -544,6 +546,7 @@
<string name="disable_vpn" msgid="482685974985502922">"ປິດ​ການ​ໃຊ້ VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"ຕັດ​ການ​ເຊື່ອມ​ຕໍ່ VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"ເບິ່ງນະໂຍບາຍ"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"ເບິ່ງການຄວບຄຸມ"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"ອຸປະກອນນີ້ເປັນຂອງ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nຜູ້ເບິ່ງແຍງໄອທີຂອງທ່ານສາມາດເຝົ້າຕິດຕາມ ແລະ ຈັດການການຕັ້ງຄ່າ, ສິດເຂົ້າເຖິງອົງກອນ, ແອັບ, ຂໍ້ມູນທີ່ເຊື່ອມໂຍງກັບອຸປະກອນຂອງທ່ານໄດ້.\n\nສຳລັບຂໍ້ມູນເພີ່ມເຕີມ, ກະລຸນາຕິດຕໍ່ຜູ້ເບິ່ງແຍງໄອທີຂອງທ່ານ."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"ອຸປະກອນນີ້ເປັນຂອງອົງການທ່ານ.\n\nຜູ້ເບິ່ງແຍງໄອທີຂອງທ່ານສາມາດເຝົ້າຕິດຕາມ ແລະ ຈັດການການຕັ້ງຄ່າ, ສິດເຂົ້າເຖິງອົງກອນ, ແອັບ, ຂໍ້ມູນທີ່ເຊື່ອມໂຍງກັບອຸປະກອນຂອງທ່ານໄດ້.\n\nສຳລັບຂໍ້ມູນເພີ່ມເຕີມ, ກະລຸນາຕິດຕໍ່ຜູ້ເບິ່ງແຍງໄອທີຂອງທ່ານ."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ອົງກອນຂອງທ່ານຕິດຕັ້ງອຳນາດໃບຮັບຮອງໄວ້ໃນອຸປະກອນນີ້. ທຣາບຟິກເຄືອຂ່າຍທີ່ເຂົ້າລະຫັດໄວ້ຂອງທ່ານອາດຖືກຕິດຕາມ ຫຼື ແກ້ໄຂໄດ້."</string>
@@ -567,6 +570,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Your admin has turned on network logging, which monitors traffic on your device.\n\nFor more information, contact your admin."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"ທ່ານໄດ້ອະນຸຍາດໃຫ້ແອັບຕັ້ງການເຊື່ອມຕໍ່ VPN.\n\nແອັບນີ້ສາມາດຕິດຕາມການເຄື່ອນໄຫວຂອງອຸປະກອນ ແລະເຄືອຂ່າຍຂອງທ່ານ ເຊິ່ງລວມທັງອີເມວ, ແອັບ ແລະເວັບໄຊທ໌."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Your work profile is managed by <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nYour admin is capable of monitoring your network activity including emails, apps, and websites.\n\nFor more information, contact your admin.\n\nYou\'re also connected to a VPN, which can monitor your network activity."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ອຸປະກອນນີ້ແມ່ນຈັດການໂດຍພໍ່ແມ່ຂອງທ່ານ. ພໍ່ແມ່ຂອງທ່ານສາມາດເບິ່ງ ແລະ ຈັດການຂໍ້ມູນໄດ້ ເຊັ່ນ: ແອັບທີ່ທ່ານໃຊ້, ສະຖານທີ່ ແລະ ເວລາໜ້າຈໍຂອງທ່ານ."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"ທ່ານເຊື່ອມຕໍ່ຫາ <xliff:g id="APPLICATION">%1$s</xliff:g> ແລ້ວ, ເຊິ່ງສາມາດຕິດຕາມການເຄື່ອນໄຫວເຄືອຂ່າຍຂອງທ່ານ ຮວມທັງອີເມວ, ແອັບ ແລະ ເວັບໄຊ."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"ທ່ານເຊື່ອມຕໍ່ກັບ <xliff:g id="APPLICATION">%1$s</xliff:g>, ເຊິ່ງສາມາດຕິດຕາມການເຄື່ອນໄຫວເຄືອຂ່າຍສ່ວນຕົວຂອງທ່ານ ລວມທັງອີເມວ, ​ແອັບ ແລະເວັບໄຊທ໌."</string>
@@ -1089,4 +1093,6 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ຈັບຄູ່ອຸປະກອນໃໝ່"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ໝາຍເລກສ້າງ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ສຳເນົາໝາຍເລກສ້າງໄປໃສ່ຄລິບບອດແລ້ວ."</string>
+ <string name="battery_state_unknown_notification_title" msgid="8464703640483773454">"ເກີດບັນຫາໃນການອ່ານຕົວວັດແທກແບັດເຕີຣີຂອງທ່ານ"</string>
+ <string name="battery_state_unknown_notification_text" msgid="13720937839460899">"ແຕະເພື່ອເບິ່ງຂໍ້ມູນເພີ່ມເຕີມ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 152a5323536b..ec102b7cec3f 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Dvi akumuliatoriaus juostos."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Trys akumuliatoriaus juostos."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Akumuliatorius įkrautas."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Nėra telefono."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Viena telefono juosta."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dvi telefono juostos."</string>
@@ -526,6 +528,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profilis gali būti stebimas"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Tinklas gali būti stebimas"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Tinklas gali būti stebimas"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Šį įrenginį tvarko vienas iš tavo tėvų"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Šis įrenginys priklauso jūsų organizacijai ir ji gali stebėti tinklo srautą"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Šis įrenginys priklauso „<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>“ ir ji gali stebėti tinklo srautą"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Šis įrenginys priklauso jūsų organizacijai ir yra susietas su „<xliff:g id="VPN_APP">%1$s</xliff:g>“"</string>
@@ -550,6 +553,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Išjungti VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Atjungti VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Žr. politiką"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Rodinio valdikliai"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Šis įrenginys priklauso „<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>“.\n\nIT administratorius gali stebėti ir tvarkyti nustatymus, įmonės prieigą, programas, su įrenginiu susietus duomenis ir įrenginio vietovės informaciją.\n\nDaugiau informacijos galite gauti susisiekę su IT administratoriumi."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Šis įrenginys priklauso jūsų organizacijai.\n\nIT administratorius gali stebėti ir tvarkyti nustatymus, įmonės prieigą, programas, su įrenginiu susietus duomenis ir įrenginio vietovės informaciją.\n\nDaugiau informacijos galite gauti susisiekę su IT administratoriumi."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Jūsų organizacija įdiegė šiame įrenginyje sertifikato įgaliojimą. Jūsų saugaus tinklo srautas gali būti stebimas arba keičiamas."</string>
@@ -573,6 +577,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Administratorius įjungė tinklo duomenų įrašymą į žurnalą. Įjungus šią funkciją stebimas srautas jūsų įrenginyje.\n\nJei reikia daugiau informacijos, susisiekite su administratoriumi."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Suteikėte programai leidimą nustatyti VPN ryšį.\n\nŠi programa gali stebėti įrenginio ir tinklo veiklą, įskaitant el. laiškus, programas ir svetaines."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Jūsų darbo profilį tvarko „<xliff:g id="ORGANIZATION">%1$s</xliff:g>“.\n\nJūsų administratorius gali stebėti jūsų tinklo veiklą, įskaitant el. laiškus, programas ir svetaines.\n\nJei reikia daugiau informacijos, susisiekite su administratoriumi.\n\nTaip pat esate prisijungę prie VPN, kuris gali stebėti jūsų tinklo veiklą."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Šį įrenginį tvarko vienas iš tavo tėvų. Jis gali peržiūrėti ir tvarkyti informaciją, pvz., tavo naudojamas programas, vietovę ir įrenginio naudojimo laiką."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Esate prisijungę prie „<xliff:g id="APPLICATION">%1$s</xliff:g>“, kuri gali stebėti tinklo veiklą, įskaitant el. laiškus, programas ir svetaines."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Esate prisijungę prie programos „<xliff:g id="APPLICATION">%1$s</xliff:g>“, kuri gali stebėti asmeninio profilio tinklo veiklą, įskaitant el. laiškus, programas ir svetaines."</string>
@@ -1101,4 +1106,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Naujo įrenginio susiejimas"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijos numeris"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versijos numeris nukopijuotas į iškarpinę."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index ae67d0f22997..9c12665f7f3b 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Akumulators: divas joslas."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Akumulators: trīs joslas."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Akumulators ir pilnīgi uzlādēts."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Nav tālruņa."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Tālrunis: viena josla."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Tālrunis: divas joslas."</string>
@@ -523,6 +525,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profilu var pārraudzīt"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Iespējams, tīklā veiktās darbības tiek pārraudzītas."</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Var tikt pārraudzītas tīklā veiktās darbības."</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Šo ierīci pārvalda viens no jūsu vecākiem."</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Šī ierīce pieder jūsu organizācijai, un jūsu organizācija var uzraudzīt tīkla datplūsmu."</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Šī ierīce pieder organizācijai<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>, un šī organizācija var uzraudzīt tīkla datplūsmu."</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Šī ierīce pieder jūsu organizācijai un ir saistīta ar: <xliff:g id="VPN_APP">%1$s</xliff:g>."</string>
@@ -547,6 +550,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Atspējot VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Atvienot VPN tīklu"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Skatīt politikas"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Skatīt vadīklas"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Šī ierīce pieder organizācijai <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nJūsu IT administrators var pārraudzīt un pārvaldīt iestatījumus, korporatīvo piekļuvi, lietotnes, ar ierīci saistītos datus un ierīces atrašanās vietas informāciju.\n\nLai iegūtu plašāku informāciju, sazinieties ar IT administratoru."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Šī ierīce pieder jūsu organizācijai.\n\nJūsu IT administrators var pārraudzīt un pārvaldīt iestatījumus, korporatīvo piekļuvi, lietotnes, ar ierīci saistītos datus un ierīces atrašanās vietas informāciju.\n\nLai iegūtu plašāku informāciju, sazinieties ar IT administratoru."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Jūsu organizācija instalēja sertifikātu šajā ierīcē. Jūsu drošā tīkla datplūsma var tikt uzraudzīta."</string>
@@ -570,6 +574,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Administrators ir ieslēdzis tīkla reģistrēšanu, kuru izmanto, lai pārraudzītu datplūsmu jūsu ierīcē.\n\nLai iegūtu plašāku informāciju, sazinieties ar administratoru."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Jūs piešķīrāt lietotnei atļauju izveidot savienojumu ar VPN tīklu.\n\nŠī lietotne var pārraudzīt jūsu ierīcē un tīklā veiktās darbības, tostarp e-pasta ziņojumus, lietotnes un vietnes."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Jūsu darba profilu pārvalda <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministrators var pārraudzīt jūsu darbības darba tīklā, tostarp e-pastu, lietotnes un vietnes.\n\nLai iegūtu plašāku informāciju, sazinieties ar administratoru.\n\nIr izveidots savienojums arī ar VPN, kurā var pārraudzīt jūsu darbības tīklā."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Šo ierīci pārvalda viens no jūsu vecākiem. Vecāki var skatīt un pārvaldīt tādu informāciju kā jūsu izmantotās lietotnes, atrašanās vieta un izmantošanas ilgums."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Ir izveidots savienojums ar lietotni <xliff:g id="APPLICATION">%1$s</xliff:g>, kura var pārraudzīt jūsu tīklā veiktās darbības, tostarp e-pasta ziņojumus, lietotnes un vietnes."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Ir izveidots savienojums ar lietotni <xliff:g id="APPLICATION">%1$s</xliff:g>, kura var pārraudzīt jūsu tīklā veiktās privātās darbības, tostarp e-pasta ziņojumus, lietotnes un vietnes."</string>
@@ -1095,4 +1100,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Savienošana pārī ar jaunu ierīci"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versijas numurs"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versijas numurs ir kopēts starpliktuvē."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index fca688d28f8e..a67e3b55af1e 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Батерија две цртички."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Батерија три цртички."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Батеријата е полна."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Нема сигнал."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Телефон една цртичка.."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Телефон две цртички."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Профилот можеби се следи"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Мрежата може да се следи"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Мрежата може да се следи"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Родителот управува со уредов"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Организацијата е сопственик на уредов и може да го следи мрежниот сообраќај"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> е сопственик на уредов и може да го следи мрежниот сообраќај"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Уредов е во сопственост на организацијата и е поврзан со <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Оневозможи ВПН"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Исклучи ВПН"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Прикажи „Политики“"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Прикажи ги контролите"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Уредов е во сопственост на <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nIT-администраторот може да ги следи и да управува со поставките, корпоративниот пристап, апликациите, податоците поврзани со уредот и податоците за локацијата на уредот.\n\nЗа повеќе информации, контактирајте со IT-администраторот."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Уредов е во сопственост на организацијата.\n\nIT-администраторот може да ги следи и да управува со поставките, корпоративниот пристап, апликациите, податоците поврзани со уредот и податоците за локацијата на уредот.\n\nЗа повеќе информации, контактирајте со IT-администраторот."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Вашата организација инсталираше авторитет за сертификат на уредов. Сообраќајот на вашата безбедна мрежа можно е да се следи или изменува."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Вашиот администратор вклучил евиденција на мрежата, што подразбира следење на сообраќајот на вашиот уред.\n\nЗа повеќе информации, контактирајте со администраторот."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Дозволивте апликацијата да постави поврзување преку ВПН.\n\nАпликацијата може да го следи уредот и активноста на мрежата, вклучувајќи ги е-пораките, апликациите и веб-локациите."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> управува со вашиот работен профил.\n\nАдминистратор е во можност да ја следи вашата активност на мрежата, вклучувајќи ги е-пораките, апликациите и веб-локациите.\n\nЗа повеќе информации, контактирајте со администраторот.\n\nYИсто така, поврзани сте на VPN којашто може да ја следи вашата активност на мрежата."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Родителот управува со уредов. Родителот може да прегледува и управува со податоците, како што се апликациите што ги користите, вашата локација и време поминато на уредот."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"ВПН"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Поврзани сте на <xliff:g id="APPLICATION">%1$s</xliff:g>, што може да ја следи вашата активност на мрежата, заедно со е-пораките, апликациите и веб-сајтовите."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Поврзани сте на <xliff:g id="APPLICATION">%1$s</xliff:g>, којашто може да ја следи вашата лична активност на мрежата, вклучувајќи ги е-пораките, апликациите и веб-локациите."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Спарете нов уред"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Број на верзија"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Бројот на верзијата е копиран во привремената меморија."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index cd757612073a..3b6c616182f1 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"ബാറ്ററി രണ്ട് ബാർ."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ബാറ്ററി മൂന്ന് ബാർ."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ബാറ്ററി നിറഞ്ഞു."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"ഫോൺ സിഗ്‌നൽ ഒന്നുമില്ല."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ഫോണിൽ ഒരു ബാർ."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ഫോണിൽ രണ്ട് ബാർ."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"പ്രൊഫൈൽ നിരീക്ഷിക്കപ്പെടാം"</string>
<string name="vpn_footer" msgid="3457155078010607471">"നെറ്റ്‌വർക്ക് നിരീക്ഷിക്കപ്പെടാം"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"നെറ്റ്‌വർക്ക് നിരീക്ഷിക്കപ്പെടാം"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ഈ ഉപകരണം മാനേജ് ചെയ്യുന്നത് നിങ്ങളുടെ രക്ഷിതാവാണ്"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ഈ ഉപകരണം നിങ്ങളുടെ സ്ഥാപനത്തിന്റെ ഉടമസ്ഥതയിലായതിനാൽ നെറ്റ്‌വർക്ക് ട്രാഫിക്ക് നിരീക്ഷിച്ചേക്കാം"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"ഈ ഉപകരണം <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> എന്ന സ്ഥാപനത്തിന്റെ ഉടമസ്ഥതയിലായതിനാൽ നെറ്റ്‌വർക്ക് ട്രാഫിക്ക് നിരീക്ഷിച്ചേക്കാം"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ഈ ഉപകരണം നിങ്ങളുടെ സ്ഥാപനത്തിന്റേതാണ്, കൂടാതെ <xliff:g id="VPN_APP">%1$s</xliff:g> എന്നതിലേക്ക് കണക്റ്റ് ചെയ്‌തിരിക്കുന്നു"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN പ്രവർത്തനരഹിതമാക്കുക"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN വിച്‌ഛേദിക്കുക"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"നയങ്ങൾ കാണുക"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"നിയന്ത്രണങ്ങൾ കാണുക"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"ഈ ഉപകരണം <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>എന്ന സ്ഥാപനത്തിന്റേതാണ്.\n\nക്രമീകരണം, കോർപ്പറേറ്റ് ആക്‌സസ്, ആപ്പുകൾ, നിങ്ങളുടെ ഉപകരണവുമായി ബന്ധപ്പെട്ട ഡാറ്റ, ഉപകരണത്തിന്റെ ലൊക്കേഷൻ ‌വിവരങ്ങൾ എന്നിവ നിരീക്ഷിക്കാനും മാനേജ് ചെയ്യാനും നിങ്ങളുടെ ഐടി അഡ്‌മിന് കഴിയും.\n\nകൂടുതൽ വിവരങ്ങൾക്ക് നിങ്ങളുടെ ഐടി അഡ്‌മിനെ ബന്ധപ്പെടുക."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"ഈ ഉപകരണം നിങ്ങളുടെ സ്ഥാപനത്തിന്റേതാണ്.\n\nക്രമീകരണം, കോർപ്പറേറ്റ് ആക്‌സസ്, ആപ്പുകൾ, നിങ്ങളുടെ ഉപകരണവുമായി ബന്ധപ്പെട്ട ഡാറ്റ, ഉപകരണത്തിന്റെ ലൊക്കേഷൻ ‌വിവരങ്ങൾ എന്നിവ നിരീക്ഷിക്കാനും മാനേജ് ചെയ്യാനും നിങ്ങളുടെ ഐടി അഡ്‌മിന് കഴിയും.\n\nകൂടുതൽ വിവരങ്ങൾക്ക് നിങ്ങളുടെ ഐടി അഡ്‌മിനെ ബന്ധപ്പെടുക."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ഈ ഉപകരണത്തിൽ നിങ്ങളുടെ സ്ഥാപനമൊരു സർട്ടിഫിക്കറ്റ് അതോറിറ്റി ഇൻസ്റ്റാൾ ചെയ്തിരിക്കുന്നു. നിങ്ങളുടെ സുരക്ഷിത നെറ്റ്‌വർക്ക് ട്രാഫിക്ക് നിരീക്ഷിക്കപ്പെടുകയോ പരിഷ്കരിക്കപ്പെടുയോ ചെയ്തേക്കാം."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"നിങ്ങളുടെ ഉപകരണത്തിലെ ട്രാഫിക്ക് നിരീക്ഷിക്കുന്ന നെറ്റ്‌വർക്ക് ലോഗിംഗ് അഡ്‌മിൻ ഓണാക്കിയിട്ടുണ്ട്.\n\nകൂടുതൽ ‌വിവരങ്ങൾക്ക് അഡ്‌മിനുമായി‌ ബന്ധപ്പെടുക."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"VPN കണക്ഷൻ സജ്ജീകരിക്കാൻ നിങ്ങൾ ഒരു ആപ്പിന് അനുമതി നൽകി.\n\nഈ ആപ്പിന് നിങ്ങളുടെ ഇമെയിലുകളും ആപ്സും വെബ്‌സൈറ്റുകളും ഉൾപ്പെടെ, ഉപകരണവും നെറ്റ്‌വർക്ക് പ്രവർത്തനവും നിരീക്ഷിക്കാൻ കഴിയും."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"നിങ്ങളുടെ ഔദ്യോഗിക പ്രൊഫൈൽ നിയന്ത്രിക്കുന്നത് <xliff:g id="ORGANIZATION">%1$s</xliff:g> ആണ്.\n\nഇമെയിലുകൾ, ആപ്‌സ്, വെബ്‌സൈറ്റുകൾ എന്നിവയടങ്ങുന്ന നിങ്ങളുടെ നെറ്റ്‌വർക്ക് ആക്റ്റിവിറ്റി നിരീക്ഷിക്കാൻ അഡ്‌മിന് കഴിയും.\n\nകൂടുതൽ ‌വിവരങ്ങൾക്ക് അഡ്‌മിനുമായി‌ ബന്ധപ്പെടുക.\n\nനെറ്റ്‌വർക്ക് ആക്റ്റിവിറ്റി ‌നിരീക്ഷിക്കാൻ സാധിക്കുന്ന ഒരു VPN-ലേക്ക് കൂടി നിങ്ങൾ കണക്റ്റ് ‌ചെയ്യപ്പെട്ടിരിക്കുന്നു."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ഈ ഉപകരണം മാനേജ് ചെയ്യുന്നത് നിങ്ങളുടെ രക്ഷിതാവാണ്. നിങ്ങൾ ഉപയോഗിക്കുന്ന ആപ്പുകൾ, സ്‌ക്രീൻ സമയം, ലൊക്കേഷൻ എന്നിവ പോലുള്ള വിവരങ്ങൾ നിങ്ങളുടെ രക്ഷിതാവിന് കാണാം, നിയന്ത്രിക്കാം."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"നിങ്ങൾ <xliff:g id="APPLICATION">%1$s</xliff:g> ആപ്പിലേക്ക് കണക്റ്റുചെയ്‌തിരിക്കുന്നു, അതിന് ഇമെയിലുകൾ, ആപ്പുകൾ, വെബ്‌സൈറ്റുകൾ എന്നിവ ഉൾപ്പെടെ നിങ്ങളുടെ നെറ്റ്‌വർക്ക് ആക്റ്റിവിറ്റി നിരീക്ഷിക്കാനാകും."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"നിങ്ങൾ <xliff:g id="APPLICATION">%1$s</xliff:g> എന്നതിലേക്ക് കണക്റ്റുചെയ്‌തിരിക്കുന്നു, അതിന് ഇമെയിലുകൾ, ആപ്സ്, വെബ്‌സൈറ്റുകൾ എന്നിവ ഉൾപ്പെടെ നിങ്ങളുടെ സ്വകാര്യ നെറ്റ്‌വർക്ക് പ്രവർത്തനം നിരീക്ഷിക്കാനാകും."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"പുതിയ ഉപകരണവുമായി ജോടിയാക്കുക"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ബിൽഡ് നമ്പർ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ക്ലിപ്പ്ബോർഡിലേക്ക് ബിൽഡ് നമ്പർ പകർത്തി."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 4eb2fb1076c3..ef110e9e2fa3 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Батерей хоёр баганатай."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Батерей гурван баганатай."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Батерей дүүрэн."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Утас байхгүй."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Утас нэг баганатай."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Утас хоёр баганатай."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Профайлыг хянаж байж болзошгүй"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Сүлжээ хянагдаж байж болзошгүй"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Сүлжээг хянаж байж болзошгүй"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Энэ төхөөрөмжийг таны эцэг эх удирддаг"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Танай байгууллага энэ төхөөрөмжийг эзэмшдэг бөгөөд сүлжээний ачааллыг хянаж болно"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> энэ төхөөрөмжийг эзэмшдэг бөгөөд сүлжээний ачааллыг хянаж болно"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Энэ төхөөрөмж танай байгууллагад харьяалагддаг бөгөөд <xliff:g id="VPN_APP">%1$s</xliff:g>-д холбогдсон байна"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN идэвхгүйжүүлэх"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN таслах"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Удирдамж харах"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Хяналтыг харах"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Энэ төхөөрөмж <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>-д харьяалагддаг.\n\nТанай IT админ тохиргоо, байгууллагын хандалт, аппууд, таны төхөөрөмжтэй холбоотой өгөгдөл, таны төхөөрөмжийн байршлын мэдээллийг хянах, удирдах боломжтой.\n\nНэмэлт мэдээлэл авахын тулд IT админтайгаа холбогдоно уу."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Энэ төхөөрөмж танай байгууллагад харьяалагддаг.\n\nТанай IT админ тохиргоо, байгууллагын хандалт, аппууд, таны төхөөрөмжтэй холбоотой өгөгдөл, таны төхөөрөмжийн байршлын мэдээллийг хянах, удирдах боломжтой.\n\nНэмэлт мэдээлэл авахын тулд IT админтайгаа холбогдоно уу."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Таны байгууллага энэ төхөөрөмжид сертификатын зөвшөөрлийг суулгасан байна. Таны аюулгүй сүлжээний ачааллыг өөрчлөх эсвэл хянах боломжтой."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Таны админ төхөөрөмжийн ачааллыг хянадаг сүлжээний логийг асаасан байна.\n\nДэлгэрэнгүй мэдээлэл авах бол админтайгаа холбогдоно уу."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Та апп-д VPN холболт хийхийг зөвшөөрсөн байна.\n\nЭнэхүү апп нь таны имэйл, апп, вебсайт зэрэг төхөөрөмж болон сүлжээний үйл ажиллагааг хянах боломжтой."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> таны ажлын профайлыг удирддаг.\n\nТаны админ имэйл, апп болон веб хуудас зэрэг сүлжээний үйл ажиллагааг хянах боломжтой.\n\nДэлгэрэнгүй мэдээлэл авах бол админтайгаа холбогдоно уу.\n\nТа сүлжээний үйл ажиллагааг хянах боломжтой VPN-д холбогдсон байна."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Энэ төхөөрөмжийг таны эцэг эх удирддаг. Таны эцэг эх таны хэрэглэдэг апп, байршил, дэлгэцийн цаг зэрэг мэдээллийг харж, удирдах боломжтой."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Та <xliff:g id="APPLICATION">%1$s</xliff:g>-д холбогдсон бөгөөд энэ нь таны имэйл, апп, вебсайт зэрэг сүлжээний үйл ажиллагааг хянах боломжтой."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Та <xliff:g id="APPLICATION">%1$s</xliff:g>-д холбогдсон бөгөөд энэ нь таны имэйл, апп, вебсайт зэрэг сүлжээний хувийн үйл ажиллагааг хянах боломжтой."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Шинэ төхөөрөмж хослуулах"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Хийгдсэн дугаар"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Хийгдсэн дугаарыг түр санах ойд хуулсан."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 57c1e07d3802..9b3ee7115268 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"बॅटरी दोन बार."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"बॅटरी तीन बार."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"बॅटरी पूर्ण भरली."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"कोणताही फोन नाही."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"फोन एक बार."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"फोन दोन बार."</string>
@@ -520,6 +522,8 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"प्रोफाईलचे परीक्षण केले जाऊ शकते"</string>
<string name="vpn_footer" msgid="3457155078010607471">"नेटवर्कचे परीक्षण केले जाऊ शकते"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"नेटवर्कचे परीक्षण केले जाऊ शकते"</string>
+ <!-- no translation found for quick_settings_disclosure_parental_controls (2114102871438223600) -->
+ <skip />
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"तुमच्‍या संस्‍थेकडे या डिव्हाइसची मालकी आहे आणि ती नेटवर्क ट्रॅफिकचे परीक्षण करू शकते"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> च्या मालकीचे आहे आणि ती नेटवर्क ट्रॅफिकचे परीक्षण करू शकते"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"हे डिव्हाइस तुमच्या संस्थेचे आहे आणि ते <xliff:g id="VPN_APP">%1$s</xliff:g> ला कनेक्ट केले आहे"</string>
@@ -544,6 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN अक्षम करा"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN डिस्कनेक्ट करा"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"धोरणे पहा"</string>
+ <!-- no translation found for monitoring_button_view_controls (8316440345340701117) -->
+ <skip />
<string name="monitoring_description_named_management" msgid="505833016545056036">"हे डिव्हाइस <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> चे आहे.\n\nतुमचा आयटी ॲडमिन सेटिंग्ज, कॉर्पोरेट अ‍ॅक्सेस, ॲप्‍स, तुमच्‍या डिव्‍हाइसशी संबंधित डेटा आणि तुमच्‍या डिव्‍हाइसच्‍या स्‍थानाची माहिती यांचे परीक्षण व व्‍यवस्‍थापन करू शकतो.\n\nअधिक माहितीसाठी तुमच्‍या आयटी ॲडमिनशी संपर्क साधा."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"हे डिव्हाइस तुमच्या संस्थेचे आहे.\n\nतुमचा आयटी ॲडमिन सेटिंग्ज, कॉर्पोरेट अ‍ॅक्सेस, ॲप्‍स, तुमच्‍या डिव्‍हाइसशी संबंधित डेटा आणि तुमच्‍या डिव्‍हाइसच्‍या स्‍थानाची माहिती यांचे परीक्षण व व्‍यवस्‍थापन करू शकतो.\n\nअधिक माहितीसाठी तुमच्‍या आयटी ॲडमिनशी संपर्क साधा."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"आपल्या संस्थेने या डिव्हाइसवर प्रमाणपत्र अधिकार इंस्टॉल केला आहे. आपल्या सुरक्षित नेटवर्क रहदारीचे परीक्षण केले जाऊ शकते किंवा ती सुधारली जाऊ शकते."</string>
@@ -567,6 +573,8 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"आपल्या प्रशासकाने नेटवर्क लॉगिंग सुरू केले आहे, जे आपल्या डिव्हाइसवरील रहदारीचे निरीक्षण करते.\n\nअधिक माहितीसाठी आपल्या प्रशासकाशी संपर्क साधा."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"तुम्ही VPN कनेक्शन सेट करण्यासाठी अ‍ॅपला परवानगी दिली.\n\nहा अ‍ॅप ईमेल, अ‍ॅप्स आणि वेबसाइटसह, तुमच्या डिव्हाइस आणि नेटवर्क ॲक्टिव्हिटीचे परीक्षण करू शकतो."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"तुमचे कार्य प्रोफाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> द्वारे व्यवस्थापित केले जाते.\n\nतुमचा प्रशासक ईमेल, अ‍ॅप्स आणि वेबसाइटसह आपल्या नेटवर्क ॲक्टिव्हिटीचे निरीक्षण करण्यास सक्षम आहे.\n\nअधिक माहितीसाठी आपल्या प्रशासकाशी संपर्क साधा.\n\nतुम्ही VPN शी देखील कनेक्ट आहात, जे आपल्या नेटवर्क ॲक्टिव्हिटीचे निरीक्षण करू शकते."</string>
+ <!-- no translation found for monitoring_description_parental_controls (8184693528917051626) -->
+ <skip />
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"तुम्ही <xliff:g id="APPLICATION">%1$s</xliff:g> शी कनेक्‍ट केले आहे, जे ईमेल, अ‍ॅप्स आणि वेबसाइटसह आपल्‍या नेटवर्क क्रियाकलापाचे परीक्षण करू शकते."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"तुम्ही <xliff:g id="APPLICATION">%1$s</xliff:g> शी कनेक्‍ट केले आहे, जो ईमेल, अ‍ॅप्स आणि वेबसाइटसह आपल्‍या वैयक्तिक नेटवर्क क्रियाकलापाचे परीक्षण करू शकतो."</string>
@@ -1089,4 +1097,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नवीन डिव्हाइससोबत पेअर करा"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नंबर"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नंबर क्लिपबोर्डवर कॉपी केला."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 058055f54c95..55f1e3252e5e 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Bateri dua bar."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Bateri tiga bar."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateri penuh."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Tiada telefon."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon satu bar."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon dua bar."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil mungkin dipantau"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Rangkaian mungkin dipantau"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Rangkaian mungkin dipantau"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Peranti ini diurus oleh ibu bapa anda"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organisasi anda memiliki peranti ini dan mungkin memantau trafik rangkaian"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> memiliki peranti ini dan mungkin memantau trafik rangkaian"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Peranti ini milik organisasi anda dan dihubungkan dengan <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Lumpuhkan VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Putuskan sambungan VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Lihat Dasar"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Lihat kawalan"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Peranti ini milik <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nPentadbir IT anda boleh memantau dan mengurus tetapan, akses korporat, apl, data yang dikaitkan dengan peranti anda dan maklumat lokasi peranti anda.\n\nUntuk maklumat lanjut, hubungi pentadbir IT anda."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Peranti ini milik organisasi anda.\n\nPentadbir IT anda boleh memantau dan mengurus tetapan, akses korporat, apl, data yang dikaitkan dengan peranti anda dan maklumat lokasi peranti anda.\n\nUntuk maklumat lanjut, hubungi pentadbir IT anda."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organisasi anda memasang sijil kuasa pada peranti ini. Trafik rangkaian selamat anda mungkin dipantau atau diubah suai."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Pentadbir anda telah menghidupkan pengelogan rangkaian yang memantau trafik pada peranti anda.\n\nUntuk mendapatkan maklumat lanjut, hubungi pentadbir anda."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Anda memberikan kebenaran kepada apl untuk menyediakan sambungan VPN.\n\nApl ini boleh memantau aktiviti peranti dan rangkaian anda, termasuk e-mel, apl dan tapak web."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Profil kerja anda diurus oleh <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nPentadbir anda boleh memantau aktiviti rangkaian, termasuk e-mel, apl dan tapak web.\n\nUntuk mendapatkan maklumat lanjut, hubungi pentadbir anda.\n\nAnda juga disambungkan ke VPN, yang boleh memantau aktiviti rangkaian."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Peranti ini diurus oleh ibu bapa anda. Ibu bapa anda dapat melihat dan mengurus maklumat seperti apl yang anda gunakan, lokasi dan masa skrin anda."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Anda dihubungkan ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang boleh memantau aktiviti rangkaian anda, termasuk e-mel, apl dan tapak web."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Anda disambungkan ke <xliff:g id="APPLICATION">%1$s</xliff:g>, yang boleh memantau aktiviti rangkaian peribadi anda, termasuk e-mel, apl dan tapak web."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Gandingkan peranti baharu"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nombor binaan"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nombor binaan disalin ke papan keratan."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 5249efa4d48e..18e804b5a2ff 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"ဘတ္တရီနှစ်ဘား။"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ဘတ္တရီသုံးဘား။"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ဘတ္တရီအပြည့်။"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"ဖုန်းလိုင်းမရှိပါ။"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ဖုန်းလိုင်းတစ်ဘား။"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ဖုန်းလိုင်းနှစ်ဘား။"</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"ပရိုဖိုင်ကို စောင့်ကြပ်နိုင်သည်"</string>
<string name="vpn_footer" msgid="3457155078010607471">"ကွန်ရက်ကို ကို စောင့်ကြပ် နိုင်ပါသည်"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ကွန်ရက်ကို စောင့်ကြည့်စစ်ဆေးမှု ရှိနိုင်ပါသည်"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ဤစက်ပစ္စည်းကို သင့်မိဘက စီမံခန့်ခွဲသည်"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ဤစက်ကို သင့်အဖွဲ့အစည်းကပိုင်ဆိုင်ပြီး ကွန်ရက်ဒေတာ စီးဆင်းမှုကို စောင့်ကြည့်နိုင်ပါသည်"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"ဤစက်ကို <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> က ပိုင်ဆိုင်ပြီး ကွန်ရက်ဒေတာ စီးဆင်းမှုကို စောင့်ကြည့်နိုင်ပါသည်"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ဤစက်ကို သင့်အဖွဲ့အစည်းကပိုင်ဆိုင်ပြီး <xliff:g id="VPN_APP">%1$s</xliff:g> သို့ ချိတ်ဆက်ထားပါသည်"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN ကို ပိတ်ထားရန်"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN ကို အဆက်ဖြတ်ရန်"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"မူဝါဒများကို ကြည့်ရန်"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"ထိန်းချုပ်မှုများကို ကြည့်ရန်"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"ဤစက်ကို <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> က ပိုင်ဆိုင်ပါသည်။\n\nဆက်တင်များ၊ ကော်ပိုရိတ် သုံးခွင့်၊ အက်ပ်များ၊ သင့်စက်နှင့် ဆက်စပ်နေသော ဒေတာများနှင့် သင့်စက်တည်နေရာတို့ကို သင်၏ IT စီမံခန့်ခွဲသူက စောင့်ကြည့် စီမံနိုင်သည်။\n\nနောက်ထပ်အချက်အလက်များအတွက် သင်၏ IT စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"ဤစက်ကို သင့်အဖွဲ့အစည်းက ပိုင်ဆိုင်သည်။\n\nဆက်တင်များ၊ ကော်ပိုရိတ် သုံးခွင့်၊ အက်ပ်များ၊ သင့်စက်နှင့် ဆက်စပ်နေသော ဒေတာများနှင့် သင့်စက်တည်နေရာတို့ကို သင်၏ IT စီမံခန့်ခွဲသူက စောင့်ကြည့် စီမံနိုင်သည်။\n\nနောက်ထပ်အချက်အလက်များအတွက် သင်၏ IT စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"သင်၏ အဖွဲ့အစည်းက ဤစက်ပစ္စည်းတွင် စီမံခန့်ခွဲမှုဆိုင်ရာ အသိအမှတ်ပြုလက်မှတ်ကို ထည့်သွင်းထားပါသည်။ လုံခြုံမှုရှိသော ကွန်ရက်ဒေတာစီးဆင်းမှုကို စောင့်ကြည့်ခြင်း သို့မဟုတ် ပြုပြင်ခြင်းများ ပြုလုပ်နိုင်ပါသည်။"</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"သင့်စီမံခန့်ခွဲသူသည် စက်ပစ္စည်းပေါ်ရှိ ဒေတာအသွားအလာကို စောင့်ကြည့်နိုင်သည့် ကွန်ရက်အတွက် မှတ်တမ်းတင်ခြင်းကို ဖွင့်ထားပါသည်။\n\nနောက်ထပ် အချက်အလက်များအတွက် သင့်စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"VPN ချိတ်ဆက်မှုပြုလုပ်ရန် အက်ပ်ကို သင်ခွင့်ပြုလိုက်သည်။ \n\n ဤအက်ပ်သည် အီးမေးလ်များ၊ အက်ပ်များနှင့် ဝဘ်ဆိုက်များအပါအဝင် သင့်ကွန်ရက်လုပ်ဆောင်ချက်များကို စောင့်ကြည့်နိုင်သည်။"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"သင့်အလုပ်ပရိုဖိုင်ကို <xliff:g id="ORGANIZATION">%1$s</xliff:g> က စီမံခန့်ခွဲထားပါသည်။\n\nသင့်စီမံခန့်ခွဲသူသည် အီးမေးလ်၊ အက်ပ်နှင့် ဝဘ်ဆိုက်များအပါအဝင် သင့်ကွန်ရက်လုပ်ဆောင်ချက်ကို စောင့်ကြည့်နိုင်ပါသည်။\n\nနောက်ထပ် အချက်အလက်များအတွက် သင့်စီမံခန့်ခွဲသူကို ဆက်သွယ်ပါ။\n\nသင်သည် သင့်ကွန်ရက်လုပ်ဆောင်ချက်ကို စောင့်ကြည့်နိုင်သည့် VPN သို့လည်း ချိတ်ဆက်ထားပါသေးသည်။"</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ဤစက်ပစ္စည်းကို သင့်မိဘက စီမံခန့်ခွဲသည်။ သင့်မိဘက သင်သုံးသောအက်ပ်များ၊ သင်၏တည်နေရာနှင့် အသုံးပြုချိန် ကဲ့သို့သော အချက်အလက်များကို မြင်နိုင်ပြီး စီမံခန့်ခွဲနိုင်သည်။"</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"သင်သည် အီးမေး၊ အက်ပ်နှင့် ဝဘ်ဆိုက်များအပါအဝင် သင်၏ကွန်ရက် လုပ်ဆောင်ချက်များကို စောင့်ကြည့်နိုင်သည့် <xliff:g id="APPLICATION">%1$s</xliff:g> သို့ ချိတ်ဆက်ထားပါသည်။"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"သင်သည် <xliff:g id="APPLICATION">%1$s</xliff:g> သို့ ချိတ်ဆက်ထားသည်။ ၎င်းသည် အီးမေးလ်များ၊ အက်ပ်များနှင့် ဝဘ်ဆိုက်များအပါအဝင် သင့်ကွန်ရက်လုပ်ဆောင်ချက်ကို စောင့်ကြည့်နိုင်သည်။"</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"စက်အသစ် တွဲချိတ်ရန်"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"တည်ဆောက်မှုနံပါတ်"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"တည်ဆောက်မှုနံပါတ်ကို ကလစ်ဘုတ်သို့ မိတ္တူကူးပြီးပါပြီ။"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index b676e91398e1..8becc3b81fc4 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Batteri – to stolper."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batteri – tre stolper."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batteriet er fullt."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Ingen telefon."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon – én stolpe."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon – to stolper."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profilen kan overvåkes"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Nettverket kan være overvåket"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Nettverket kan bli overvåket"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Denne enheten administreres av forelderen din"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organisasjonen din eier denne enheten og kan overvåke nettverkstrafikken"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> eier denne enheten og kan overvåke nettverkstrafikken"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Denne enheten tilhører organisasjonen din og er koblet til <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Deaktiver VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Koble fra VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Se retningslinjer"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Visningskontroller"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Denne enheten tilhører <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nIT-administratoren din kan overvåke og administrere innstillinger, bedriftstilgang, apper, data som er tilknyttet denne enheten, og enhetens posisjonsinformasjon.\n\nKontakt IT-administratoren for å få mer informasjon."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Denne enheten tilhører organisasjonen din.\n\nIT-administratoren din kan overvåke og administrere innstillinger, bedriftstilgang, apper, data som er tilknyttet denne enheten, og enhetens posisjonsinformasjon.\n\nKontakt IT-administratoren for å få mer informasjon."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organisasjonen din installerte en sertifiseringsinstans på denne enheten. Den sikre nettverkstrafikken din kan overvåkes eller endres."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Administratoren din har slått på loggføring av nettverk, som overvåker trafikken på enheten din.\n\nKontakt administratoren for mer informasjon."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Du ga en app tillatelse til å konfigurere en VPN-tilkobling.\n\nDenne appen kan overvåke enheten og nettverksaktiviteten din, inkludert e-post, apper og nettsteder."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Jobbprofilen din administreres av <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministratoren din kan overvåke nettverksaktiviteten din, inkludert e-post, apper og nettsteder.\n\nKontakt administratoren for mer informasjon.\n\nDu er også tilkoblet en VPN som kan overvåke nettverksaktiviteten din."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Denne enheten administreres av forelderen din. Forelderen din kan se og administrere informasjon, for eksempel appene du bruker, posisjonen din og skjermtiden din."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Enheten er koblet til <xliff:g id="APPLICATION">%1$s</xliff:g>, som kan overvåke nettverksaktiviteten din, inkludert e-post, apper og nettsteder."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Enheten er koblet til <xliff:g id="APPLICATION">%1$s</xliff:g>, som kan overvåke den personlige nettverksaktiviteten din, inkludert e-post, apper og nettsteder."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Koble til en ny enhet"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Delversjonsnummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Delversjonsnummeret er kopiert til utklippstavlen."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index c3c8903c809c..eac89c2a31aa 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"ब्याट्रिका दुईवटा पट्टिहरू"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ब्याट्रिका तिनवटा पट्टिहरू"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ब्याट्री पूर्ण छ।"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"फोन छैन्।"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"फोन एउटा पट्टि।"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"फोन दुई पट्टि।"</string>
@@ -520,6 +522,8 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"प्रोफाइल अनुगमन हुन सक्छ"</string>
<string name="vpn_footer" msgid="3457155078010607471">"सञ्जाल अनुगमित हुन सक्छ"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"नेटवर्कको अनुगमन गरिने सम्भावना छ"</string>
+ <!-- no translation found for quick_settings_disclosure_parental_controls (2114102871438223600) -->
+ <skip />
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"यो यन्त्र तपाईंको सङ्गठनको स्वामित्वमा छ र उक्त सङ्गठनले यसको नेटवर्क ट्राफिक अनुगमन गर्न सक्छ"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"यो यन्त्र <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> को स्वामित्वमा छ र उक्त सङ्गठनले यसको नेटवर्क ट्राफिक अनुगमन गर्न सक्छ"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"यो यन्त्र तपाईंको सङ्गठनको स्वामित्वमा छ र <xliff:g id="VPN_APP">%1$s</xliff:g> मा कनेक्ट गरिएको छ"</string>
@@ -544,6 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN असक्षम गर्नुहोस्"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"विच्छेद VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"नीतिहरू हेर्नुहोस्"</string>
+ <!-- no translation found for monitoring_button_view_controls (8316440345340701117) -->
+ <skip />
<string name="monitoring_description_named_management" msgid="505833016545056036">"यो यन्त्र <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> को स्वामित्वमा छ।\n\nतपाईंका IT एड्मिन सेटिङ, संस्थागत पहुँच, एप, तपाईंको यन्त्रसँग सम्बन्धित डेटा र तपाईंको यन्त्रको स्थानसम्बन्धी जानकारीको निगरानी र व्यवस्थापन गर्न सक्नुहुन्छ।\n\nथप जानकारीका लागि आफ्ना IT एड्मिनसँग सम्पर्क गर्नुहोस्।"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"यो यन्त्र तपाईंको सङ्गठनको स्वामित्वमा छ।\n\nतपाईंका IT एड्मिन सेटिङ, संस्थागत पहुँच, एप, तपाईंको यन्त्रसँग सम्बन्धित डेटा र तपाईंको यन्त्रको स्थानसम्बन्धी जानकारीको निगरानी र व्यवस्थापन गर्न सक्नुहुन्छ।\n\nथप जानकारीका लागि आफ्ना IT एड्मिनसँग सम्पर्क गर्नुहोस्।"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"तपाईंको संगठनले तपाईंको कार्य प्रोफाइलमा एउटा प्रमाणपत्र सम्बन्धी अख्तियार सुविधा स्थापित गऱ्यो। तपाईंको सुरक्षित नेटवर्क ट्राफिकको अनुगमन वा परिमार्जन हुनसक्छ।"</string>
@@ -567,6 +573,8 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"तपाईँको प्रशासकले तपाईँको यन्त्रमा ट्राफिकको अनुगमन गर्ने नेटवर्कको लगिङलाई सक्रिय पार्नुभएको छ।\n\nथप जानकारीका लागि आफ्नो प्रशासकलाई सम्पर्क गर्नुहोस्।"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"तपाईँले VPN जडान गर्न एपलाई अनुमति दिनुभयो।\n\nयो एपले तपाईँका यन्त्र र नेटवर्क गतिविधि लगायत इमेल, एप र वेबसाइटहरू अनुगमन गर्न सक्छ।"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"तपाईंको कार्य प्रोफाइल <xliff:g id="ORGANIZATION">%1$s</xliff:g> ले व्यवस्थापन गर्दछ।\n\nतपाईंको प्रशासकले तपाईंको इमेल, एप र वेबसाइट सहित नेटवर्कमा तपाईंको गतिविधिको अनुगमन गर्न सक्नुहुन्छ। \n\nथप जानकारीका लागि आफ्नो प्रशासकलाई सम्पर्क गर्नुहोस्।\n\n तपाईं एउटा VPN मा जडित हुनुहुन्छ। यस VPN ले नेटवर्कमा तपाईंको गतिविधिको अनुगमन गर्न सक्छ।"</string>
+ <!-- no translation found for monitoring_description_parental_controls (8184693528917051626) -->
+ <skip />
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"तपाईं आफ्ना इमेल, एप र वेवसाइटहरू लगायत तपाईंको नेटवर्कको गतिविधिको अनुगमन गर्नसक्ने <xliff:g id="APPLICATION">%1$s</xliff:g> मा जडान हुनुहुन्छ।"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"तपाईं <xliff:g id="APPLICATION">%1$s</xliff:g> सँग जडित हुनुहुन्छ जसले इ-मेल, एपहरू र वेबसाइट लगायतका तपाईंको निजी नेटवर्क गतिविधिका अनुगमन गर्न सक्छ।"</string>
@@ -1089,4 +1097,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"नयाँ यन्त्रको जोडा बनाउनुहोस्"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"बिल्ड नम्बर"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"बिल्ड नम्बर कपी गरी क्लिपबोर्डमा सारियो।"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 691bfcbc57f7..d1134d39fe81 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Batterij: twee streepjes."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batterij: drie streepjes."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batterij is vol."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Geen telefoonsignaal."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefoon: één streepje."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefoon: twee streepjes."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profiel kan worden gecontroleerd"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Netwerk kan worden gecontroleerd"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Netwerk kan worden gecontroleerd"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Dit apparaat wordt beheerd door je ouder"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Je organisatie is eigenaar van dit apparaat en kan het netwerkverkeer bijhouden"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> is eigenaar van dit apparaat en kan het netwerkverkeer bijhouden"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Dit apparaat is eigendom van je organisatie en is verbonden met <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN uitschakelen"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Verbinding met VPN verbreken"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Beleid bekijken"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Beheeropties bekijken"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Dit apparaat is eigendom van <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nJe IT-beheerder kan instellingen, zakelijke toegang, apps, aan je apparaat gekoppelde gegevens en de locatiegegevens van je apparaat bekijken en beheren.\n\nNeem contact op met je IT-beheerder voor meer informatie."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Dit apparaat is eigendom van je organisatie.\n\nJe IT-beheerder kan instellingen, zakelijke toegang, apps, aan je apparaat gekoppelde gegevens en de locatiegegevens van je apparaat bekijken en beheren.\n\nNeem contact op met je IT-beheerder voor meer informatie."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Je organisatie heeft een certificeringsinstantie geïnstalleerd op dit apparaat. Je beveiligde netwerkverkeer kan worden bijgehouden of aangepast."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Je beheerder heeft netwerkregistratie ingeschakeld, waarmee verkeer op je apparaat wordt bijgehouden.\n\nNeem contact op met je beheerder voor meer informatie."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Je hebt een app rechten gegeven voor het instellen van een VPN-verbinding.\n\nMet deze app kan je apparaat- en netwerkactiviteit worden gecontroleerd, inclusief e-mails, apps en websites."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Je werkprofiel wordt beheerd door <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nJe beheerder kan je netwerkactiviteit controleren, inclusief e-mails, apps en websites.\n\nNeem contact op met je beheerder voor meer informatie.\n\nJe bent ook verbonden met een VPN, waarmee je netwerkactiviteit kan worden gecontroleerd."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Dit apparaat wordt beheerd door je ouder. Je ouder kan informatie bekijken en beheren, zoals de apps die je gebruikt, je locatie en je schermtijd."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Je bent verbonden met <xliff:g id="APPLICATION">%1$s</xliff:g>, waarmee je netwerkactiviteit (waaronder e-mails, apps en websites) kan worden bijgehouden."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"U bent verbonden met <xliff:g id="APPLICATION">%1$s</xliff:g>, waarmee je persoonlijke netwerkactiviteit kan worden gecontroleerd, inclusief e-mails, apps en websites."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Nieuw apparaat koppelen"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Build-nummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Build-nummer naar klembord gekopieerd."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index de48527f1980..264076f6b669 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"ବ୍ୟାଟେରୀର ଦୁଇଟି ବାର୍‍ ଅଛି।"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ବ୍ୟାଟେରୀର ତିନୋଟି ବାର୍‍ ଅଛି।"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ବ୍ୟାଟେରୀ ପୂର୍ଣ୍ଣ‍।"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"କୌଣସି ଫୋନ୍ ନାହିଁ।"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ଫୋନର ଗୋଟିଏ ବାର ଅଛି।"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ଫୋନର ଦୁଇଟି ବାର୍‌ ଅଛି।"</string>
@@ -520,6 +522,8 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"ପ୍ରୋଫାଇଲ୍ ନିରୀକ୍ଷଣ କରାଯାଇପାରେ।"</string>
<string name="vpn_footer" msgid="3457155078010607471">"ନେଟ୍‌ୱର୍କ ନୀରିକ୍ଷଣ କରାଯାଇପାରେ"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ନେଟ୍‌ୱର୍କକୁ ନିରୀକ୍ଷଣ କରାଯାଇପାରେ"</string>
+ <!-- no translation found for quick_settings_disclosure_parental_controls (2114102871438223600) -->
+ <skip />
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ଏହି ଡିଭାଇସର ମାଲିକାନା ଆପଣଙ୍କ ସଂସ୍ଥା ପାଖରେ ଅଛି ଏବଂ ଏହା ନେଟୱାର୍କ ଟ୍ରାଫିକର ନିରୀକ୍ଷଣ କରିପାରେ"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"ଏହି ଡିଭାଇସଟି <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>ର ଅଟେ ଏବଂ ଏହା ନେଟୱାର୍କ ଟ୍ରାଫିକକୁ ନିରୀକ୍ଷଣ କରିପାରେ"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ଏହି ଡିଭାଇସଟି ଆପଣଙ୍କ ସଂସ୍ଥାର ଅଟେ ଏବଂ ଏହା <xliff:g id="VPN_APP">%1$s</xliff:g> ସହ ସଂଯୁକ୍ତ ଅଛି"</string>
@@ -544,6 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN ଅକ୍ଷମ କରନ୍ତୁ"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN ବିଛିନ୍ନ କରନ୍ତୁ"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"ପଲିସୀ ଦେଖନ୍ତୁ"</string>
+ <!-- no translation found for monitoring_button_view_controls (8316440345340701117) -->
+ <skip />
<string name="monitoring_description_named_management" msgid="505833016545056036">"ଏହି ଡିଭାଇସଟି <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>ର ଅଟେ।\n\nଆପଣଙ୍କ IT ଆଡମିନ୍ ସେଟିଂସ୍, କର୍ପୋରେଟ୍ ଆକ୍ସେସ୍, ଆପ୍ସ, ଆପଣଙ୍କ ଡିଭାଇସ୍ ସହ ସମ୍ବନ୍ଧିତ ଡାଟା ଏବଂ ଆପଣଙ୍କ ଡିଭାଇସର ଲୋକେସନ୍ ସୂଚନାକୁ ନିରୀକ୍ଷଣ ଏବଂ ପରିଚାଳନା କରିପାରିବେ।\n\nଅଧିକ ସୂଚନା ପାଇଁ, ଆପଣଙ୍କ IT ଆଡମିନଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"ଏହି ଡିଭାଇସଟି ଆପଣଙ୍କ ସଂସ୍ଥାର ଅଟେ।\n\nଆପଣଙ୍କ IT ଆଡମିନ୍ ସେଟିଂସ୍, କର୍ପୋରେଟ୍ ଆକ୍ସେସ୍, ଆପ୍ସ, ଆପଣଙ୍କ ଡିଭାଇସ୍ ସହ ସମ୍ବନ୍ଧିତ ଡାଟା ଏବଂ ଆପଣଙ୍କ ଡିଭାଇସର ଲୋକେସନ୍ ସୂଚନାକୁ ନିରୀକ୍ଷଣ ଏବଂ ପରିଚାଳନା କରିପାରିବେ।\n\nଅଧିକ ସୂଚନା ପାଇଁ, ଆପଣଙ୍କ IT ଆଡମିନଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ଏହି ଡିଭାଇସରେ ଆପଣଙ୍କ ସଂସ୍ଥା ଏକ ସର୍ଟିଫିକେଟ୍‍ ଅଥରିଟି ଇନଷ୍ଟଲ୍‍ କରିଛନ୍ତି। ଆପଣଙ୍କ ସୁରକ୍ଷିତ ନେଟୱର୍କ ଟ୍ରାଫିକ୍‍ ନୀରିକ୍ଷଣ କିମ୍ବା ସଂଶୋଧନ କରାଯାଇ ପାରେ।"</string>
@@ -567,6 +573,8 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"ଆପଣଙ୍କ ଆଡମିନ୍‍ ନେଟ୍‌ୱର୍କ ଲଗଇନ୍‍ କରିବା ଅନ୍‍ କରିଛନ୍ତି, ଯାହା ଆପଣଙ୍କ ଡିଭାଇସରେ ଟ୍ରାଫିକ୍‍ ନିରୀକ୍ଷଣ କରେ।\n\nଅଧିକ ସୂଚନା ପାଇଁ, ନିଜ ଆଡମିନଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"ଏକ VPN ସଂଯୋଗ ସେଟ୍‍ ଅପ୍‍ କରିବା ପାଇଁ ଆପଣ ଗୋଟିଏ ଆପକୁ ଅନୁମତି ଦେଲେ।\n\nଏହି ଆପ୍‍ ଇମେଲ୍‍, ଆପ୍‌ ଓ ୱେବସାଇଟ୍‍ ସମେତ ଆପଣଙ୍କ ଡିଭାଇସ୍‍ ଓ ନେଟ୍‌ୱର୍କ ଗତିବିଧିକୁ ନିରୀକ୍ଷଣ କରିପାରେ।"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"ଆପଣଙ୍କ ୱର୍କ ପ୍ରୋଫାଇଲ୍‍ <xliff:g id="ORGANIZATION">%1$s</xliff:g> ଦ୍ୱାରା ପରିଚାଳନା କରାଯାଉଛି।\n\nଆପଣଙ୍କ ଆଡମିନ୍‍ ଇମେଲ୍‍, ଆପ୍‌ ଓ ୱେବସାଇଟ୍‍ ସମେତ ଆପଣଙ୍କ ନେଟୱର୍କ ଗତିବିଧିକୁ ନିରୀକ୍ଷଣ କରିପାରିବେ।\n\nଅଧିକ ସୂଚନା ପାଇଁ, ନିଜ ଆଡମିନଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।.\n\nଆପଣ ଏକ VPNରେ ମଧ୍ୟ ସଂଯୁକ୍ତ, ଯାହା ଆପଣଙ୍କ ନେଟୱର୍କ ଗତିବିଧିକୁ ନିରୀକ୍ଷଣ କରିପାରେ।"</string>
+ <!-- no translation found for monitoring_description_parental_controls (8184693528917051626) -->
+ <skip />
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"ଆପଣ <xliff:g id="APPLICATION">%1$s</xliff:g>ରେ ସଂଯୁକ୍ତ, ଯାହା ଇମେଲ୍‍, ଆପ୍‌ ଓ ୱେବସାଇଟ୍‍ ସମେତ ଆପଣଙ୍କ ନେଟୱର୍କ ଗତିବିଧିକୁ ନିରୀକ୍ଷଣ କରିପାରେ।"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"ଆପଣ <xliff:g id="APPLICATION">%1$s</xliff:g>ରେ ସଂଯୁକ୍ତ, ଯାହା ଇମେଲ୍‍, ଆପ୍‌ ଓ ୱେବସାଇଟ୍‍ ସମେତ ଆପଣଙ୍କ ନେଟ୍‌ୱର୍କ ଗତିବିଧିକୁ ନିରୀକ୍ଷଣ କରିପାରେ।"</string>
@@ -1089,4 +1097,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ନୂଆ ଡିଭାଇସକୁ ପେୟାର୍ କରନ୍ତୁ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ବିଲ୍ଡ ନମ୍ୱର"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"କ୍ଲିପବୋର୍ଡକୁ କପି କରାଯାଇଥିବା ବିଲ୍ଡ ନମ୍ୱର।"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 13f45067ce7a..d05f80d6698d 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"ਬੈਟਰੀ ਦੋ ਬਾਰਸ।"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"ਬੈਟਰੀ ਤਿੰਨ ਬਾਰਸ।"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"ਬੈਟਰੀ ਪੂਰੀ।"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"ਕੋਈ ਫ਼ੋਨ ਨਹੀਂ।"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ਫ਼ੋਨ ਇੱਕ ਬਾਰ।"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ਫ਼ੋਨ ਦੋ ਬਾਰਸ।"</string>
@@ -520,6 +522,8 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"ਪ੍ਰੋਫਾਈਲ ਦਾ ਨਿਰੀਖਣ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ"</string>
<string name="vpn_footer" msgid="3457155078010607471">"ਨੈੱਟਵਰਕ ਦਾ ਨਿਰੀਖਣ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ਹੋ ਸਕਦਾ ਹੈ ਨੈੱਟਵਰਕ ਦੀ ਨਿਗਰਾਨੀ ਹੋ ਰਹੀ ਹੋਵੇ"</string>
+ <!-- no translation found for quick_settings_disclosure_parental_controls (2114102871438223600) -->
+ <skip />
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਕੋਲ ਇਸ ਡੀਵਾਈਸ ਦੀ ਮਲਕੀਅਤ ਹੈ ਅਤੇ ਇਹ ਨੈੱਟਵਰਕ ਟਰੈਫ਼ਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ਕੋਲ ਇਸ ਡੀਵਾਈਸ ਦੀ ਮਲਕੀਅਤ ਹੈ ਅਤੇ ਇਹ ਨੈੱਟਵਰਕ ਟਰੈਫ਼ਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ਇਹ ਡੀਵਾਈਸ ਤੁਹਾਡੀ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ ਅਤੇ <xliff:g id="VPN_APP">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੈ"</string>
@@ -544,6 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN ਨੂੰ ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"ਨੀਤੀਆਂ ਦੇਖੋ"</string>
+ <!-- no translation found for monitoring_button_view_controls (8316440345340701117) -->
+ <skip />
<string name="monitoring_description_named_management" msgid="505833016545056036">"ਇਹ ਡੀਵਾਈਸ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ।\n\nਤੁਹਾਡਾ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨਾਲ ਸੰਬੰਧਿਤ ਸੈਟਿੰਗਾਂ, ਕਾਰਪੋਰੇਟ ਪਹੁੰਚ, ਐਪਾਂ, ਡਾਟੇ ਅਤੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਟਿਕਾਣਾ ਜਾਣਕਾਰੀ ਦੀ ਨਿਗਰਾਨੀ ਅਤੇ ਪ੍ਰਬੰਧਨ ਕਰ ਸਕਦਾ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"ਇਹ ਡੀਵਾਈਸ ਤੁਹਾਡੀ ਸੰਸਥਾ ਨਾਲ ਸੰਬੰਧਿਤ ਹੈ।\n\nਤੁਹਾਡਾ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਨਾਲ ਸੰਬੰਧਿਤ ਸੈਟਿੰਗਾਂ, ਕਾਰਪੋਰੇਟ ਪਹੁੰਚ, ਐਪਾਂ, ਡਾਟੇ ਅਤੇ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਦੀ ਟਿਕਾਣਾ ਜਾਣਕਾਰੀ ਦੀ ਨਿਗਰਾਨੀ ਅਤੇ ਪ੍ਰਬੰਧਨ ਕਰ ਸਕਦਾ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਆਈ.ਟੀ. ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ਤੁਹਾਡੀ ਸੰਸਥਾ ਵੱਲੋਂ ਇਸ ਡੀਵਾਈਸ \'ਤੇ ਇੱਕ ਪ੍ਰਮਾਣ-ਪੱਤਰ ਅਥਾਰਟੀ ਸਥਾਪਤ ਕੀਤੀ ਗਈ ਹੈ। ਤੁਹਾਡੇ ਸੁਰੱਖਿਅਤ ਨੈੱਟਵਰਕ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ ਜਾਂ ਉਸਨੂੰ ਸੋਧਿਆ ਜਾ ਸਕਦਾ ਹੈ।"</string>
@@ -567,6 +573,8 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"ਤੁਹਾਡੇ ਪ੍ਰਸ਼ਾਸਕ ਨੇ ਨੈੱਟਵਰਕ ਲੌਗਿੰਗ ਨੂੰ ਚਾਲੂ ਕੀਤਾ ਹੋਇਆ ਹੈ, ਜੋ ਤੁਹਾਡੇ ਡੀਵਾਈਸ \'ਤੇ ਟਰੈਫਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰਦਾ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"ਤੁਸੀਂ ਕਿਸੇ ਐਪ ਨੂੰ ਇੱਕ VPN ਕਨੈਕਸ਼ਨ ਸੈੱਟ ਅੱਪ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੱਤੀ ਹੈ।\n\nਇਹ ਐਪ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਅਤੇ ਨੈੱਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦੀ ਹੈ, ਈਮੇਲਾਂ, ਐਪਾਂ ਅਤੇ ਸੁਰੱਖਿਅਤ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ।"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"ਤੁਹਾਡੇ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਦਾ ਪ੍ਰਬੰਧਨ <xliff:g id="ORGANIZATION">%1$s</xliff:g> ਵੱਲੋਂ ਕੀਤਾ ਜਾਂਦਾ ਹੈ।\n\nਤੁਹਾਡਾ ਪ੍ਰਸ਼ਾਸਕ ਈਮੇਲ, ਐਪਾਂ, ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰਨ ਦੇ ਸਮਰੱਥ ਹੈ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਸ਼ਾਸਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।\n\nਤੁਸੀਂ ਇੱਕ VPN ਨਾਲ ਵੀ ਕਨੈਕਟ ਹੋਂ, ਜੋ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦਾ ਹੈ।"</string>
+ <!-- no translation found for monitoring_description_parental_controls (8184693528917051626) -->
+ <skip />
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"ਤੁਸੀਂ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋ, ਜੋ ਈਮੇਲਾਂ, ਐਪਾਂ ਅਤੇ ਵੈੱਬਸਾਈਟਾਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈਟਵਰਕ ਸਰਗਰਮੀ ਦੀ ਨਿਗਰਾਨੀ ਕਰ ਸਕਦੀ ਹੈ।"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"ਤੁਸੀਂ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਹੋ, ਜੋ ਈਮੇਲ, ਐਪਸ ਅਤੇ ਵੈਬਸਫ਼ਿਆਂ ਸਮੇਤ ਤੁਹਾਡੀ ਨੈੱਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦੀ ਹੈ।"</string>
@@ -1089,4 +1097,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"ਨਵਾਂ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"ਬਿਲਡ ਨੰਬਰ"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"ਬਿਲਡ ਨੰਬਰ ਨੂੰ ਕਲਿੱਪਬੋਰਡ \'ਤੇ ਕਾਪੀ ਕੀਤਾ ਗਿਆ।"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 6da167dffd34..7343b26c18ab 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Bateria: dwa paski."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Bateria: trzy paski."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria naładowana."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Brak sygnału telefonu."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon: jeden pasek."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon: dwa paski."</string>
@@ -526,6 +528,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil może być monitorowany"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Sieć może być monitorowana"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Sieć może być monitorowana"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Tym urządzeniem zarządza Twój rodzic"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Twoja organizacja jest właścicielem tego urządzenia i może monitorować ruch w sieci"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Organizacja <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> jest właścicielem tego urządzenia i może monitorować ruch w sieci"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"To urządzenie należy do Twojej organizacji i jest połączone z siecią <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -550,6 +553,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Wyłącz VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Rozłącz z VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Zobacz zasady"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Wyświetl elementy sterujące"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"To urządzenie należy do organizacji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nAdministrator IT może monitorować ustawienia, firmowe uprawnienia dostępu, aplikacje, dane dotyczące urządzenia i lokalizacji oraz nimi zarządzać.\n\nAby dowiedzieć się więcej, skontaktuj się z administratorem IT."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"To urządzenie należy do Twojej organizacji.\n\nAdministrator IT może monitorować ustawienia, firmowe uprawnienia dostępu, aplikacje, dane dotyczące urządzenia i lokalizacji oraz nimi zarządzać.\n\nAby dowiedzieć się więcej, skontaktuj się z administratorem IT."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Twoja organizacja zainstalowała urząd certyfikacji na tym urządzeniu. Zabezpieczony ruch w sieci może być monitorowany i zmieniany."</string>
@@ -573,6 +577,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Administrator włączył rejestrowanie sieciowe, które pozwala monitorować ruch na Twoim urządzeniu.\n\nAby dowiedzieć się więcej, skontaktuj się z administratorem."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Aplikacja otrzymała od Ciebie uprawnienia do konfigurowania połączenia VPN.\n\nMoże ona monitorować Twoją aktywność na urządzeniu i w sieci, w tym e-maile, aplikacje i strony internetowe."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Twoim profilem do pracy zarządza <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministrator może monitorować Twoją aktywność w sieci, w tym e-maile, aplikacje i strony internetowe.\n\nAby dowiedzieć się więcej, skontaktuj się z administratorem.\n\nŁączysz się też z siecią VPN, która może monitorować Twoją aktywność w sieci."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Tym urządzeniem zarządza Twój rodzic. Rodzic może zobaczyć różne informacje, np. o aplikacjach, których używasz, lokalizacji i czasie korzystania z urządzenia, a także zarządzać tymi danymi."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Łączysz się z aplikacją <xliff:g id="APPLICATION">%1$s</xliff:g>, która może monitorować Twoją aktywność w sieci, w tym e-maile, aplikacje i strony internetowe."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Masz połączenie z aplikacją <xliff:g id="APPLICATION">%1$s</xliff:g>, która może monitorować Twoją prywatną aktywność w sieci, w tym e-maile, aplikacje i strony internetowe."</string>
@@ -1101,4 +1106,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sparuj nowe urządzenie"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numer kompilacji"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numer kompilacji został skopiowany do schowka."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 0db05d895746..344671d1df9c 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Duas barras de bateria."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Três barras de bateria."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria cheia."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Sem telefone."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Uma barra de sinal do telefone."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Duas barras de sinal do telefone."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"O perfil pode ser monitorado"</string>
<string name="vpn_footer" msgid="3457155078010607471">"A rede pode ser monitorada"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"A rede pode ser monitorada"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu pai/mãe"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Sua organização é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"A organização <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Este dispositivo pertence à sua organização e está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Desativar VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Desconectar VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Ver políticas"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Controles de visualização"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Este dispositivo pertence à organização <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nO administrador de TI pode monitorar e gerenciar configurações, acesso corporativo, apps, dados associados ao dispositivo e informações de local do dispositivo.\n\nPara saber mais, entre em contato com seu administrador de TI."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Este dispositivo pertence à sua organização.\n\nO administrador de TI pode monitorar e gerenciar configurações, acesso corporativo, apps, dados associados ao dispositivo e informações de local do dispositivo.\n\nPara saber mais, entre em contato com seu administrador de TI."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Sua organização instalou uma autoridade de certificação neste dispositivo. É possível monitorar ou modificar seu tráfego de rede seguro."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Seu administrador ativou o registro de rede, que monitora o tráfego no seu dispositivo.\n\nPara ver mais informações, entre em contato com o administrador."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Você deu permissão para um app configurar uma conexão VPN.\n\nEsse app pode monitorar seu dispositivo e a atividade na rede, incluindo e-mails, apps e websites."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Seu perfil de trabalho é gerenciado por <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nSeu administrador pode monitorar sua atividade de rede, incluindo e-mails, apps e websites.\n\nPara ver mais informações, entre em contato com o administrador.\n\nVocê também está conectado a uma VPN, que pode monitorar sua atividade de rede."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu pai/mãe, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de uso."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Você está conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorar sua atividade de rede, incluindo e-mails, apps e websites."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Você está conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorar sua atividade pessoal na rede, incluindo e-mails, apps e websites."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parear novo dispositivo"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número da versão copiado para a área de transferência."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 147ed1d7eebf..709f532bb50c 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Duas barras de bateria."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Três barras de bateria."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria carregada."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Sem telefone."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Uma barra de telefone."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Duas barras de telefone."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"O perfil pode ser monitorizado"</string>
<string name="vpn_footer" msgid="3457155078010607471">"A rede pode ser monitorizada"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"A rede pode ser monitorizada"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerido pelos teus pais"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"A sua entidade gere este dispositivo e pode monitorizar o tráfego de rede."</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"A entidade <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é proprietária deste dispositivo e pode monitorizar o tráfego de rede."</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Este dispositivo pertence à sua entidade e está ligado a <xliff:g id="VPN_APP">%1$s</xliff:g>."</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Desativar a VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Desligar VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Ver Políticas"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Ver controlos"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Este dispositivo pertence à entidade <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nO administrador de TI pode monitorizar e gerir as definições, o acesso empresarial, as apps, os dados associados ao dispositivo e as informações de localização do mesmo.\n\nContacte o administrador de TI para obter mais informações."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Este dispositivo pertence à sua entidade.\n\nO administrador de TI pode monitorizar e gerir as definições, o acesso empresarial, as apps, os dados associados ao dispositivo e as informações de localização do mesmo.\n\nContacte o administrador de TI para obter mais informações."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"A sua entidade instalou uma autoridade de certificação neste dispositivo. O tráfego da sua rede segura pode ser monitorizado ou alterado."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"O seu gestor ativou os registos de rede, que monitorizam o tráfego no seu dispositivo.\n\nPara obter mais informações, contacte o gestor."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Concedeu autorização a uma app para configurar uma ligação VPN.\n\nEsta app pode monitorizar a atividade do dispositivo e da rede, incluindo emails, aplicações e Sites."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"O seu perfil de trabalho é gerido por <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nO seu gestor tem a capacidade de monitorizar a sua atividade da rede, incluindo emails, aplicações e Sites.\n\nPara obter mais informações, contacte o gestor.\n\nAlém disso, está ligado a uma VPN, que pode monitorizar a sua atividade da rede."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerido pelos teus pais. Estes podem ver e gerir informações como as apps que utilizas, a tua localização e o tempo de utilização."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Está associado à app <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Está ligado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a atividade da rede pessoal, incluindo emails, aplicações e Sites."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Sincronize o novo dispositivo"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da compilação"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número da compilação copiado para a área de transferência."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 0db05d895746..344671d1df9c 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Duas barras de bateria."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Três barras de bateria."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria cheia."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Sem telefone."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Uma barra de sinal do telefone."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Duas barras de sinal do telefone."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"O perfil pode ser monitorado"</string>
<string name="vpn_footer" msgid="3457155078010607471">"A rede pode ser monitorada"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"A rede pode ser monitorada"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Este dispositivo é gerenciado pelo seu pai/mãe"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Sua organização é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"A organização <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> é dona deste dispositivo e pode monitorar o tráfego de rede"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Este dispositivo pertence à sua organização e está conectado a <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Desativar VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Desconectar VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Ver políticas"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Controles de visualização"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Este dispositivo pertence à organização <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nO administrador de TI pode monitorar e gerenciar configurações, acesso corporativo, apps, dados associados ao dispositivo e informações de local do dispositivo.\n\nPara saber mais, entre em contato com seu administrador de TI."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Este dispositivo pertence à sua organização.\n\nO administrador de TI pode monitorar e gerenciar configurações, acesso corporativo, apps, dados associados ao dispositivo e informações de local do dispositivo.\n\nPara saber mais, entre em contato com seu administrador de TI."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Sua organização instalou uma autoridade de certificação neste dispositivo. É possível monitorar ou modificar seu tráfego de rede seguro."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Seu administrador ativou o registro de rede, que monitora o tráfego no seu dispositivo.\n\nPara ver mais informações, entre em contato com o administrador."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Você deu permissão para um app configurar uma conexão VPN.\n\nEsse app pode monitorar seu dispositivo e a atividade na rede, incluindo e-mails, apps e websites."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Seu perfil de trabalho é gerenciado por <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nSeu administrador pode monitorar sua atividade de rede, incluindo e-mails, apps e websites.\n\nPara ver mais informações, entre em contato com o administrador.\n\nVocê também está conectado a uma VPN, que pode monitorar sua atividade de rede."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Este dispositivo é gerenciado pelo seu pai/mãe, que pode ver e gerenciar informações como os apps que você usa, sua localização e seu tempo de uso."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Você está conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorar sua atividade de rede, incluindo e-mails, apps e websites."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Você está conectado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorar sua atividade pessoal na rede, incluindo e-mails, apps e websites."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parear novo dispositivo"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Número da versão"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Número da versão copiado para a área de transferência."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 24e71fbe1392..6c544604821c 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Baterie: două bare."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterie: trei bare."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Baterie: complet."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Nu există semnal pentru telefon."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Semnal pentru telefon: o bară."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Semnal pentru telefon: două bare."</string>
@@ -523,6 +525,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profilul poate fi monitorizat"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Rețeaua poate fi monitorizată"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Este posibil ca rețeaua să fie monitorizată"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Dispozitivul este gestionat de unul dintre părinți"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organizația dvs. deține acest dispozitiv și poate monitoriza traficul de rețea"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> deține acest dispozitiv și poate monitoriza traficul din rețea"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Dispozitivul aparține organizației dvs. și este conectat la <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -547,6 +550,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Dezactivați conexiunea prin VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Deconectați rețeaua VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Afișați politicile"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Vedeți opțiunile"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Dispozitivul aparține organizației <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nAdministratorul dvs. IT poate să monitorizeze și să gestioneze setările, accesul la nivelul companiei, aplicațiile, datele asociate dispozitivului și informațiile despre locația dispozitivului.\n\nPentru mai multe informații, contactați administratorul IT."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Dispozitivul aparține organizației dvs.\n\nAdministratorul dvs. IT poate să monitorizeze și să gestioneze setările, accesul la nivelul companiei, aplicațiile, datele asociate dispozitivului și informațiile despre locația dispozitivului.\n\nPentru mai multe informații, contactați administratorul IT."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organizația dvs. a instalat un certificat CA pe acest dispozitiv. Traficul dvs. sigur de rețea poate fi monitorizat sau modificat."</string>
@@ -570,6 +574,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Administratorul dvs. a activat înregistrarea în jurnal pentru rețea, funcție ce monitorizează traficul de pe dispozitivul dvs.\n\nPentru mai multe informații, contactați administratorul."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Ați acordat unei aplicații permisiunea de a configura o conexiune VPN.\n\nAceastă aplicație poate monitoriza activitatea de pe dispozitiv și în rețea, inclusiv e-mailurile, aplicațiile și site-urile."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Profilul dvs. de serviciu este gestionat de <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministratorul dvs. vă poate monitoriza activitatea în rețea, inclusiv e-mailurile, aplicațiile și site-urile.\n\nPentru mai multe informații, contactați administratorul.\n\nDe asemenea, sunteți conectat(ă) la o rețea VPN care vă poate monitoriza activitatea în rețea."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Dispozitivul este gestionat de unul dintre părinți. Părintele poate să vadă și să gestioneze informații cum ar fi aplicațiile pe care le folosești, locația ta și durata de folosire a dispozitivului."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"V-ați conectat la <xliff:g id="APPLICATION">%1$s</xliff:g>, care vă poate monitoriza activitatea în rețea, inclusiv e-mailurile, aplicațiile și site-urile accesate."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Sunteți conectat(ă) la <xliff:g id="APPLICATION">%1$s</xliff:g>, care vă poate monitoriza activitatea în rețeaua personală, inclusiv e-mailurile, aplicațiile și site-urile."</string>
@@ -1095,4 +1100,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Asociați un nou dispozitiv"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numărul versiunii"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numărul versiunii s-a copiat în clipboard."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 1ca1c80738c2..53773cf4d253 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Заряд батареи: два деления."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Заряд батареи: три деления."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Батарея полностью заряжена."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Сигнал телефонной сети отсутствует."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Сигнал телефонной сети: одно деление."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Сигнал телефонной сети: два деления."</string>
@@ -526,6 +528,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Действия в профиле могут отслеживаться"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Сеть может отслеживаться"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Сеть может отслеживаться"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Этим устройством управляет один из твоих родителей."</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Ваша организация управляет этим устройством и может отслеживать сетевой трафик"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Организация \"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>\" управляет этим устройством и может отслеживать сетевой трафик"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Это устройство принадлежит вашей организации и подключено к приложению \"<xliff:g id="VPN_APP">%1$s</xliff:g>\""</string>
@@ -550,6 +553,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Отключить VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Отключить VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Просмотреть политику"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Показать элементы управления"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Это устройство принадлежит организации \"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>\".\n\nВаш системный администратор может управлять настройками, приложениями и параметрами доступа к корпоративным ресурсам на этом устройстве, а также связанными с ним данными (например, сведениями о местоположении).\n\nЗа подробной информацией обращайтесь к системному администратору."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Это устройство принадлежит вашей организации.\n\nСистемный администратор может управлять настройками, приложениями и параметрами доступа к корпоративным ресурсам на этом устройстве, а также связанными с ним данными (например, сведениями о местоположении).\n\nЗа подробной информацией обращайтесь к системному администратору."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Ваша организация установила сертификат ЦС на устройство. Она может отслеживать и изменять защищенный сетевой трафик."</string>
@@ -573,6 +577,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Администратор включил ведение сетевого журнала, чтобы отслеживать трафик на вашем устройстве.\n\nДля получения подробной информации обращайтесь к администратору."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Вы разрешили приложению подключаться к сети VPN.\n\nОно может отслеживать ваши действия на устройстве и в Интернете, включая работу с электронной почтой, приложениями и веб-сайтами."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Вашим рабочим профилем управляет <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nАдминистратор может отслеживать ваши действия в сети, в том числе работу с электронной почтой, приложениями и веб-сайтами.\n\nДля получения подробной информации обращайтесь к администратору.\n\nВы также подключены к сети VPN, в которой можно отслеживать ваши действия."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Этим устройством управляет один из твоих родителей. Он может видеть определенные сведения (например, какие приложения ты используешь и где находишься), а также устанавливать определенные настройки (например, ограничивать время использования устройства)."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"Сеть VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Запущено приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\", которое может отслеживать ваши действия в сети, включая работу с электронной почтой, приложениями и веб-сайтами."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Запущено приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\", которое может отслеживать ваши действия в Интернете (выполняемые в личном профиле), включая работу с электронной почтой, приложениями и веб-сайтами."</string>
@@ -1101,4 +1106,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Подключить новое устройство"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер сборки"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Номер сборки скопирован в буфер обмена."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index eb789c1e9181..afd556ac074f 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"බැටරිය තීරු දෙකයි."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"බැටරිය තීරු තුනයි."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"බැටරිය පිරී ඇත."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"දුරකථනයක් නැත."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"දුරකථනය තීරු එකයි."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"දුරකථනය තීරු දෙකයි."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"ඇතැම් විට පැතිකඩ නිරීක්ෂණය කරන ලදි"</string>
<string name="vpn_footer" msgid="3457155078010607471">"ඇතැම් විට ජාලය නිරීක්ෂණය විය හැක"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"ඇතැම් විට ජාලය නිරීක්ෂණය විය හැක"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"මෙම උපාංගය ඔබගේ මාපියන්ගෙන් අයකු විසින් කළමනාකරණය කෙරේ"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ඔබේ සංවිධානයට මෙම උපාංගය අයිති අතර ජාල තදබදය නිරීක්ෂණය කළ හැකිය"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> සංවිධානයට මෙම උපාංගය අයිති අතර ජාල තදබදය නිරීක්ෂණය කළ හැකිය"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"මෙම උපාංගය ඔබේ සංවිධානයට අයිති අතර <xliff:g id="VPN_APP">%1$s</xliff:g> වෙත සම්බන්ධ කර ඇත"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN අබල කරන්න."</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN විසන්ධි කරන්න"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"ප්‍රතිපත්ති පෙන්වන්න"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"පාලන බලන්න"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"මෙම උපාංගය <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> සංවිධානයට අයිතිය.\n\nඔබේ IT පරිපාලකට ඔබේ උපාංගය හා සම්බන්ධිත සැකසීම්, ආයතනික ප්‍රවේශය, යෙදුම්, දත්ත සහ ඔබේ උපාංගයේ ස්ථාන තොරතුරු නිරීක්ෂණය කර කළමනාකරණය කිරීමට හැකිය.\n\nවැඩිදුර තොරතුරු සඳහා, ඔබේ IT අමතන්න."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"මෙම උපාංගය ඔබේ සංවිධානයට අයිතිය.\n\nඔබේ IT පරිපාලකට ඔබේ උපාංගය හා සම්බන්ධිත සැකසීම්, ආයතනික ප්‍රවේශය, යෙදුම්, දත්ත සහ ඔබේ උපාංගයේ ස්ථාන තොරතුරු නිරීක්ෂණය කර කළමනාකරණය කිරීමට හැකිය.\n\nවැඩිදුර තොරතුරු සඳහා, ඔබේ IT අමතන්න."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ඔබගේ සංවිධානය ඔබගේ උපාංගය තුළ සහතික අධිකාරියක් ස්ථාපනය කර තිබේ. ඔබගේ ආරක්ෂක ජාල තදබදය නිරීක්ෂණය හෝ වෙනස් කිරීමට පුළුවනි."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"ඔබගේ පරිපාලක ඔබගේ උපාංගය මත තදබදය නිරීක්ෂණය කරන, ජාල ඇතුළු වීම ක්‍රියාත්මක කර ඇත.\n\nවැඩිදුර තොරතුරු සඳහා ඔබේ පරිපාලක අමතන්න."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"ඔබ VPN සම්බන්ධතාවක් පිහිටුවීමට යෙදුමකට අවසරයක් දී ඇත.\n\nමෙම යෙදුමට ඔබේ ඊ-තැපැල්, යෙදුම්, සහ වෙබ් අඩවි ඇතුළු, ඔබගේ උපාංග සහ ජාල ක්‍රියාකාරකම් නිරීක්ෂණය කිරීමට හැකිය."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"ඔබේ කාර්ය පැතිකඩ කළමනාකරණය කරන්නේ <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nඔබේ පරිපාලකට ඔබේ ඊ-තැපැල්, යෙදුම්, සහ වෙබ් අඩවි ඇතුළු, ඔබේ ජාල ක්‍රියාකාරකම් නිරීක්ෂණය කළ හැකිය.\n\nවැඩිදුර තොරතුරු සඳහා, ඔබගේ පරිපාලක අමතන්න.\n\nඔබේ ජාල ක්‍රියාකාරකම් නිරීක්ෂණය කළ හැකි, VPN එකකටද ඔබ සබැඳී ඇත"</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"මෙම උපාංගය ඔබගේ මාපියන් විසින් කළමනාකරණය කෙරේ. ඔබ භාවිත කරන යෙදුම්, ඔබගේ ස්ථානය සහ ඔබගේ තිර කාලය වැනි තොරතුරු ඔබගේ මාපියන්ට බැලීමට සහ කළමනාකරණය කිරීමට හැකිය."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"ඊ-තැපැල්, යෙදුම් සහ වෙබ් අඩවි ඇතුළු ඔබේ ජාල ක්‍රියාකාරකම් නිරීක්ෂණය කළ හැකි, <xliff:g id="APPLICATION">%1$s</xliff:g> වෙත ඔබ සම්බන්ධ වී ඇත."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"ඊ-තැපැල්, යෙදුම් සහ වෙබ් අඩවි ඇතුළු ඔබේ පෞද්ගලික ජාල ක්‍රියාකාරකම් නිරීක්ෂණය කළ හැකි, <xliff:g id="APPLICATION">%1$s</xliff:g> වෙත ඔබ සම්බන්ධ වී ඇත."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"නව උපාංගය යුගල කරන්න"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"නිමැවුම් අංකය"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"නිමැවුම් අංකය පසුරු පුවරුවට පිටපත් කරන ලදි."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 9ec0771c89f9..4c518dcc8379 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Dve čiarky batérie."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Tri čiarky batérie."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batéria je nabitá."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Žiadna telefónna sieť."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Jeden stĺpec signálu telefónnej siete."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Dve čiarky signálu telefónnej siete."</string>
@@ -526,6 +528,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil môže byť monitorovaný"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Sieť môže byť sledovaná"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Sieť môže byť monitorovaná"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Toto zariadenie spravuje tvoj rodič"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Vaša organizácia spravuje toto zariadenie a môže sledovať sieťovú premávku"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> vlastní toto zariadenie a môže sledovať sieťovú premávku"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Toto zariadenie patrí vašej organizácii a je pripojené k sieti <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -550,6 +553,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Deaktivovať VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Odpojiť sieť VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Zobraziť pravidlá"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Zobraziť ovládacie prvky"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Toto zariadenie patrí organizácii <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nVáš správca IT môže sledovať a spravovať nastavenia, podnikový prístup, aplikácie, údaje spojené s vaším zariadení a informácie o jeho polohe.\n\nViac sa dozviete od správcu IT."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Toto zariadenie patrí vašej organizácii.\n\nVáš správca IT môže sledovať a spravovať nastavenia, podnikový prístup, aplikácie, údaje spojené s vaším zariadením a informácie o jeho polohe.\n\n. Viac sa dozviete od správcu IT."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organizácia nainštalovala pre toto zariadenie certifikačnú autoritu. Zabezpečená sieťová premávka môže byť sledovaná či upravená."</string>
@@ -573,6 +577,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Správca aktivoval zapisovanie do denníka siete, ktoré sleduje premávku na vašom zariadení.\n\nĎalšie informácie vám poskytne správca."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Určitej aplikácii ste udelili povolenie nastaviť pripojenie VPN.\n\nTáto aplikácia môže sledovať vaše zariadenie a aktivitu v sieti vrátane e-mailových správ, aplikácií a webových stránok."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Váš pracovný profil spravuje organizácia <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nSprávca môže sledovať vašu aktivitu v sieti vrátane e-mailov, aplikácií a webov.\n\nĎalšie informácie vám poskytne správca.\n\nMáte tiež aktívne pripojenie k sieti VPN, ktorá môže sledovať vašu aktivitu v rámci siete."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Toto zariadenie spravuje tvoj rodič. Vidí a môže spravovať informácie, napríklad aplikácie, ktoré používaš, tvoju polohu a čas používania."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Pripojili ste sa k aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g>, ktorá môže sledovať vašu aktivitu v sieti vrátane správ, aplikácií a webových stránok."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Ste pripojený/-á k aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g>, ktorá môže sledovať vašu osobnú aktivitu v sieti vrátane e-mailových správ, aplikácií a webových stránok."</string>
@@ -1101,4 +1106,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Spárovať nové zariadenie"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Číslo zostavy"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Číslo zostavy bolo skopírované do schránky."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 14f6553ddcfc..f459bc864605 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Baterija z dvema črticama."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterija s tremi črticami."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Baterija je polna."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Ni telefona."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon z eno črtico."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon z dvema črticama."</string>
@@ -526,6 +528,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil je morda nadziran"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Omrežje je lahko nadzorovano"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Omrežje je morda nadzorovano"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"To napravo upravlja tvoj starš"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Vaša organizacija je lastnica te naprave in lahko nadzira omrežni promet"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Organizacija <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> je lastnica te naprave in lahko nadzira omrežni promet"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Ta naprava pripada vaši organizaciji in je povezana v aplikacijo <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -550,6 +553,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Onemogoči VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Prekini povezavo z VPN-jem"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Prikaži pravilnike"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Ogled kontrolnikov"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Ta naprava pripada organizaciji <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nSkrbnik za IT lahko nadzira in upravlja nastavitve, dostop za podjetje, aplikacije, z napravo povezane podatke in podatke o lokaciji naprave.\n\nZa več informacij se obrnite na skrbnika za IT."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Ta naprava pripada vaši organizaciji.\n\nSkrbnik za IT lahko nadzira in upravlja nastavitve, dostop za podjetje, aplikacije, z napravo povezane podatke in podatke o lokaciji naprave.\n\nZa več informacij se obrnite na skrbnika za IT."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Vaša organizacija je v to napravo namestila overitelja potrdil. Varni omrežni promet se lahko nadzira ali spreminja."</string>
@@ -573,6 +577,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Skrbnik je vklopil beleženje omrežnega prometa, ki nadzoruje promet v napravi.\n\nČe želite več informacij, se obrnite na skrbnika."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Aplikaciji ste dovolili vzpostavitev povezave VPN.\n\nTa aplikacija lahko nadzira napravo in omrežno dejavnost, vključno z e-pošto, aplikacijami in spletnimi mesti."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Delovni profil upravlja <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nSkrbnik lahko nadzira vašo omrežno dejavnost, vključno z e-pošto, aplikacijami in spletnimi mesti.\n\nČe želite več informacij, se obrnite na skrbnika.\n\nPovezani ste tudi z omrežjem VPN, ki lahko nadzira vašo omrežno dejavnost."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"To napravo upravlja tvoj starš. Tvoj starš si lahko ogleda in upravlja podatke, na primer katere aplikacije uporabljaš, tvojo lokacijo in koliko časa uporabljaš telefon."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Povezani ste z aplikacijo <xliff:g id="APPLICATION">%1$s</xliff:g>, ki lahko nadzira omrežno dejavnost, vključno z e-pošto, aplikacijami in spletnimi mesti."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Povezani ste z aplikacijo <xliff:g id="APPLICATION">%1$s</xliff:g>, ki lahko nadzira vašo osebno omrežno dejavnost, vključno z e-pošto, aplikacijami in spletnimi mesti."</string>
@@ -1101,4 +1106,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Seznanitev nove naprave"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Delovna različica"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Delovna različica je bila kopirana v odložišče."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 87ca508d3893..73408cee8321 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Bateria ka edhe dy vija."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Bateria ka edhe tre vija."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Bateria u mbush."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Nuk ka telefon."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefoni ka edhe një vijë."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefoni ka dy vija."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profili mund të monitorohet"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Rrjeti mund të jetë i monitoruar"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Rrjeti mund të jetë i monitoruar"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Kjo pajisje menaxhohet nga prindi yt."</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organizata jote e zotëron këtë pajisje dhe mund të monitorojë trafikun e rrjetit"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> e zotëron këtë pajisje dhe mund të monitorojë trafikun e rrjetit"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Kjo pajisje i përket organizatës sate dhe është e lidhur me <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Çaktivizo VPN-në"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Shkëput VPN-në"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Shiko politikat"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Shiko kontrollet"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Kjo pajisje i përket <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nAdministratori i teknologjisë së informacionit mund të monitorojë dhe menaxhojë cilësimet, qasjen e korporatës, aplikacionet, të dhënat e lidhura me pajisjen tënde, si dhe informacionet e vendndodhjes së pajisjes tënde.\n\nPër më shumë informacione, kontakto me administratorin e teknologjisë së informacionit."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Kjo pajisje i përket organizatës sate.\n\nAdministratori i teknologjisë së informacionit mund të monitorojë dhe menaxhojë cilësimet, qasjen e korporatës, aplikacionet, të dhënat e lidhura me pajisjen tënde, si dhe informacionet e vendndodhjes së pajisjes tënde.\n\nPër më shumë informacione, kontakto me administratorin e teknologjisë së informacionit."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organizata jote instaloi një autoritet certifikate në këtë pajisje. Trafiku i rrjetit tënd të sigurt mund të monitorohet ose modifikohet."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Administratori yt ka aktivizuar regjistrimin e rrjetit, i cili monitoron trafikun në pajisjen tënde.\n\nPër më shumë informacione, kontakto me administratorin."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"I dhe leje një aplikacioni që të konfigurojë një lidhje VPN.\n\nKy aplikacion mund të monitorojë pajisjen tënde dhe aktivitetin e rrjetit, përfshirë email-et, aplikacionet dhe sajtet e uebit."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Profili yt i punës menaxhohet nga <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministratori yt mund të monitorojë aktivitetin tënd të rrjetit, duke përfshirë email-et, aplikacionet dhe sajtet e uebit.\n\nPër më shumë informacion, kontakto me administratorin tënd.\n\nJe i lidhur edhe me një VPN, që mund të monitorojë aktivitetin tënd të rrjetit."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Kjo pajisje menaxhohet nga prindi yt. Prindi yt mund të shohë e menaxhojë informacionin, si p.sh. aplikacionet që përdor, vendndodhjen tënde dhe kohën para ekranit."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Je i lidhur me aplikacionin <xliff:g id="APPLICATION">%1$s</xliff:g> i cili mund të monitorojë aktivitetin tënd në rrjet, duke përfshirë mail-et, aplikacionet dhe sajtet e uebit."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Je i lidhur me aplikacionin <xliff:g id="APPLICATION">%1$s</xliff:g>, i cili mund të monitorojë aktivitetin tënd personal në rrjet, përfshirë email-et, aplikacionet dhe sajtet e uebit."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Çifto pajisjen e re"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numri i ndërtimit"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Numri i ndërtimit u kopjua te kujtesa e fragmenteve"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 1ad7a91e551d..d173f007bd2b 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Батерија од две црте."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Батерија од три црте."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Батерија је пуна."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Нема телефона."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Сигнал телефона има једну црту."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Сигнал телефона од две црте."</string>
@@ -523,6 +525,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Профил се можда надгледа"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Мрежа се можда надгледа"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Мрежа се можда надгледа"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Овим уређајем управља родитељ"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Организација је власник уређаја и може да надгледа мрежни саобраћај"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> је власник овог уређаја и може да надгледа мрежни саобраћај"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Овај уређај припада организацији и повезан је са апликацијом <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -547,6 +550,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Онемогући VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Прекини везу са VPN-ом"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Прикажи смернице"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Прикажи контроле"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Овај уређај припада организацији <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nИТ администратор може да надгледа подешавања, корпоративни приступ, апликације, податке повезане са уређајем и информације о локацији уређаја, као и да управља њима.\n\nВише информација потражите од ИТ администратора."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Овај уређај припада организацији.\n\nИТ администратор може да надгледа подешавања, корпоративни приступ, апликације, податке повезане са уређајем и информације о локацији уређаја, као и да управља њима.\n\nВише информација потражите од ИТ администратора."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Организација је на овом уређају инсталирала ауторитет за издавање сертификата. Безбедни мрежни саобраћај може да се прати или мења."</string>
@@ -570,6 +574,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Администратор је укључио евидентирање мреже, које прати саобраћај на уређају.\n\nКонтактирајте администратора за више информација."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Дали сте дозволу апликацији да подешава VPN везу.\n\nТа апликација може да надгледа активности на уређају и мрежи, укључујући имејлове, апликације и веб-сајтове."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> управља пословним профилом.\n\nАдминистратор може да прати активности на мрежи, укључујући имејлове, апликације и веб-сајтове.\n\nКонтактирајте администратора за више информација.\n\nПовезани сте и са VPN-ом, који може да прати активности на мрежи."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Овим уређајем управља родитељ. Родитељ може да види информације, као што су апликације које користиш, твоју локацију и време испред екрана, и да управља њима."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Повезани сте са апликацијом <xliff:g id="APPLICATION">%1$s</xliff:g>, која може да надгледа активности на мрежи, укључујући имејлове, апликације и веб-сајтове."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Повезани сте са апликацијом <xliff:g id="APPLICATION">%1$s</xliff:g>, која може да надгледа активности на личној мрежи, укључујући имејлове, апликације и веб-сајтове."</string>
@@ -1095,4 +1100,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Упари нови уређај"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Број верзије"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Број верзије је копиран у привремену меморију."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index d34c814f2aa7..b79fb40e2324 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Batteri: två staplar."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batteri: tre staplar."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batteriet är fulladdat."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Ingen telefon."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon: en stapel."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon: två staplar."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Det kan hända att profilen övervakas"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Nätverket kan vara övervakat"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Nätverket kan vara övervakat"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Den här enheten hanteras av din förälder"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Organisationen äger den här enheten och kan övervaka nätverkstrafiken"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> äger den här enheten och kan övervaka nätverkstrafiken"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Den här enheten tillhör organisationen och är ansluten till <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Inaktivera VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Koppla från VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Visa policyer"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Visa kontroller"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Den här enheten tillhör <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nIT-administratören kan övervaka och hantera inställningar, företagsåtkomst, appar, data med koppling till enheten och enhetens plats.\n\nKontakta IT-administratören om du vill veta mer."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Den här enheten tillhör organisationen.\n\nIT-administratören kan övervaka och hantera inställningar, företagsåtkomst, appar, data med koppling till enheten och enhetens plats.\n\nKontakta IT-administratören om du vill veta mer."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Organisationen har installerat en certifikatutfärdare på enheten. Din säkra nätverkstrafik kan övervakas och ändras."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Administratören har aktiverat nätverksloggning som övervakar trafik på enheten.\n\nKontakta administratören om du vill veta mer."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Du har gett en app behörighet att upprätta en VPN-anslutning.\n\nAppen kan bevaka aktivitet på enheten och nätverket, inklusive e-post, appar och webbplatser."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Jobbprofilen hanteras av <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministratören kan övervaka nätverksaktivitet, till exempel e-postmeddelanden, appar och webbplatser.\n\nKontakta administratören om du vill veta mer.\n\nDu är även ansluten till ett VPN som kan övervaka nätverksaktivitet."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Den här enheten hanteras av din förälder. Föräldern kan se och hantera information som vilka appar du använder, din plats och din skärmtid."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Du är ansluten till <xliff:g id="APPLICATION">%1$s</xliff:g> som kan bevaka din nätverksaktivitet, exempelvis e-post, appar och webbplatser."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Du är ansluten till <xliff:g id="APPLICATION">%1$s</xliff:g>, som kan bevaka din privata aktivitet på nätverket, inklusive e-post, appar och webbplatser."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Parkoppla en ny enhet"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Versionsnummer"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Versionsnumret har kopierats till urklipp."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index eab7f69b8914..2e4c91df087e 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Pau mbili za betri"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Pau tatu za betri."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Betri imejaa."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Hakuna simu"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Mwambaa mmoja wa simu."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Miambaa miwili ya simu"</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Huenda wasifu ukafuatiliwa"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Huenda mtandao unafuatiliwa"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Huenda mtandao unafuatiliwa"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Kifaa hiki kinadhibitiwa na mzazi wako"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Shirika lako linamiliki kifaa hiki na huenda likafuatilia trafiki ya mtandao"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> inamiliki kifaa hiki na huenda ikafuatilia trafiki ya mtandao"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Kifaa hiki kinamilikiwa na shirika lako na kimeunganishwa kwenye <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Zima VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Ondoa VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Angalia Sera"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Angalia vidhibiti"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Kifaa hiki kinamilikiwa na <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nMsimamizi wako wa TEHAMA anaweza kufuatilia na kudhibiti mipangilio, ufikiaji wa maudhui ya shirika, programu, data inayohusiana na kifaa chako na maelezo kuhusu mahali kifaa chako kilipo.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako wa TEHAMA."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Kifaa hiki kinamilikiwa na shirika lako.\n\nMsimamizi wako wa TEHAMA anaweza kufuatilia na kudhibiti mipangilio, ufikiaji wa maudhui ya shirika, programu, data inayohusiana na kifaa chako na maelezo kuhusu mahali kifaa chako kilipo.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako wa TEHAMA."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Shirika lako limesakinisha mamlaka ya cheti kwenye kifaa hiki. Huenda shughuli kwenye mtandao wako salama zikafuatiliwa au kubadilishwa."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Msimamizi wako amewasha kumbukumbu ya kuingia mtandaoni ambayo hufuatilia shughuli kwenye kifaa chako.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Uliruhusu programu iweke muunganisho wa VPN.\n\nProgramu hii inaweza kufuatilia shughuli za kifaa na mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Wasifu wako wa kazini unadhibitiwa na <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nMsimamizi wako anaweza kufuatilia shughuli za mtandaoni, ikiwa ni pamoja na barua pepe, programu na tovuti.\n\nKwa maelezo zaidi, wasiliana na msimamizi wako.\n\nUmeunganishwa pia kwenye VPN, ambayo inaweza kufuatilia shughuli zako mtandaoni."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Kifaa hiki kinadhibitiwa na mzazi wako. Mzazi wako anaweza kuona na kudhibiti maelezo kama vile programu unazotumia, mahali ulipo na muda unaotumia kifaa."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Umeunganishwa kwenye <xliff:g id="APPLICATION">%1$s</xliff:g>, ambayo inaweza kufuatilia shughuli za mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Umeunganishwa kwenye <xliff:g id="APPLICATION">%1$s</xliff:g>, ambayo inaweza kufuatilia shughuli za mtandao wako, ikiwa ni pamoja na barua pepe, programu na tovuti."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Oanisha kifaa kipya"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nambari ya muundo"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nambari ya muundo imewekwa kwenye ubao wa kunakili."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index a72ebeff0ddc..97240d9eb8dd 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"பேட்டரி சக்தி இரண்டு பார் அளவில் உள்ளது."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"பேட்டரி சக்தி மூன்று பார் அளவில் உள்ளது."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"பேட்டரி முழுமையாக உள்ளது."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"சிக்னல் இல்லை."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"சிக்னல் ஒரு கோட்டில் உள்ளது."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"சிக்னல் இரண்டு கோட்டில் உள்ளது."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"சுயவிவரம் கண்காணிக்கப்படலாம்"</string>
<string name="vpn_footer" msgid="3457155078010607471">"நெட்வொர்க் கண்காணிக்கப்படலாம்"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"நெட்வொர்க் கண்காணிக்கப்படலாம்"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"இந்தச் சாதனம் உங்கள் பெற்றோரால் நிர்வகிக்கப்படுகிறது"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"இந்த சாதனம் உங்கள் நிறுவனத்துக்கு உரியது, நெட்வொர்க் ட்ராஃபிக்கையும் நிறுவனமே கண்காணிக்கக்கூடும்"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"இந்த சாதனம் <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> நிறுவனத்துக்கு உரியது, நெட்வொர்க் ட்ராஃபிக்கையும் நிறுவனமே கண்காணிக்கக்கூடும்"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"இந்த சாதனம் உங்கள் நிறுவனத்துக்கு சொந்தமானது, அது <xliff:g id="VPN_APP">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளது"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPNஐ முடக்கு"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPNஐத் துண்டி"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"கொள்கைகளைக் காட்டு"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"கட்டுப்பாடுகளைக் காட்டு"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"இந்த சாதனம் <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> நிறுவனத்துக்கு சொந்தமானது.\n\nஉங்கள் IT நிர்வாகியால் அமைப்புகள், நிறுவன அணுகல், ஆப்ஸ், உங்கள் சாதனத்துடன் தொடர்புடைய தரவு, சாதனத்தின் இருப்பிடத் தகவல்கள் ஆகியவற்றைக் கண்காணிக்கவும் நிர்வகிக்கவும் முடியும்.\n\nமேலும் தகவல்களுக்கு IT நிர்வாகியைத் தொடர்புகொள்ளவும்."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"இந்த சாதனம் உங்கள் நிறுவனத்துக்கு சொந்தமானது.\n\nஉங்கள் IT நிர்வாகியால் அமைப்புகள், நிறுவன அணுகல், ஆப்ஸ், உங்கள் சாதனத்துடன் தொடர்புடைய தரவு, சாதனத்தின் இருப்பிடத் தகவல்கள் ஆகியவற்றைக் கண்காணிக்கவும் நிர்வகிக்கவும் முடியும்.\n\nமேலும் தகவல்களுக்கு IT நிர்வாகியைத் தொடர்புகொள்ளவும்."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"உங்கள் நிறுவனம் இந்தச் சாதனத்தில் சான்றிதழ் அங்கீகாரத்தை நிறுவியுள்ளது. உங்களின் பாதுகாப்பான நெட்வொர்க் ட்ராஃபிக் கண்காணிக்கப்படலாம் அல்லது மாற்றப்படலாம்."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"உங்கள் நிர்வாகி நெட்வொர்க் பதிவெடுத்தலை இயக்கியுள்ளார், இது சாதனத்தில் ட்ராஃபிக்கைக் கண்காணிக்கும்.\n\nமேலும் தகவலுக்கு, உங்கள் நிர்வாகியைத் தொடர்புகொள்ளவும்."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"VPN இணைப்பை அமைக்க, பயன்பாட்டிற்கு அனுமதி வழங்கியுள்ளீர்கள்.\n\nஇந்த ஆப்ஸால் மின்னஞ்சல்கள், ஆப்ஸ் மற்றும் இணையதளங்கள் உட்பட, உங்கள் சாதனத்தையும் நெட்வொர்க் செயல்பாட்டையும் கண்காணிக்க முடியும்."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"உங்கள் பணிக் கணக்கை <xliff:g id="ORGANIZATION">%1$s</xliff:g> நிர்வகிக்கிறது.\n\nஉங்கள் நிர்வாகியால் ஆப்ஸ், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்க முடியும்.\n\nமேலும் தகவலுக்கு, உங்கள் நிர்வாகியைத் தொடர்புகொள்ளவும்.\n\nஉங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய VPN உடனும் இணைக்கப்பட்டுள்ளீர்கள்."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"இந்தச் சாதனம் உங்கள் பெற்றோரால் நிர்வகிக்கப்படுகிறது. நீங்கள் பயன்படுத்தும் ஆப்ஸ், இருப்பிடம், பயன்படுத்திய நேரம் ஆகியவற்றைப் பார்க்கவும் நிர்வகிக்கவும் உங்கள் பெற்றோரால் முடியும்."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"மின்னஞ்சல்கள், ஆப்ஸ், இணையதளங்கள் உட்பட உங்கள் நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்கக்கூடிய <xliff:g id="APPLICATION">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள்."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"<xliff:g id="APPLICATION">%1$s</xliff:g> உடன் இணைக்கப்பட்டுள்ளீர்கள். இந்த ஆப்ஸால், மின்னஞ்சல்கள், ஆப்ஸ் மற்றும் இணையதளங்கள் உட்பட உங்கள் தனிப்பட்ட நெட்வொர்க் செயல்பாட்டைக் கண்காணிக்க முடியும்."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"புதிய சாதனத்தை இணைத்தல்"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"பதிப்பு எண்"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"பதிப்பு எண் கிளிப்போர்டுக்கு நகலெடுக்கப்பட்டது."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 0d23f25409b4..7100c3307047 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"బ్యాటరీ రెండు బార్లు."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"బ్యాటరీ మూడు బార్లు."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"బ్యాటరీ నిండింది."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"ఫోన్ లేదు."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"ఫోన్ ఒక బారు."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"ఫోన్ రెండు బార్లు."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"ప్రొఫైల్‌ని పర్యవేక్షించవచ్చు"</string>
<string name="vpn_footer" msgid="3457155078010607471">"నెట్‌వర్క్ పర్యవేక్షించబడవచ్చు"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"నెట్‌వర్క్ పర్యవేక్షించబడవచ్చు"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"ఈ పరికరాన్ని మీ తల్లి/తండ్రి మేనేజ్ చేస్తున్నారు"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"ఈ పరికరం మీ సంస్థకు చెందినది, కాబట్టి అది నెట్‌వర్క్ ట్రాఫిక్‌ను పర్యవేక్షించవచ్చు"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"మీ పరికరం <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>కు చెందినది, కాబట్టి అది నెట్‌వర్క్ ట్రాఫిక్‌ను పర్యవేక్షించవచ్చు"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"ఈ పరికరం మీ సంస్థకు చెందినది, ఇది <xliff:g id="VPN_APP">%1$s</xliff:g>కు కనెక్ట్ అయి ఉంది"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPNని నిలిపివేయి"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPNను డిస్‌కనెక్ట్ చేయి"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"విధానాలను వీక్షించండి"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"నియంత్రణలను చూడండి"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"ఈ పరికరం <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>కు చెందినది.\n\nసెట్టింగ్‌లను, కార్పొరేట్ యాక్సెస్‌ను, యాప్‌లను, మీ పరికరానికి సంబంధించిన డేటాను, అలాగే మీ పరికరం యొక్క లొకేషన్ సమాచారాన్ని మీ IT అడ్మిన్ పర్యవేక్షించగలరు, మేనేజ్ చేయగలరు.\n\nమరింత సమాచారం కోసం, మీ IT అడ్మిన్‌ను సంప్రదించండి."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"ఈ పరికరం మీ సంస్థకు చెందినది.\n\nసెట్టింగ్‌లను, కార్పొరేట్ యాక్సెస్‌ను, యాప్‌లను, మీ పరికరానికి సంబంధించిన డేటాను, అలాగే మీ పరికరం యొక్క లొకేషన్ సమాచారాన్ని మీ IT అడ్మిన్ పర్యవేక్షించగలరు, మేనేజ్ చేయగలరు.\n\nమరింత సమాచారం కోసం, మీ IT అడ్మిన్‌ను సంప్రదించండి."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"ఈ పరికరంలో మీ సంస్థ ఒక ప్రమాణపత్ర అధికారాన్ని ఇన్‌స్టాల్ చేసింది. మీ సురక్షిత నెట్‌వర్క్ ట్రాఫిక్ పర్యవేక్షించబడవచ్చు లేదా సవరించబడవచ్చు."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"మీ నిర్వాహకులు మీ పరికరంలోని ట్రాఫిక్‌ని పర్యవేక్షించగల నెట్‌వర్క్ లాగింగ్‌ని ఆన్ చేసారు.\n\nమరింత సమాచారం కావాలంటే, మీ నిర్వాహకులను సంప్రదించండి."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"మీరు VPN కనెక్షన్ సెటప్ చేయడానికి ఒక యాప్‌నకు అనుమతి ఇచ్చారు.\n\nఈ యాప్ ఇమెయిల్‌లు,యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ డివైజ్ మరియు నెట్‌వర్క్ కార్యకలాపాన్ని పర్యవేక్షించగలదు."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> ద్వారా మీ కార్యాలయ ప్రొఫైల్ నిర్వహించబడుతోంది.\n\nఇమెయిల్‌లు, అనువర్తనాలు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల సామర్థ్యం మీ నిర్వాహకులకు ఉంది.\n\nమరింత సమాచారం కావాలంటే, మీ నిర్వాహకులను సంప్రదించండి.\n\nమీరు VPNకి కూడా కనెక్ట్ అయ్యారు, ఇది మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ఈ పరికరాన్ని మీ తల్లి/తండ్రి మేనేజ్ చేస్తున్నారు. మీ తల్లి/తండ్రి, మీరు ఉపయోగించే యాప్‌లు, మీ లొకేషన్, అలాగే మీ పరికర వినియోగ వ్యవధి వంటి సమాచారాన్ని చూడగలరు, మేనేజ్ చేయగలరు."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"మీరు ఇమెయిల్‌లు, అనువర్తనాలు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"మీరు <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఇమెయిల్‌లు, అనువర్తనాలు మరియు వెబ్‌‍సైట్‌లతో సహా మీ వ్యక్తిగత నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"కొత్త పరికరాన్ని పెయిర్ చేయండి"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"బిల్డ్ నంబర్"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"బిల్డ్ నంబర్, క్లిప్‌బోర్డ్‌కు కాపీ చేయబడింది."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 094cb765a49b..8db84b8d1e67 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"แบตเตอรี่สองขีด"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"แบตเตอรี่สามขีด"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"แบตเตอรี่เต็ม"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"ไม่มีสัญญาณโทรศัพท์"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"สัญญาณโทรศัพท์หนึ่งขีด"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"สัญญาณโทรศัพท์สองขีด"</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"อาจมีการตรวจสอบโปรไฟล์"</string>
<string name="vpn_footer" msgid="3457155078010607471">"เครือข่ายอาจได้รับการตรวจสอบ"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"เครือข่ายอาจถูกตรวจสอบ"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"อุปกรณ์นี้จัดการโดยผู้ปกครอง"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"องค์กรของคุณเป็นเจ้าของอุปกรณ์นี้และอาจตรวจสอบการจราจรของข้อมูลในเครือข่าย"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> เป็นเจ้าของอุปกรณ์นี้และอาจตรวจสอบการจราจรของข้อมูลในเครือข่าย"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"องค์กรของคุณเป็นเจ้าของอุปกรณ์นี้ และอุปกรณ์เชื่อมต่ออยู่กับ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"ปิดใช้ VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"ยกเลิกการเชื่อมต่อ VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"ดูนโยบาย"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"ดูการควบคุม"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> เป็นเจ้าของอุปกรณ์นี้\n\nผู้ดูแลระบบไอทีจะตรวจสอบและจัดการการตั้งค่า การเข้าถึงของบริษัท แอป ข้อมูลที่เชื่อมโยงกับอุปกรณ์ และข้อมูลตำแหน่งของอุปกรณ์ได้\n\nติดต่อผู้ดูแลระบบไอทีหากต้องการข้อมูลเพิ่มเติม"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"องค์กรของคุณเป็นเจ้าของอุปกรณ์นี้\n\nผู้ดูแลระบบไอทีจะตรวจสอบและจัดการการตั้งค่า การเข้าถึงของบริษัท แอป ข้อมูลที่เชื่อมโยงกับอุปกรณ์ และข้อมูลตำแหน่งของอุปกรณ์ได้\n\nติดต่อผู้ดูแลระบบไอทีหากต้องการข้อมูลเพิ่มเติม"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"องค์กรของคุณติดตั้งผู้ออกใบรับรองในอุปกรณ์นี้ อาจมีการตรวจสอบหรือแก้ไขการจราจรของข้อมูลในเครือข่ายที่ปลอดภัยของคุณ"</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"ผู้ดูแลระบบได้เปิดการทำบันทึกเครือข่าย ซึ่งจะติดตามดูการรับส่งข้อมูลบนอุปกรณ์ของคุณ\n\nโปรดติดต่อผู้ดูแลระบบสำหรับข้อมูลเพิ่มเติม"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"คุณได้ให้สิทธิ์แอปในการตั้งค่าการเชื่อมต่อ VPN\n\nแอปนี้จะสามารถตรวจสอบอุปกรณ์และกิจกรรมในเครือข่าย รวมถึงอีเมล แอป และเว็บไซต์ได้"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"โปรไฟล์งานของคุณได้รับการจัดการโดย <xliff:g id="ORGANIZATION">%1$s</xliff:g>\n\nผู้ดูแลระบบสามารถตรวจสอบกิจกรรมในเครือข่ายของคุณ ซึ่งรวมถึงอีเมล แอป และเว็บไซต์ต่างๆ\n\nโปรดติดต่อผู้ดูแลระบบสำหรับข้อมูลเพิ่มเติม\n\nนอกจากนี้คุณยังเชื่อมต่อกับ VPN ซึ่งตรวจสอบกิจกรรมในเครือข่ายของคุณได้"</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"อุปกรณ์นี้จัดการโดยผู้ปกครอง ผู้ปกครองจะดูและจัดการข้อมูลต่างๆ ได้ เช่น แอปที่คุณใช้ ตำแหน่งของคุณ และเวลาอยู่หน้าจอ"</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"คุณเชื่อมต่ออยู่กับ <xliff:g id="APPLICATION">%1$s</xliff:g> ซึ่งสามารถตรวจสอบกิจกรรมในเครือข่ายของคุณ รวมถึงอีเมล แอป และเว็บไซต์"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"คุณเชื่อมต่อกับ <xliff:g id="APPLICATION">%1$s</xliff:g> ซึ่งสามารถตรวจสอบกิจกรรมในเครือข่ายส่วนตัวของคุณ รวมถึงอีเมล แอป และเว็บไซต์ได้"</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"จับคู่อุปกรณ์ใหม่"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"หมายเลขบิวด์"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"คัดลอกหมายเลขบิวด์ไปยังคลิปบอร์ดแล้ว"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 8ef18697cd4d..09f8a71167b3 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Baterya na dalawang bar."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Baterya na tatlong bar."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Puno na ang baterya."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Walang telepono."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telepono na isang bar."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telepono na dalawang bar."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Maaaring subaybayan ang profile"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Maaaring sinusubaybayan ang network"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Maaaring sinusubaybayan ang network"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Pinapamahalaan ng iyong magulang ang device na ito"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Pagmamay-ari ng organisasyon mo ang device na ito at puwede nitong subaybayan ang trapiko sa network"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Pagmamay-ari ng <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ang device na ito at puwede nitong subaybayan ang trapiko sa network"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Pagmamay-ari ng iyong organisasyon ang device na ito at nakakonekta ito sa <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"I-disable ang VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Idiskonekta ang VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Tingnan ang Mga Patakaran"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Tingnan ang mga kontrol"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Pagmamay-ari ng <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ang device na ito.\n\nMagagawa ng iyong IT admin na subaybayan at pamahalaan ang mga setting, pangkorporasyong access, mga app, data na nauugnay sa device mo, at ang impormasyon ng lokasyon ng iyong device.\n\nPara sa higit pang impormasyon, makipag-ugnayan sa iyong IT admin."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Pagmamay-ari ng iyong organisasyon ang device na ito.\n\nMagagawa ng iyong IT admin na subaybayan at pamahalaan ang mga setting, pangkorporasyong access, mga app, data na nauugnay sa device mo, at ang impormasyon ng lokasyon ng iyong device.\n\nPara sa higit pang impormasyon, makipag-ugnayan sa iyong IT admin."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Nag-install ang iyong organisasyon ng awtoridad sa certificate sa device na ito. Maaaring subaybayan o baguhin ang iyong ligtas na trapiko sa network."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Na-on ng iyong admin ang pag-log sa network, na sumusubaybay sa trapiko ng device mo.\n\nPara sa higit pang impormasyon, makipag-ugnayan sa iyong admin."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Nagbigay ka ng pahintulot sa app upang mag-set up ng VPN na koneksyon.\n\nMaaaring subaybayan ng app na ito ang iyong aktibidad sa device at network, kabilang ang mga email, app at website."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Pinamamahalaan ng <xliff:g id="ORGANIZATION">%1$s</xliff:g> ang iyong profile sa trabaho.\n\nMay kakayahan ang admin mo na subaybayan ang iyong aktibidad sa network, kasama ang mga email, app at website.\n\nPara sa higit pang impormasyon, makipag-ugnayan sa admin mo.\n\nNakakonekta ka rin sa isang VPN, na may kakayahang subaybayan ang iyong aktibidad sa network."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Pinapamahalaan ng iyong magulang ang device na ito. Makikita at mapapamahalaan ng iyong magulang ang impormasyon tulad ng mga app na ginagamit mo, iyong lokasyon, at tagal ng paggamit mo sa device."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Nakakonekta ka sa <xliff:g id="APPLICATION">%1$s</xliff:g>, na maaaring sumubaybay sa iyong aktibidad sa network, kasama ang mga email, app, at website."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Nakakonekta ka sa <xliff:g id="APPLICATION">%1$s</xliff:g>, na maaaring sumubaybay sa iyong personal na aktibidad sa network, kabilang ang mga email, app at website."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Magpares ng bagong device"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Numero ng build"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nakopya sa clipboard ang numero ng build."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index c17c8f710079..89d737410ddb 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Pil gücü iki çubuk."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Pil gücü üç çubuk."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Pil tam dolu."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Telefon sinyali yok."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon sinyali bir çubuk."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon sinyali iki çubuk."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil izlenebilir"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Ağ etkinliği izlenebilir"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Ağ etkinliği izlenebilir"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Bu cihaz ebeveyniniz tarafından yönetiliyor"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Bu cihaz, kuruluşunuza ait olup ağ trafiği kuruluşunuz tarafından izlenebilir"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Bu cihaz, <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> adlı kuruluşa ait olup ağ trafiği bu kuruluş tarafından izlenebilir"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Bu cihaz, kuruluşunuza ait olup <xliff:g id="VPN_APP">%1$s</xliff:g> uygulamasına bağlı"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN\'yi devre dışı bırak"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN bağlantısını kes"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Politikaları Göster"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Kontrolleri göster"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Bu cihaz <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> adlı kuruluşa ait.\n\nBT yöneticiniz cihazınızın ayarlarını, şirket erişimini, uygulamaları, cihazınızla ilişkilendirilen verileri, cihazınızın konum bilgilerini izleyip yönetebilir.\n\nDaha fazla bilgi için BT yöneticinize başvurun."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Bu cihaz kuruluşunuza ait.\n\nBT yöneticiniz cihazın ayarlarını, şirket erişimini, uygulamaları, cihazınızla ilişkilendirilen verileri, cihazınızın konum bilgilerini izleyip yönetebilir.\n\nDaha fazla bilgi için BT yöneticinize başvurun."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Kuruluşunuz bu cihaza bir sertifika yetkilisi yükledi. Güvenli ağ trafiğiniz izlenebilir veya değiştirilebilir."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Yöneticiniz,cihazınızdaki trafiği izleyen ağ günlük kaydını açtı.\n\nDaha fazla bilgi için yöneticinizle iletişim kurun."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"VPN bağlantısı kurması için bir uygulamaya izin verdiniz.\n\nBu uygulama, cihazınızın yanı sıra e-postalarınız, uygulamalarınız ve web siteleriniz dahil olmak üzere ağ etkinliğinizi izleyebilir."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"İş profiliniz <xliff:g id="ORGANIZATION">%1$s</xliff:g> tarafından yönetiliyor.\n\nYöneticiniz e-postalar, uygulamalar ve web siteleri de dahil olmak üzere ağ etkinliğinizi izleyebilir.\n\nDaha fazla bilgi için yöneticinizle iletişim kurun.\n\nAyrıca, ağ etkinliğinizi izleyebilen bir VPN\'ye de bağlısınız."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Bu cihaz ebeveyniniz tarafından yönetiliyor. Kullandığınız uygulamalar, konumunuz ve ekran başında kalma süreniz gibi bilgiler ebeveyniniz tarafından görülüp yönetebilir."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"E-postalarınız, uygulamalarınız ve web siteleriniz dahil olmak üzere ağ etkinliğinizi izleyebilen <xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasına bağlısınız."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"E-postalarınız, uygulamalarınız ve web siteleriniz dahil olmak üzere kişisel ağ etkinliğinizi izleyebilen <xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasına bağlısınız."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yeni cihaz eşle"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Derleme numarası"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Derleme numarası panoya kopyalandı."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 7dcfc3b175ac..f1962939622d 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Заряд акумулятора: дві смужки."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Заряд акумулятора: три смужки."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Акумулятор заряджений."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Немає сигналу телефону."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Одна смужка сигналу телефону."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Дві смужки сигналу телефону."</string>
@@ -526,6 +528,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Профіль може відстежуватись"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Дії в мережі можуть відстежуватися"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Мережа може відстежуватися"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Цим пристроєм керує батько або мати"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Цей пристрій належить вашій організації. Її адміністратор може відстежувати мережевий трафік"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Цей пристрій належить організації \"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>\". Її адміністратор може відстежувати мережевий трафік"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Цей пристрій належить вашій організації. Його підключено до додатка <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -550,6 +553,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Вимкнути VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Від’єднатися від мережі VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Переглянути правила"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Переглянути засоби контролю"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Цей пристрій належить організації \"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>\".\n\nIT-адміністратор може відстежувати й контролювати налаштування, корпоративний доступ, додатки, дані пристрою та інформацію про його місцезнаходження.\n\nЩоб дізнатися більше, зв\'яжіться з IT-адміністратором."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Цей пристрій належить вашій організації.\n\nІТ-адміністратор може відстежувати й контролювати налаштування, корпоративний доступ, додатки, дані пристрою та інформацію про його місцезнаходження.\n\nЩоб дізнатися більше, зв\'яжіться з ІТ-адміністратором."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Адміністратор організації встановив центр сертифікації на цьому пристрої. Захищений мережевий трафік може відстежуватися або змінюватися."</string>
@@ -573,6 +577,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Ваш адміністратор увімкнув реєстрацію в мережі, під час якої на вашому пристрої відстежується трафік.\n\nЩоб дізнатися більше, зв’яжіться з адміністратором."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Ви дозволили додатку під’єднуватися до мережі VPN.\n\nЦей додаток може відстежувати вашу активність на пристрої та в мережі, зокрема в електронній пошті, додатках і на веб-сайтах."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Вашим робочим профілем керує адміністратор організації <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nВін може відстежувати ваші дії в мережі, зокрема електронні листи, додатки та веб-сайти.\n\nЩоб дізнатися більше, зв’яжіться з адміністратором.\n\nВаш пристрій також під’єднано до мережі VPN, у якій можна відстежувати ваші дії в мережі."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Цим пристроєм керує батько або мати. Вони можуть бачити та контролювати, якими додатками ви користуєтесь, де перебуваєте й скільки часу проводите за пристроєм."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Ваш профіль під’єднано до додатка <xliff:g id="APPLICATION">%1$s</xliff:g>, який може відстежувати вашу активність у мережі, зокрема в електронній пошті, додатках і на веб-сайтах."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Ваш профіль під’єднано до додатка <xliff:g id="APPLICATION">%1$s</xliff:g>, який може відстежувати вашу особисту активність у мережі, зокрема в електронній пошті, додатках і на веб-сайтах."</string>
@@ -1101,4 +1106,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Підключити новий пристрій"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Номер складання"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Номер складання скопійовано в буфер обміну."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index 4c0ebaad9275..6973c5e9127f 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"بیٹری کے دو بارز۔"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"بیٹری کے تین بارز۔"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"بیٹری بھری ہے۔"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"کوئی فون نہیں ہے۔"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"فون کا ایک بار۔"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"فون کے دو بارز۔"</string>
@@ -520,6 +522,8 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"پروفائل کو مانیٹر کیا جا سکتا ہے"</string>
<string name="vpn_footer" msgid="3457155078010607471">"نیٹ ورک کو مانیٹر کیا جا سکتا ہے"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"نیٹ ورک کو شاید مانیٹر کیا جائے"</string>
+ <!-- no translation found for quick_settings_disclosure_parental_controls (2114102871438223600) -->
+ <skip />
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"آپ کی تنظیم اس آلے کی مالک ہے اور نیٹ ورک ٹریفک کی نگرانی کر سکتی ہے"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> اس آلے کی مالک ہے اور نیٹ ورک ٹریفک کی نگرانی کر سکتی ہے"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"یہ آلہ آپ کی تنظیم کا ہے اور <xliff:g id="VPN_APP">%1$s</xliff:g> سے منسلک ہے"</string>
@@ -544,6 +548,8 @@
<string name="disable_vpn" msgid="482685974985502922">"‏VPN کو غیر فعال کریں"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"‏VPN کو غیر منسلک کریں"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"پالیسیاں دیکھیں"</string>
+ <!-- no translation found for monitoring_button_view_controls (8316440345340701117) -->
+ <skip />
<string name="monitoring_description_named_management" msgid="505833016545056036">"‏یہ آلہ <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> کا ہے۔\n\nآپ کا IT منتظم ترتیبات، کارپوریٹ رسائی، ایپس، آپ کے آلہ سے وابستہ ڈیٹا اور آپ کے آلہ کے مقام کی معلومات کی نگرانی اور ان کا نظم کر سکتا ہے۔\n\nمزید معلومات کے لیے اپنے IT منتظم سے رابطہ کریں۔"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"‏یہ آلہ آپ کی تنظیم کا ہے۔\n\nآپ کا IT منتظم ترتیبات، کارپوریٹ رسائی، ایپس، آپ کے آلہ سے وابستہ ڈیٹا اور آپ کے آلہ کے مقام کی معلومات کی نگرانی اور ان کا نظم کر سکتا ہے۔\n\nمزید معلومات کے لیے اپنے IT منتظم سے رابطہ کریں۔"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"آپ کی تنظیم نے اس آلے پر ایک سرٹیفکیٹ کی اتھارٹی کو انسٹال کیا ہے۔ آپ کا محفوظ نیٹ ورک ٹریفک مانیٹر ہو سکتا ہے یا اس میں ترمیم کی جا سکتی ہے۔"</string>
@@ -567,6 +573,8 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"آپ کے ایڈمن نے نیٹ ورک لاگنگ آن کر دی ہے، جو آپ کے آلہ پر ٹریفک کو مانیٹر کرتی ہے۔\n\nمزید معلومات کیلئے اپنے ایڈمن سے رابطہ کریں۔"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"‏آپ نے ایک ایپ کو VPN کنکشن ترتیب دینے کی اجازت دی ہے۔\n\nیہ ایپ ای میلز، ایپس اور ویب سائٹس سمیت آپ کے آلہ اور نیٹ ورک کی سرگرمی مانیٹر کر سکتی ہے۔"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"‏آپ کی دفتری پروفائل <xliff:g id="ORGANIZATION">%1$s</xliff:g> کے زیر نظم ہے۔\n\nآپ کا ایڈمن بشمول ای میلز، ایپس، اور ویب سائٹس، آپ کے نیٹ ورک کی سرگرمی کو مانیٹر کرنے کا اہل ہے۔\n\nمزید معلومات کے لیے اپنے ایڈمن سے رابطہ کریں۔\n\nآپ ایک VPN سے بھی منسلک ہیں، جو آپ کے نیٹ ورک کی سرگرمی کو مانیٹر کر سکتا ہے۔"</string>
+ <!-- no translation found for monitoring_description_parental_controls (8184693528917051626) -->
+ <skip />
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"آپ <xliff:g id="APPLICATION">%1$s</xliff:g> سے منسلک ہیں، جو ای میلز، ایپس اور ویب سائٹس سمیت آپ کے نیٹ ورک کی سرگرمی مانیٹر کر سکتی ہے۔"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"آپ <xliff:g id="APPLICATION">%1$s</xliff:g> سے منسلک ہیں، جو آپ کے نجی نیٹ ورک کی سرگرمی سمیت ای میلز، ایپس اور ویب سائٹس مانیٹر کر سکتی ہے۔"</string>
@@ -1089,4 +1097,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"نئے آلہ کا جوڑا بنائیں"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"بلڈ نمبر"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"بلڈ نمبر کلپ بورڈ میں کاپی ہو گیا۔"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 33d4f4ca14b7..a97f1e4a13d6 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Batareya ikkta panelda."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Batareya uchta panelda."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Batareya to‘la."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Signal yo‘q."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Telefon bitta panelda."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Telefon ikkita panelda."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Profil kuzatilishi mumkin"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Tarmoqni kuzatish mumkin"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Tarmoq kuzatilishi mumkin"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Bu – ota-onangiz tomonidan boshqariladigan qurilma."</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Bu qurilma tashkilotingizga tegishli va tarmoq trafigi tashkilotingiz tomonidan kuzatilishi mumkin"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"Bu qurilma <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> tashkilotiga tegishli va tarmoq trafigi tashkilot tomonidan kuzatilishi mumkin"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Bu qurilma tashkilotingizga tegishli va <xliff:g id="VPN_APP">%1$s</xliff:g> tarmogʻiga ulangan"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"VPN tarmog‘ini o‘chirish"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"VPN ulanishini uzish"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Siyosatlarni ko‘rish"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Boshqaruvni chiqarish"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Bu qurilma <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> tashkilotiga tegishli.\n\nAT administratori sozlamalar, korporativ ruxsat, ilovalar, qurilmaning geolokatsiyasi va unga aloqador axborotlarni kuzatishi va boshqarishi mumkin.\n\nBatafsil axborot uchun AT administratoriga murojaat qiling."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Bu qurilma tashkilotingizga tegishli.\n\nAT administratori sozlamalar, korporativ ruxsat, ilovalar, qurilmaning geolokatsiyasi va unga aloqador axborotlarni kuzatishi va boshqarishi mumkin.\n\nBatafsil axborot uchun AT administratoriga murojaat qiling."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Tashkilotingiz bu qurilmada CA sertifikatini o‘rnatdi. U himoyalangan tarmoq trafigini nazorat qilishi va o‘zgartirishi mumkin."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Administrator qurilmangizdagi trafikni nazorat qiluvchi tarmoq jurnalini yoqdi.\n\nBatafsil axborot olish uchun administratoringizga murojaat qiling."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Siz ilovaga VPN tarmog‘iga ulanishga ruxsat bergansiz.\n\nUshbu ilova qurilmangiz va internetdagi harakatlaringizni, jumladan, e-pochta, ilovalar va veb-saytlardagi xatti-harakatlaringizni kuzatishi mumkin."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Sizning ishchi profilingiz <xliff:g id="ORGANIZATION">%1$s</xliff:g> tomonidan boshqariladi.\n\nAdministrator internetdagi harakatlaringizni, jumladan, e-pochta, ilova va xavfsiz veb-saytlar bilan ishlashingizni kuzatishi mumkin.\n\nBatafsil axborot olish uchun administrator bilan bog‘laning.\n\nShuningdek, siz VPN tarmog‘iga ham ulangansiz. U internetdagi harakatlaringizni kuzatishi mumkin."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Bu – ota-onangiz tomonidan boshqariladigan qurilma. Ota-onangiz siz foydalangan ilovalar, joylashuvingiz va qurilmadan foydalanish vaqti kabi axborotlarni koʻrishi va boshqarishi mumkin."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasi ishga tushirilgan. U tarmoqdagi, jumladan, e-pochta, ilova va veb-saytlardagi xatti-harakatlaringizni kuzatishi mumkin."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasi ishga tushirilgan. U internetdagi harakatlaringiz, jumladan, e-pochta, ilova va veb-saytlardagi xatti-harakatlaringizni kuzatishi mumkin."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Yangi qurilmani ulash"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Nashr raqami"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Nashr raqami vaqtinchalik xotiraga nusxalandi."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 179f7c265496..4a69cc70abf6 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Mức pin hai vạch."</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Mức pin ba vạch."</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Mức pin đầy."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Không có điện thoại nào."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Tín hiệu điện thoại một vạch."</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Tín hiệu điện thoại hai vạch."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Hồ sơ có thể được giám sát"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Mạng có thể được giám sát"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Mạng có thể được giám sát"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Thiết bị này do cha mẹ của bạn quản lý"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Tổ chức của bạn sở hữu thiết bị này và có thể giám sát lưu lượng truy cập mạng"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> sở hữu thiết bị này và có thể giám sát lưu lượng truy cập mạng"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Thiết bị này thuộc về tổ chức của bạn và đã kết nối với <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Tắt VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Ngắt kết nối VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Xem chính sách"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Xem các quyền kiểm soát"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Thiết bị này thuộc về <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nQuản trị viên CNTT có thể giám sát và quản lý các tùy chọn cài đặt, quyền truy cập vào dữ liệu công ty, ứng dụng, dữ liệu liên kết với thiết bị và thông tin vị trí thiết bị của bạn.\n\nĐể biết thêm thông tin, hãy liên hệ với quản trị viên CNTT của bạn."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Thiết bị này thuộc về tổ chức của bạn.\n\nQuản trị viên CNTT có thể giám sát và quản lý các tùy chọn cài đặt, quyền truy cập vào dữ liệu công ty, ứng dụng, dữ liệu liên kết với thiết bị và thông tin vị trí thiết bị của bạn.\n\nĐể biết thêm thông tin, hãy liên hệ với quản trị viên CNTT của bạn."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Tổ chức của bạn đã cài đặt một tổ chức phát hành chứng chỉ trên thiết bị này. Lưu lượng truy cập mạng bảo mật của bạn có thể được giám sát hoặc sửa đổi."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Quản trị viên đã bật tính năng ghi nhật ký mạng. Tính năng này giám sát lưu lượng truy cập trên thiết bị của bạn.\n\nĐể biết thêm thông tin, hãy liên hệ với quản trị viên của bạn."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Bạn đã cấp cho ứng dụng quyền thiết lập kết nối VPN.\n\nỨng dụng này có thể giám sát hoạt động mạng và thiết bị của bạn, bao gồm email, ứng dụng và trang web."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Hồ sơ công việc của bạn do <xliff:g id="ORGANIZATION">%1$s</xliff:g> quản lý.\n\nQuản trị viên có thể giám sát hoạt động mạng của bạn bao gồm email, ứng dụng và trang web.\n\nĐể biết thêm thông tin, hãy liên hệ với quản trị viên của bạn.\n\nBạn cũng được kết nối với VPN. Dịch vụ này có thể giám sát hoạt động mạng của bạn."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Thiết bị này do cha mẹ bạn quản lý. Cha mẹ có thể có thể xem và quản lý những thông tin như ứng dụng bạn dùng, vị trí của bạn và thời gian bạn sử dụng thiết bị."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Bạn đang kết nối với <xliff:g id="APPLICATION">%1$s</xliff:g>. Ứng dụng này có thể giám sát hoạt động mạng của bạn bao gồm email, ứng dụng và trang web."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Bạn đang kết nối với <xliff:g id="APPLICATION">%1$s</xliff:g>. Ứng dụng này có thể giám sát hoạt động mạng cá nhân của bạn bao gồm email, ứng dụng và trang web."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Ghép nối thiết bị mới"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Số bản dựng"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Đã sao chép số bản dựng vào khay nhớ tạm."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index e1f483c78e7f..9c34b31f6051 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"电池电量为两格。"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"电池电量为三格。"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"电池电量满格。"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"没有手机信号。"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"手机信号强度为一格。"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"手机信号强度为两格。"</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"资料可能会受到监控"</string>
<string name="vpn_footer" msgid="3457155078010607471">"网络可能会受到监控"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"网络可能会受到监控"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"此设备由您的家长管理"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"贵单位拥有此设备,且可能会监控网络流量"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>拥有此设备,且可能会监控网络流量"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"此设备归贵单位所有,且已连接到“<xliff:g id="VPN_APP">%1$s</xliff:g>”"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"关闭VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"断开VPN连接"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"查看政策"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"查看家长控制功能相关信息"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"此设备归<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>所有。\n\n您的 IT 管理员能够监控和管理与您的设备相关的设置、企业权限、应用、数据,以及您设备的位置信息。\n\n如需了解详情,请与您的 IT 管理员联系。"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"此设备归贵单位所有。\n\n您的 IT 管理员能够监控和管理与您的设备相关的设置、企业权限、应用、数据,以及您设备的位置信息。\n\n如需了解详情,请与您的 IT 管理员联系。"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"您所在的单位已在此设备上安装证书授权中心。您的安全网络流量可能会受到监控或修改。"</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"您的管理员已开启网络日志功能,该功能会监控您设备上的流量。\n\n如需更多信息,请与您的管理员联系。"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"您已授权应用设置 VPN 连接。\n\n该应用可以监控您的设备和网络活动,包括收发电子邮件、使用应用和浏览网站。"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"您的工作资料由“<xliff:g id="ORGANIZATION">%1$s</xliff:g>”管理。\n\n您的管理员能够监控您的网络活动,其中包括收发电子邮件、使用应用和访问网站。\n\n如需更多信息,请与您的管理员联系。\n\n此外,您还连接到了 VPN,它同样可以监控您的网络活动。"</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"此设备由您的家长管理。您的家长可以查看和管理相关信息,例如您使用的应用、您的位置信息和设备使用时间。"</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"您已连接到“<xliff:g id="APPLICATION">%1$s</xliff:g>”(该应用能够监控您的网络活动,其中包括收发电子邮件、使用应用和浏览网站)。"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"您已连接到<xliff:g id="APPLICATION">%1$s</xliff:g>,该应用可以监控您的个人网络活动,包括收发电子邮件、使用应用和浏览网站。"</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"与新设备配对"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"版本号"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"已将版本号复制到剪贴板。"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index f986ef33ca28..2e22b0751e47 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"電池電量為兩格。"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"電池電量為三格。"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"電池已滿。"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"沒有電話訊號。"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"電話訊號強度為一格。"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"電話訊號強度為兩格。"</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"個人檔案可能受到監控"</string>
<string name="vpn_footer" msgid="3457155078010607471">"網絡可能會受到監控"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"網絡可能會受到監控"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"此裝置由您的家長管理"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"您的機構擁有此裝置,並可能會監察網絡流量"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"「<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>」擁有此裝置,並可能會監察網絡流量"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"此裝置屬於您的機構,並已連結至「<xliff:g id="VPN_APP">%1$s</xliff:g>」"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"停用 VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"中斷 VPN 連線"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"查看政策"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"查看控制項"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"此裝置屬於 <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>。\n\n您的 IT 管理員可監察及管理與裝置相關聯的設定、公司存取權、應用程式和資料,以及裝置的位置資料。\n\n如要瞭解詳情,請與您的 IT 管理員聯絡。"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"此裝置屬於您的機構。\n\n您的 IT 管理員可監察及管理與裝置相關聯的設定、公司存取權、應用程式和資料,以及裝置的位置資料。\n\n如要瞭解詳情,請與您的 IT 管理員聯絡。"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"您的機構已在此裝置中安裝憑證授權單位。您的安全網絡流量可能會受監控或修改。"</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"您的管理員已開啟網絡記錄功能,以監控您裝置上的流量。\n\n如需瞭解詳情,請聯絡您的管理員。"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"您已授權應用程式設定 VPN 連線。\n\n這個應用程式能夠監控您的裝置和網絡活動,包括電郵、應用程式和網站。"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"您的工作設定檔由<xliff:g id="ORGANIZATION">%1$s</xliff:g>管理。\n\n您的管理員可以監控您的網絡活動,包括收發電郵、使用應用程式和瀏覽網站。\n\n如需瞭解詳情,請聯絡您的管理員。\n\n此外,由於您已連接至 VPN,因此 VPN 可監控您的網絡活動。"</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"此裝置由您的家長管理。家長可以查看及管理裝置上的資料,例如您使用的應用程式、位置和裝置使用時間。"</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"您已連結至「<xliff:g id="APPLICATION">%1$s</xliff:g>」,此應用程式可以監控您的網絡活動,包括電郵、應用程式和網站。"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"您已連結至<xliff:g id="APPLICATION">%1$s</xliff:g>,它能夠監控您的個人網絡活動,包括電郵、應用程式和網站。"</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"配對新裝置"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"版本號碼"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"版本號碼已複製到剪貼簿。"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index b442b792e95f..0cc17efc553b 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"電池電量兩格。"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"電池電量三格。"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"電池電量已滿。"</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"沒有電話訊號。"</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"電話訊號強度一格。"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"電話訊號強度兩格。"</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"設定檔可能會受到監控"</string>
<string name="vpn_footer" msgid="3457155078010607471">"網路可能會受到監控"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"網路可能會受到監控"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"這個裝置是由你的家長管理"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"貴機構擁有這部裝置,而且可能會監控網路流量"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"這部裝置的擁有者為「<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>」,而且該機構可能會監控網路流量"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"這部裝置的擁有者為貴機構,並且已連線到「<xliff:g id="VPN_APP">%1$s</xliff:g>」"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"停用 VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"中斷 VPN 連線"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"查看政策"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"查看監護功能相關資訊"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"這部裝置的擁有者為「<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>」。\n\n你的 IT 管理員可以監控及管理與裝置相關聯的設定、公司系統權限、應用程式和資料,以及裝置的位置資訊。\n\n如要瞭解詳情,請與你的 IT 管理員聯絡。"</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"這部裝置的擁有者為貴機構。\n\n你的 IT 管理員可以監控及管理與裝置相關聯的設定、公司系統權限、應用程式和資料,以及裝置的位置資訊。\n\n如要瞭解詳情,請與你的 IT 管理員聯絡。"</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"貴機構已為這個裝置安裝憑證授權單位憑證。你的安全網路流量可能會受到監控或修改。"</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"你的管理員已啟用網路記錄功能,可監控你裝置的流量。\n\n如需詳細資訊,請與你的管理員聯絡。"</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"你已授權一個應用程式設定 VPN 連線。\n\n這個應用程式可以監控你的裝置和網路活動,包括收發電子郵件、使用應用程式和瀏覽網站。"</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"你的工作資料夾是由下列機構管理:<xliff:g id="ORGANIZATION">%1$s</xliff:g>。\n\n你的管理員可以監控你的網路活動,包括收發電子郵件、使用應用程式及瀏覽網站。\n\n如需詳細資訊,請與你的管理員聯絡。\n\n此外,由於你已連線至 VPN,因此你的網路活動也會受到 VPN 監控。"</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"這個裝置是由你的家長管理。家長可以查看及管理裝置上的資訊,例如你使用的應用程式、所在位置和裝置使用時間。"</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"由於你已連結至「<xliff:g id="APPLICATION">%1$s</xliff:g>」,因此你的網路活動 (包括收發電子郵件、使用應用程式和瀏覽網站) 可能會受到這個應用程式監控。"</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"由於你已連線至 <xliff:g id="APPLICATION">%1$s</xliff:g>,你的個人網路活動也會受到這個應用程式監控,包括收發電子郵件、使用應用程式和瀏覽網站。"</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"配對新裝置"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"版本號碼"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"已將版本號碼複製到剪貼簿。"</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 764f0b719702..9e85eeddbd96 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -182,6 +182,8 @@
<string name="accessibility_battery_two_bars" msgid="7895789999668425551">"Amabha amabili ebhethri"</string>
<string name="accessibility_battery_three_bars" msgid="118341923832368291">"Amabha amathathu ebhethri"</string>
<string name="accessibility_battery_full" msgid="1480463938961288494">"Ibhethri igcwele."</string>
+ <!-- no translation found for accessibility_battery_unknown (1807789554617976440) -->
+ <skip />
<string name="accessibility_no_phone" msgid="8828412144430247025">"Ayikho ifoni."</string>
<string name="accessibility_phone_one_bar" msgid="8786055123727785588">"Ibha eyodwa yefoni"</string>
<string name="accessibility_phone_two_bars" msgid="3316909612598670674">"Amabha amabilil efoni."</string>
@@ -520,6 +522,7 @@
<string name="profile_owned_footer" msgid="2756770645766113964">"Iphrofayela ingaqashwa"</string>
<string name="vpn_footer" msgid="3457155078010607471">"Inethiwekhi kungenzeka iqashiwe"</string>
<string name="branded_vpn_footer" msgid="816930186313188514">"Inethiwekhi kungenzeka iqashiwe"</string>
+ <string name="quick_settings_disclosure_parental_controls" msgid="2114102871438223600">"Le divayisi iphethwe ngumzali wakho"</string>
<string name="quick_settings_disclosure_management_monitoring" msgid="8231336875820702180">"Inhlangano yakho ingumnikazi wale divayisi futhi ingaqapha ithrafikhi yenethiwekhi"</string>
<string name="quick_settings_disclosure_named_management_monitoring" msgid="2831423806103479812">"I-<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> ingumnikazi wale divayisi futhi ingaqapha ithrafikhi yenethiwekhi"</string>
<string name="quick_settings_disclosure_management_named_vpn" msgid="6096715329056415588">"Le divayisi ngeyenhlangano yakho futhi ixhunywe ku-<xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
@@ -544,6 +547,7 @@
<string name="disable_vpn" msgid="482685974985502922">"Khubaza i-VPN"</string>
<string name="disconnect_vpn" msgid="26286850045344557">"Nqamula i-VPN"</string>
<string name="monitoring_button_view_policies" msgid="3869724835853502410">"Buka izinqubomgomo"</string>
+ <string name="monitoring_button_view_controls" msgid="8316440345340701117">"Buka izilawuli"</string>
<string name="monitoring_description_named_management" msgid="505833016545056036">"Le divayisi ngeye-<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g>.\n\nUmphathi wakho we-IT angakwazi ukugada nokulawula amasethingi, ukufinyelela kwenhlangano, izinhlelo zokusebenza, idatha ehlobene nedivayisi yakho, nolwazi lwendawo yedivayisi yakho.\n\nUkuze uthole ulwazi olwengeziwe, xhumana nomphathi wakho we-IT."</string>
<string name="monitoring_description_management" msgid="4308879039175729014">"Le divayisi ngeyenhlangano.\n\nUmphathi wakho we-IT angakwazi ukugada nokulawula amasethingi, ukufinyelela kwenhlangano, izinhlelo zokusebenza, idatha ehlobene nedivayisi yakho, nolwazi lwendawo yedivayisi yakho.\n\nUkuze uthole ulwazi olwengeziwe, xhumana nomphathi wakho we-IT."</string>
<string name="monitoring_description_management_ca_certificate" msgid="7785013130658110130">"Inhlangano yakho ifake ukugunyazwa kwesitifiketi kule divayisi. Ithrafikhi yenethiwekhi yakho evikelekile kungenzeka iqashelwe noma ilungiswe."</string>
@@ -567,6 +571,7 @@
<string name="monitoring_description_network_logging" msgid="577305979174002252">"Umlawuli wakho uvule ukungena kwenethiwekhi, okuhlola ithrafikhi kudivayisi yakho.\n\nNgolwazi olubanzi xhumana nomlawuli wakho."</string>
<string name="monitoring_description_vpn" msgid="1685428000684586870">"Unikeze uhlelo lokusebenza imvume yokusetha ukuxhumana kwe-VPN.\n\nLolu hlelo lokusebenza lungahlola idivayisi yakho nomsebenzi wenethiwekhi, ofaka ama-imeyili, izinhlelo zokusebenza, namawebhusayithi."</string>
<string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"Iphrofayela yakho yomsebenzi iphethwe ngu-<xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nUmlawuli wakho uyakwazi ukwengamela umsebenzi wakho wenethiwekhi kufaka phakathi ama-imeyili, izinhlelo zokusebenza, namawebhusayithi.\n\nNgolwazi olubanzi, xhumana nomlawuli wakho.\n\nFuthi uxhumekile ku-VPN, engangamela umsebenzi wakho wenethiwekhi."</string>
+ <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"Le divayisi iphethwe ngumzali wakho. Umzali wakho angabona futhi aphathe ulwazi olunjengezinhlelo zokusebenza ozisebenzisayo, indawo yakho, kanye nesikhathi sesikrini."</string>
<string name="legacy_vpn_name" msgid="4174223520162559145">"I-VPN"</string>
<string name="monitoring_description_app" msgid="376868879287922929">"Uxhumeke ku-<xliff:g id="APPLICATION">%1$s</xliff:g>, engaqapha umsebenzi wakho wenethiwekhi, ofaka ama-imeyili, izinhlelo zokusebenza, namawebhusayithi."</string>
<string name="monitoring_description_app_personal" msgid="1970094872688265987">"Uxhumeke ku-<xliff:g id="APPLICATION">%1$s</xliff:g>, engahlola umsebenzi wenethiwekhi yakho yomuntu siqu, ofaka ama-imeyili, izinhlelo zokusebenza, namawebhusayithi."</string>
@@ -1089,4 +1094,8 @@
<string name="media_output_dialog_pairing_new" msgid="9099497976087485862">"Bhanqa idivayisi entsha"</string>
<string name="build_number_clip_data_label" msgid="3623176728412560914">"Yakha inombolo"</string>
<string name="build_number_copy_toast" msgid="877720921605503046">"Yakha inombolo ekopishelwe kubhodi yokunamathisela."</string>
+ <!-- no translation found for battery_state_unknown_notification_title (8464703640483773454) -->
+ <skip />
+ <!-- no translation found for battery_state_unknown_notification_text (13720937839460899) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 2e845fbb21dd..31b0701360f6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -94,6 +94,7 @@ import com.android.settingslib.fuelgauge.BatteryStatus;
import com.android.systemui.DejankUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
+import com.android.systemui.biometrics.AuthController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
@@ -235,6 +236,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private final Context mContext;
private final boolean mIsPrimaryUser;
private final boolean mIsAutomotive;
+ private final AuthController mAuthController;
private final StatusBarStateController mStatusBarStateController;
HashMap<Integer, SimData> mSimDatas = new HashMap<>();
HashMap<Integer, ServiceState> mServiceStates = new HashMap<Integer, ServiceState>();
@@ -287,6 +289,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private final DevicePolicyManager mDevicePolicyManager;
private final BroadcastDispatcher mBroadcastDispatcher;
private boolean mLogoutEnabled;
+ // cached value to avoid IPCs
+ private boolean mIsUdfpsEnrolled;
// If the user long pressed the lock icon, disabling face auth for the current session.
private boolean mLockIconPressed;
private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -1581,7 +1585,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
RingerModeTracker ringerModeTracker,
@Background Executor backgroundExecutor,
StatusBarStateController statusBarStateController,
- LockPatternUtils lockPatternUtils) {
+ LockPatternUtils lockPatternUtils,
+ AuthController authController) {
mContext = context;
mSubscriptionManager = SubscriptionManager.from(context);
mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
@@ -1591,6 +1596,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mRingerModeTracker = ringerModeTracker;
mStatusBarStateController = statusBarStateController;
mLockPatternUtils = lockPatternUtils;
+ mAuthController = authController;
dumpManager.registerDumpable(getClass().getName(), this);
mHandler = new Handler(mainLooper) {
@@ -1853,7 +1859,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private void updateLockScreenMode() {
mLockScreenMode = Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.SHOW_NEW_LOCKSCREEN, 0);
+ Settings.Global.SHOW_NEW_LOCKSCREEN,
+ isUdfpsEnrolled() ? 1 : 0);
+ }
+
+ private void updateUdfpsEnrolled(int userId) {
+ mIsUdfpsEnrolled = mAuthController.isUdfpsEnrolled(userId);
+ }
+ public boolean isUdfpsEnrolled() {
+ return mIsUdfpsEnrolled;
}
private final UserSwitchObserver mUserSwitchObserver = new UserSwitchObserver() {
@@ -2094,6 +2108,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
int userId = getCurrentUser();
+ updateUdfpsEnrolled(userId);
if (isUnlockWithFingerprintPossible(userId)) {
if (mFingerprintCancelSignal != null) {
mFingerprintCancelSignal.cancel();
@@ -3065,6 +3080,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
+ " expected=" + (shouldListenForFingerprint() ? 1 : 0));
pw.println(" strongAuthFlags=" + Integer.toHexString(strongAuthFlags));
pw.println(" trustManaged=" + getUserTrustIsManaged(userId));
+ pw.println(" udfpsEnrolled=" + isUdfpsEnrolled());
}
if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
final int userId = ActivityManager.getCurrentUser();
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 8147f6619cd1..d3ac9accfdaf 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -89,6 +89,7 @@ import com.android.systemui.qs.SecureSetting;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
+import com.android.systemui.util.settings.SecureSettings;
import java.util.ArrayList;
import java.util.List;
@@ -120,6 +121,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
private final BroadcastDispatcher mBroadcastDispatcher;
private final Handler mMainHandler;
private final TunerService mTunerService;
+ private final SecureSettings mSecureSettings;
private DisplayManager.DisplayListener mDisplayListener;
private CameraAvailabilityListener mCameraListener;
private final UserTracker mUserTracker;
@@ -199,11 +201,13 @@ public class ScreenDecorations extends SystemUI implements Tunable {
@Inject
public ScreenDecorations(Context context,
@Main Handler handler,
+ SecureSettings secureSettings,
BroadcastDispatcher broadcastDispatcher,
TunerService tunerService,
UserTracker userTracker) {
super(context);
mMainHandler = handler;
+ mSecureSettings = secureSettings;
mBroadcastDispatcher = broadcastDispatcher;
mTunerService = tunerService;
mUserTracker = userTracker;
@@ -309,7 +313,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
// Watch color inversion and invert the overlay as needed.
if (mColorInversionSetting == null) {
- mColorInversionSetting = new SecureSetting(mContext, mHandler,
+ mColorInversionSetting = new SecureSetting(mSecureSettings, mHandler,
Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
mUserTracker.getUserId()) {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index d8e94bb45b75..b30103ef9b59 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -188,7 +188,7 @@ public class SystemUIFactory {
* This method is overridden in vendor specific implementation of Sys UI.
*/
public BackGestureTfClassifierProvider createBackGestureTfClassifierProvider(
- AssetManager am) {
+ AssetManager am, String modelName) {
return new BackGestureTfClassifierProvider();
}
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
index 64a2acab79ee..e40185c279a8 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
@@ -32,6 +32,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
@@ -67,7 +68,7 @@ class MagnificationModeSwitch {
private final int mTapTimeout = ViewConfiguration.getTapTimeout();
private final int mTouchSlop;
private int mMagnificationMode = Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
- private final WindowManager.LayoutParams mParams;
+ private final LayoutParams mParams;
private boolean mIsVisible = false;
MagnificationModeSwitch(Context context) {
@@ -80,7 +81,7 @@ class MagnificationModeSwitch {
mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
mWindowManager = (WindowManager) mContext.getSystemService(
Context.WINDOW_SERVICE);
- mParams = createLayoutParams();
+ mParams = createLayoutParams(context);
mImageView = imageView;
mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
applyResourcesValues();
@@ -221,11 +222,22 @@ class MagnificationModeSwitch {
}
void onConfigurationChanged(int configDiff) {
- if ((configDiff & ActivityInfo.CONFIG_DENSITY) == 0) {
+ if ((configDiff & ActivityInfo.CONFIG_DENSITY) != 0) {
+ applyResourcesValues();
+ mImageView.setImageResource(getIconResId(mMagnificationMode));
+ return;
+ }
+ if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) {
+ updateAccessibilityWindowTitle();
return;
}
- applyResourcesValues();
- mImageView.setImageResource(getIconResId(mMagnificationMode));
+ }
+
+ private void updateAccessibilityWindowTitle() {
+ mParams.accessibilityTitle = getAccessibilityWindowTitle(mContext);
+ if (mIsVisible) {
+ mWindowManager.updateViewLayout(mImageView, mParams);
+ }
}
private void toggleMagnificationMode() {
@@ -261,14 +273,19 @@ class MagnificationModeSwitch {
: R.drawable.ic_open_in_new_fullscreen;
}
- private static WindowManager.LayoutParams createLayoutParams() {
- final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
- WindowManager.LayoutParams.WRAP_CONTENT,
- WindowManager.LayoutParams.WRAP_CONTENT,
- WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,
- WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ private static LayoutParams createLayoutParams(Context context) {
+ final LayoutParams params = new LayoutParams(
+ LayoutParams.WRAP_CONTENT,
+ LayoutParams.WRAP_CONTENT,
+ LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,
+ LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSPARENT);
params.gravity = Gravity.BOTTOM | Gravity.RIGHT;
+ params.accessibilityTitle = getAccessibilityWindowTitle(context);
return params;
}
+
+ private static String getAccessibilityWindowTitle(Context context) {
+ return context.getString(com.android.internal.R.string.android_system_label);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
index e9e453b3d981..98424beab14e 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
@@ -53,7 +53,8 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall
CommandQueue.Callbacks {
private static final String TAG = "WindowMagnification";
private static final int CONFIG_MASK =
- ActivityInfo.CONFIG_DENSITY | ActivityInfo.CONFIG_ORIENTATION;
+ ActivityInfo.CONFIG_DENSITY | ActivityInfo.CONFIG_ORIENTATION
+ | ActivityInfo.CONFIG_LOCALE;
@VisibleForTesting
protected WindowMagnificationAnimationController mWindowMagnificationAnimationController;
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index 340ca044a1ef..fd89baa61657 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -16,7 +16,7 @@
package com.android.systemui.accessibility;
-import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+import static android.view.WindowManager.LayoutParams;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
@@ -254,9 +254,18 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
}
} else if ((configDiff & ActivityInfo.CONFIG_ORIENTATION) != 0) {
onRotate();
+ } else if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) {
+ updateAccessibilityWindowTitleIfNeeded();
}
}
+ private void updateAccessibilityWindowTitleIfNeeded() {
+ if (!isWindowVisible()) return;
+ LayoutParams params = (LayoutParams) mMirrorView.getLayoutParams();
+ params.accessibilityTitle = getAccessibilityWindowTitle();
+ mWm.updateViewLayout(mMirrorView, params);
+ }
+
/** Handles MirrorWindow position when the navigation bar mode changed. */
public void onNavigationModeChanged(int mode) {
mNavBarMode = mode;
@@ -290,8 +299,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
return;
}
// The rect of MirrorView is going to be transformed.
- WindowManager.LayoutParams params =
- (WindowManager.LayoutParams) mMirrorView.getLayoutParams();
+ LayoutParams params =
+ (LayoutParams) mMirrorView.getLayoutParams();
mTmpRect.set(params.x, params.y, params.x + params.width, params.y + params.height);
final RectF transformedRect = new RectF(mTmpRect);
matrix.mapRect(transformedRect);
@@ -313,17 +322,18 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
int windowWidth = mMagnificationFrame.width() + 2 * mMirrorSurfaceMargin;
int windowHeight = mMagnificationFrame.height() + 2 * mMirrorSurfaceMargin;
- WindowManager.LayoutParams params = new WindowManager.LayoutParams(
+ LayoutParams params = new LayoutParams(
windowWidth, windowHeight,
- WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,
- WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY,
+ LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSPARENT);
params.gravity = Gravity.TOP | Gravity.LEFT;
params.x = mMagnificationFrame.left - mMirrorSurfaceMargin;
params.y = mMagnificationFrame.top - mMirrorSurfaceMargin;
- params.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+ params.layoutInDisplayCutoutMode = LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
params.setTitle(mContext.getString(R.string.magnification_window_title));
+ params.accessibilityTitle = getAccessibilityWindowTitle();
mMirrorView = LayoutInflater.from(mContext).inflate(R.layout.window_magnifier_view, null);
mMirrorSurfaceView = mMirrorView.findViewById(R.id.surface_view);
@@ -369,6 +379,10 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
return regionInsideDragBorder;
}
+ private String getAccessibilityWindowTitle() {
+ return mResources.getString(com.android.internal.R.string.android_system_label);
+ }
+
private void showControls() {
if (mMirrorWindowControl != null) {
mMirrorWindowControl.showControl();
@@ -432,8 +446,8 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
}
final int maxMirrorViewX = mDisplaySize.x - mMirrorView.getWidth();
final int maxMirrorViewY = mDisplaySize.y - mMirrorView.getHeight() - mNavGestureHeight;
- WindowManager.LayoutParams params =
- (WindowManager.LayoutParams) mMirrorView.getLayoutParams();
+ LayoutParams params =
+ (LayoutParams) mMirrorView.getLayoutParams();
params.x = mMagnificationFrame.left - mMirrorSurfaceMargin;
params.y = mMagnificationFrame.top - mMirrorSurfaceMargin;
// If nav bar mode supports swipe-up gesture, the Y position of mirror view should not
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 874c73baf146..a6b1b90317f9 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -29,6 +29,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
+import android.graphics.RectF;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.IBiometricSysuiReceiver;
@@ -42,6 +43,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
+import android.view.MotionEvent;
import android.view.WindowManager;
import com.android.internal.R;
@@ -54,6 +56,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
+import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
@@ -79,6 +82,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
@Nullable private final List<FingerprintSensorPropertiesInternal> mFpProps;
@Nullable private final List<FaceSensorPropertiesInternal> mFaceProps;
+ @Nullable private final List<FingerprintSensorPropertiesInternal> mUdfpsProps;
// TODO: These should just be saved from onSaveState
private SomeArgs mCurrentDialogArgs;
@@ -243,16 +247,25 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
}
/**
+ * @return where the UDFPS exists on the screen in pixels.
+ */
+ public RectF getUdfpsRegion() {
+ return mUdfpsController == null ? null : mUdfpsController.getSensorLocation();
+ }
+
+ /**
* Requests fingerprint scan.
*
* @param screenX X position of long press
* @param screenY Y position of long press
+ * @param major length of the major axis. See {@link MotionEvent#AXIS_TOOL_MAJOR}.
+ * @param minor length of the minor axis. See {@link MotionEvent#AXIS_TOOL_MINOR}.
*/
- public void onAodInterrupt(int screenX, int screenY) {
+ public void onAodInterrupt(int screenX, int screenY, float major, float minor) {
if (mUdfpsController == null) {
return;
}
- mUdfpsController.onAodInterrupt(screenX, screenY);
+ mUdfpsController.onAodInterrupt(screenX, screenY, major, minor);
}
/**
@@ -303,6 +316,16 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
: null;
mFaceProps = mFaceManager != null ? mFaceManager.getSensorPropertiesInternal() : null;
+ List<FingerprintSensorPropertiesInternal> udfpsProps = new ArrayList<>();
+ if (mFpProps != null) {
+ for (FingerprintSensorPropertiesInternal props : mFpProps) {
+ if (props.isAnyUdfpsType()) {
+ udfpsProps.add(props);
+ }
+ }
+ }
+ mUdfpsProps = !udfpsProps.isEmpty() ? udfpsProps : null;
+
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
@@ -315,15 +338,9 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
mCommandQueue.addCallback(this);
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
- if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()) {
- final List<FingerprintSensorPropertiesInternal> fingerprintSensorProperties =
- mFingerprintManager.getSensorPropertiesInternal();
- for (FingerprintSensorPropertiesInternal props : fingerprintSensorProperties) {
- if (props.isAnyUdfpsType()) {
- mUdfpsController = mUdfpsControllerFactory.get();
- break;
- }
- }
+ if (mFingerprintManager != null && mFingerprintManager.isHardwareDetected()
+ && mUdfpsProps != null) {
+ mUdfpsController = mUdfpsControllerFactory.get();
}
try {
@@ -473,12 +490,14 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
}
/**
- * Whether the current user has a UDFP enrolled.
+ * Whether the passed userId has enrolled UDFPS.
*/
- public boolean hasUdfpsEnrolled() {
- // TODO: (b/171392825) right now only checks whether the UDFPS sensor exists on this device
- // but not whether user has enrolled or not
- return mUdfpsController != null;
+ public boolean isUdfpsEnrolled(int userId) {
+ if (mUdfpsController == null) {
+ return false;
+ }
+
+ return mFingerprintManager.hasEnrolledTemplatesForAnySensor(userId, mUdfpsProps);
}
private void showDialog(SomeArgs args, boolean skipAnimation, Bundle savedState) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 3c2e00869ab8..a4b407d2785d 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -25,6 +25,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.graphics.Point;
+import android.graphics.RectF;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IUdfpsOverlayController;
@@ -244,6 +245,13 @@ class UdfpsController implements DozeReceiver {
mView.dozeTimeTick();
}
+ /**
+ * @return where the UDFPS exists on the screen in pixels.
+ */
+ public RectF getSensorLocation() {
+ return mView.getSensorRect();
+ }
+
private void setShowOverlay(boolean show) {
if (show == mIsOverlayRequested) {
return;
@@ -337,7 +345,7 @@ class UdfpsController implements DozeReceiver {
* This is intented to be called in response to a sensor that triggers an AOD interrupt for the
* fingerprint sensor.
*/
- void onAodInterrupt(int screenX, int screenY) {
+ void onAodInterrupt(int screenX, int screenY, float major, float minor) {
if (mIsAodInterruptActive) {
return;
}
@@ -348,7 +356,7 @@ class UdfpsController implements DozeReceiver {
mCancelAodTimeoutAction = mFgExecutor.executeDelayed(this::onCancelAodInterrupt,
AOD_INTERRUPT_TIMEOUT_MILLIS);
// using a hard-coded value for major and minor until it is available from the sensor
- onFingerDown(screenX, screenY, 13.0f, 13.0f);
+ onFingerDown(screenX, screenY, minor, major);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
index 0ed3bda40c4b..7edcf66196e4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
@@ -196,6 +196,10 @@ public class UdfpsView extends View implements DozeReceiver,
canvas.restore();
}
+ RectF getSensorRect() {
+ return new RectF(mSensorRect);
+ }
+
void setHbmSupported(boolean hbmSupported) {
mHbmSupported = hbmSupported;
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 8220835ac509..ebfce661c9af 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -44,6 +44,7 @@ import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLoggerImpl;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.plugins.SensorManagerPlugin;
import com.android.systemui.statusbar.phone.DozeParameters;
@@ -156,7 +157,7 @@ public class DozeSensors {
findSensorWithType(config.udfpsLongPressSensorType()),
"doze_pulse_on_auth",
true /* settingDef */,
- authController.hasUdfpsEnrolled() /* configured */,
+ authController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser()),
DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS,
true /* reports touch coordinates */,
true /* touchscreen */,
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index c581e85ec444..58e49f896931 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -131,7 +131,10 @@ public class DozeTriggers implements DozeMachine.Part {
DOZING_UPDATE_SENSOR_WAKE_LOCKSCREEN(440),
@UiEvent(doc = "Dozing updated because sensor was tapped.")
- DOZING_UPDATE_SENSOR_TAP(441);
+ DOZING_UPDATE_SENSOR_TAP(441),
+
+ @UiEvent(doc = "Dozing updated because on display auth was triggered from AOD.")
+ DOZING_UPDATE_AUTH_TRIGGERED(442);
private final int mId;
@@ -155,6 +158,7 @@ public class DozeTriggers implements DozeMachine.Part {
case 7: return DOZING_UPDATE_SENSOR_WAKEUP;
case 8: return DOZING_UPDATE_SENSOR_WAKE_LOCKSCREEN;
case 9: return DOZING_UPDATE_SENSOR_TAP;
+ case 10: return DOZING_UPDATE_AUTH_TRIGGERED;
default: return null;
}
}
@@ -289,7 +293,8 @@ public class DozeTriggers implements DozeMachine.Part {
requestPulse(DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS, true, null);
// Since the gesture won't be received by the UDFPS view, manually inject an
// event.
- mAuthController.onAodInterrupt((int) screenX, (int) screenY);
+ mAuthController.onAodInterrupt((int) screenX, (int) screenY,
+ rawValues[2] /* major */, rawValues[3] /* minor */);
} else {
mDozeHost.extendPulse(pulseReason);
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index 1beb875af70c..5eb6687f0b81 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -143,6 +143,11 @@ class MediaCarouselController @Inject constructor(
if (newConfig == null) return
isRtl = newConfig.layoutDirection == View.LAYOUT_DIRECTION_RTL
}
+
+ override fun onUiModeChanged() {
+ // Only settings button needs to update for dark theme
+ inflateSettingsButton()
+ }
}
init {
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 6f6ee4c8091d..c6ed9c096544 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -641,7 +641,8 @@ class MediaDataManager(
// Move to resume key (aka package name) if that key doesn't already exist.
val resumeAction = getResumeMediaAction(removed.resumeAction!!)
val updated = removed.copy(token = null, actions = listOf(resumeAction),
- actionsToShowInCompact = listOf(0), active = false, resumption = true)
+ actionsToShowInCompact = listOf(0), active = false, resumption = true,
+ isClearable = true)
val pkg = removed.packageName
val migrate = mediaEntries.put(pkg, updated) == null
// Notify listeners of "new" controls when migrating or removed and update when not
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index d26f7ab6d78c..0d5faff65aab 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -22,6 +22,7 @@ import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.text.SpannableString;
+import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.View;
@@ -45,6 +46,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private ViewGroup mConnectedItem;
+ private boolean mInclueDynamicGroup;
public MediaOutputAdapter(MediaOutputController controller) {
super(controller);
@@ -61,9 +63,21 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
@Override
public void onBindViewHolder(@NonNull MediaDeviceBaseViewHolder viewHolder, int position) {
final int size = mController.getMediaDevices().size();
- if (mController.isZeroMode() && position == size) {
+ if (position == size && mController.isZeroMode()) {
viewHolder.onBind(CUSTOMIZED_ITEM_PAIR_NEW, false /* topMargin */,
true /* bottomMargin */);
+ } else if (mInclueDynamicGroup) {
+ if (position == 0) {
+ viewHolder.onBind(CUSTOMIZED_ITEM_DYNAMIC_GROUP, true /* topMargin */,
+ false /* bottomMargin */);
+ } else {
+ // When group item is added at the first(position == 0), devices will be added from
+ // the second item(position == 1). It means that the index of device list starts
+ // from "position - 1".
+ viewHolder.onBind(((List<MediaDevice>) (mController.getMediaDevices()))
+ .get(position - 1),
+ false /* topMargin */, position == size /* bottomMargin */);
+ }
} else if (position < size) {
viewHolder.onBind(((List<MediaDevice>) (mController.getMediaDevices())).get(position),
position == 0 /* topMargin */, position == (size - 1) /* bottomMargin */);
@@ -74,8 +88,9 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
@Override
public int getItemCount() {
- if (mController.isZeroMode()) {
- // Add extra one for "pair new"
+ mInclueDynamicGroup = mController.getSelectedMediaDevice().size() > 1;
+ if (mController.isZeroMode() || mInclueDynamicGroup) {
+ // Add extra one for "pair new" or dynamic group
return mController.getMediaDevices().size() + 1;
}
return mController.getMediaDevices().size();
@@ -107,7 +122,7 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
@Override
void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin) {
super.onBind(device, topMargin, bottomMargin);
- final boolean currentlyConnected = isCurrentlyConnected(device);
+ final boolean currentlyConnected = !mInclueDynamicGroup && isCurrentlyConnected(device);
if (currentlyConnected) {
mConnectedItem = mContainerLayout;
}
@@ -167,6 +182,22 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter {
Utils.getColorAccentDefaultColor(mContext), PorterDuff.Mode.SRC_IN));
mTitleIcon.setImageDrawable(d);
mContainerLayout.setOnClickListener(v -> onItemClick(CUSTOMIZED_ITEM_PAIR_NEW));
+ } else if (customizedItem == CUSTOMIZED_ITEM_DYNAMIC_GROUP) {
+ mConnectedItem = mContainerLayout;
+ mBottomDivider.setVisibility(View.GONE);
+ mCheckBox.setVisibility(View.GONE);
+ mDivider.setVisibility(View.VISIBLE);
+ mDivider.setTransitionAlpha(1);
+ mAddIcon.setVisibility(View.VISIBLE);
+ mAddIcon.setTransitionAlpha(1);
+ mAddIcon.setOnClickListener(v -> onEndItemClick());
+ mTitleIcon.setImageDrawable(getSpeakerDrawable());
+ final CharSequence sessionName = mController.getSessionName();
+ final CharSequence title = TextUtils.isEmpty(sessionName)
+ ? mContext.getString(R.string.media_output_dialog_group) : sessionName;
+ setTwoLineLayout(title, true /* bFocused */, true /* showSeekBar */,
+ false /* showProgressBar */, false /* showSubtitle */);
+ initSessionSeekbar();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index 536b7598ce22..f1d4804aa622 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -19,7 +19,11 @@ package com.android.systemui.media.dialog;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
@@ -35,6 +39,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
+import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.media.MediaDevice;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
@@ -47,6 +52,7 @@ public abstract class MediaOutputBaseAdapter extends
static final int CUSTOMIZED_ITEM_PAIR_NEW = 1;
static final int CUSTOMIZED_ITEM_GROUP = 2;
+ static final int CUSTOMIZED_ITEM_DYNAMIC_GROUP = 3;
final MediaOutputController mController;
@@ -223,6 +229,34 @@ public abstract class MediaOutputBaseAdapter extends
});
}
+ void initSessionSeekbar() {
+ mSeekBar.setMax(mController.getSessionVolumeMax());
+ mSeekBar.setMin(0);
+ final int currentVolume = mController.getSessionVolume();
+ if (mSeekBar.getProgress() != currentVolume) {
+ mSeekBar.setProgress(currentVolume);
+ }
+ mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (!fromUser) {
+ return;
+ }
+ mController.adjustSessionVolume(progress);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ mIsDragging = true;
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ mIsDragging = false;
+ }
+ });
+ }
+
void playSwitchingAnim(@NonNull View from, @NonNull View to) {
final float delta = (float) (mContext.getResources().getDimensionPixelSize(
R.dimen.media_output_dialog_title_anim_y_delta));
@@ -274,5 +308,15 @@ public abstract class MediaOutputBaseAdapter extends
}
});
}
+
+ Drawable getSpeakerDrawable() {
+ final Drawable drawable = mContext.getDrawable(R.drawable.ic_speaker_group_black_24dp)
+ .mutate();
+ final ColorStateList list = mContext.getResources().getColorStateList(
+ R.color.advanced_icon_color, mContext.getTheme());
+ drawable.setColorFilter(new PorterDuffColorFilter(list.getDefaultColor(),
+ PorterDuff.Mode.SRC_IN));
+ return BluetoothUtils.buildAdvancedDrawable(mContext, drawable);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
index ceb4495bd8e8..24e076bb22f1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
@@ -16,22 +16,17 @@
package com.android.systemui.media.dialog;
-import android.content.res.ColorStateList;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.SeekBar;
import androidx.annotation.NonNull;
-import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.media.MediaDevice;
import com.android.systemui.R;
@@ -155,34 +150,6 @@ public class MediaOutputGroupAdapter extends MediaOutputBaseAdapter {
}
}
- private void initSessionSeekbar() {
- mSeekBar.setMax(mController.getSessionVolumeMax());
- mSeekBar.setMin(0);
- final int currentVolume = mController.getSessionVolume();
- if (mSeekBar.getProgress() != currentVolume) {
- mSeekBar.setProgress(currentVolume);
- }
- mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
- @Override
- public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- if (!fromUser) {
- return;
- }
- mController.adjustSessionVolume(progress);
- }
-
- @Override
- public void onStartTrackingTouch(SeekBar seekBar) {
- mIsDragging = true;
- }
-
- @Override
- public void onStopTrackingTouch(SeekBar seekBar) {
- mIsDragging = false;
- }
- });
- }
-
private Drawable getDisabledCheckboxDrawable() {
final Drawable drawable = mContext.getDrawable(R.drawable.ic_check_box_blue_24dp)
.mutate();
@@ -198,16 +165,6 @@ public class MediaOutputGroupAdapter extends MediaOutputBaseAdapter {
return drawable;
}
- private Drawable getSpeakerDrawable() {
- final Drawable drawable = mContext.getDrawable(R.drawable.ic_speaker_group_black_24dp)
- .mutate();
- final ColorStateList list = mContext.getResources().getColorStateList(
- R.color.advanced_icon_color, mContext.getTheme());
- drawable.setColorFilter(new PorterDuffColorFilter(list.getDefaultColor(),
- PorterDuff.Mode.SRC_IN));
- return BluetoothUtils.buildAdvancedDrawable(mContext, drawable);
- }
-
private boolean isDeviceIncluded(List<MediaDevice> deviceList, MediaDevice targetDevice) {
for (MediaDevice device : deviceList) {
if (TextUtils.equals(device.getId(), targetDevice.getId())) {
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 18cc746666d8..f9982d04e04b 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -137,7 +137,9 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
&& (properties.getKeyset().contains(
SystemUiDeviceConfigFlags.BACK_GESTURE_ML_MODEL_THRESHOLD)
|| properties.getKeyset().contains(
- SystemUiDeviceConfigFlags.USE_BACK_GESTURE_ML_MODEL))) {
+ SystemUiDeviceConfigFlags.USE_BACK_GESTURE_ML_MODEL)
+ || properties.getKeyset().contains(
+ SystemUiDeviceConfigFlags.BACK_GESTURE_ML_MODEL_NAME))) {
updateMLModelState();
}
}
@@ -483,14 +485,15 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
private void updateMLModelState() {
boolean newState = mIsEnabled && DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.USE_BACK_GESTURE_ML_MODEL, false);
-
if (newState == mUseMLModel) {
return;
}
if (newState) {
+ String mlModelName = DeviceConfig.getString(DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.BACK_GESTURE_ML_MODEL_NAME, "backgesture");
mBackGestureTfClassifierProvider = SystemUIFactory.getInstance()
- .createBackGestureTfClassifierProvider(mContext.getAssets());
+ .createBackGestureTfClassifierProvider(mContext.getAssets(), mlModelName);
mMLModelThreshold = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.BACK_GESTURE_ML_MODEL_THRESHOLD, 0.9f);
if (mBackGestureTfClassifierProvider.isActive()) {
@@ -540,21 +543,22 @@ public class EdgeBackGestureHandler extends CurrentUserTracker implements Displa
boolean withinRange = false;
float results = -1;
+ // Disallow if we are in the bottom gesture area
+ if (y >= (mDisplaySize.y - mBottomGestureHeight)) {
+ return false;
+ }
+ // If the point is way too far (twice the margin), it is
+ // not interesting to us for logging purposes, nor we
+ // should process it. Simply return false and keep
+ // mLogGesture = false.
+ if (x > 2 * (mEdgeWidthLeft + mLeftInset)
+ && x < (mDisplaySize.x - 2 * (mEdgeWidthRight + mRightInset))) {
+ return false;
+ }
+
if (mUseMLModel && (results = getBackGesturePredictionsCategory(x, y)) != -1) {
withinRange = results == 1 ? true : false;
} else {
- // Disallow if we are in the bottom gesture area
- if (y >= (mDisplaySize.y - mBottomGestureHeight)) {
- return false;
- }
- // If the point is way too far (twice the margin), it is
- // not interesting to us for logging purposes, nor we
- // should process it. Simply return false and keep
- // mLogGesture = false.
- if (x > 2 * (mEdgeWidthLeft + mLeftInset)
- && x < (mDisplaySize.x - 2 * (mEdgeWidthRight + mRightInset))) {
- return false;
- }
// Denotes whether we should proceed with the gesture.
// Even if it is false, we may want to log it assuming
// it is not invalid due to exclusion.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java b/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
index 3ee3e117fb0f..994da9a174df 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
@@ -16,18 +16,17 @@
package com.android.systemui.qs;
-import android.content.Context;
import android.database.ContentObserver;
import android.os.Handler;
-import android.provider.Settings.Secure;
import com.android.systemui.statusbar.policy.Listenable;
+import com.android.systemui.util.settings.SecureSettings;
/** Helper for managing a secure setting. **/
public abstract class SecureSetting extends ContentObserver implements Listenable {
private static final int DEFAULT = 0;
- private final Context mContext;
+ private SecureSettings mSecureSettings;
private final String mSettingName;
private boolean mListening;
@@ -36,19 +35,20 @@ public abstract class SecureSetting extends ContentObserver implements Listenabl
protected abstract void handleValueChanged(int value, boolean observedChange);
- public SecureSetting(Context context, Handler handler, String settingName, int userId) {
+ public SecureSetting(SecureSettings secureSettings, Handler handler, String settingName,
+ int userId) {
super(handler);
- mContext = context;
+ mSecureSettings = secureSettings;
mSettingName = settingName;
mUserId = userId;
}
public int getValue() {
- return Secure.getIntForUser(mContext.getContentResolver(), mSettingName, DEFAULT, mUserId);
+ return mSecureSettings.getIntForUser(mSettingName, DEFAULT, mUserId);
}
public void setValue(int value) {
- Secure.putIntForUser(mContext.getContentResolver(), mSettingName, value, mUserId);
+ mSecureSettings.putIntForUser(mSettingName, value, mUserId);
}
@Override
@@ -57,10 +57,10 @@ public abstract class SecureSetting extends ContentObserver implements Listenabl
mListening = listening;
if (listening) {
mObservedValue = getValue();
- mContext.getContentResolver().registerContentObserver(
- Secure.getUriFor(mSettingName), false, this, mUserId);
+ mSecureSettings.registerContentObserverForUser(
+ mSecureSettings.getUriFor(mSettingName), false, this, mUserId);
} else {
- mContext.getContentResolver().unregisterContentObserver(this);
+ mSecureSettings.unregisterContentObserver(this);
mObservedValue = DEFAULT;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
index 7c799aefe90d..cfc81eee9b3c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
@@ -30,6 +30,7 @@ import com.android.systemui.statusbar.phone.ManagedProfileController;
import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.util.settings.SecureSettings;
import dagger.Binds;
import dagger.Module;
@@ -48,14 +49,24 @@ public interface QSModule {
AutoAddTracker.Builder autoAddTrackerBuilder,
QSTileHost host,
@Background Handler handler,
+ SecureSettings secureSettings,
HotspotController hotspotController,
DataSaverController dataSaverController,
ManagedProfileController managedProfileController,
NightDisplayListener nightDisplayListener,
CastController castController) {
- AutoTileManager manager = new AutoTileManager(context, autoAddTrackerBuilder,
- host, handler, hotspotController, dataSaverController, managedProfileController,
- nightDisplayListener, castController);
+ AutoTileManager manager = new AutoTileManager(
+ context,
+ autoAddTrackerBuilder,
+ host,
+ handler,
+ secureSettings,
+ hotspotController,
+ dataSaverController,
+ managedProfileController,
+ nightDisplayListener,
+ castController
+ );
manager.init();
return manager;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index c64fc50b8237..bf3e4be9b9db 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -36,6 +36,7 @@ import com.android.systemui.qs.SecureSetting;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.util.settings.SecureSettings;
import javax.inject.Inject;
@@ -62,15 +63,20 @@ public class BatterySaverTile extends QSTileImpl<BooleanState> implements
StatusBarStateController statusBarStateController,
ActivityStarter activityStarter,
QSLogger qsLogger,
- BatteryController batteryController
+ BatteryController batteryController,
+ SecureSettings secureSettings
) {
super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController,
activityStarter, qsLogger);
mBatteryController = batteryController;
mBatteryController.observe(getLifecycle(), this);
int currentUser = host.getUserContext().getUserId();
- mSetting = new SecureSetting(mContext, mHandler, Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
- currentUser) {
+ mSetting = new SecureSetting(
+ secureSettings,
+ mHandler,
+ Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
+ currentUser
+ ) {
@Override
protected void handleValueChanged(int value, boolean observedChange) {
// mHandler is the background handler so calling this is OK
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
index 5e6a6ce45b46..f742752d80be 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/CellularTile.java
@@ -25,6 +25,7 @@ import android.content.Intent;
import android.content.res.Resources;
import android.os.Handler;
import android.os.Looper;
+import android.os.UserHandle;
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.telephony.SubscriptionManager;
@@ -244,7 +245,8 @@ public class CellularTile extends QSTileImpl<SignalState> {
@Override
public boolean isAvailable() {
- return mController.hasMobileDataFeature();
+ return mController.hasMobileDataFeature()
+ && mHost.getUserContext().getUserId() == UserHandle.USER_SYSTEM;
}
private static final class CallbackInfo {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 98782f7c8b55..39952488799a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -39,6 +39,7 @@ import com.android.systemui.qs.SecureSetting;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.settings.UserTracker;
+import com.android.systemui.util.settings.SecureSettings;
import javax.inject.Inject;
@@ -63,12 +64,13 @@ public class ColorInversionTile extends QSTileImpl<BooleanState> {
StatusBarStateController statusBarStateController,
ActivityStarter activityStarter,
QSLogger qsLogger,
- UserTracker userTracker
+ UserTracker userTracker,
+ SecureSettings secureSettings
) {
super(host, backgroundLooper, mainHandler, metricsLogger, statusBarStateController,
activityStarter, qsLogger);
- mSetting = new SecureSetting(mContext, mainHandler,
+ mSetting = new SecureSetting(secureSettings, mainHandler,
Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, userTracker.getUserId()) {
@Override
protected void handleValueChanged(int value, boolean observedChange) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 7a976ac82223..6ff5ed1bceae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -236,6 +236,7 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
NotificationChannel.DEFAULT_CHANNEL_ID)
&& numTotalChannels == 1;
}
+ mIsAutomaticChosen = getAlertingBehavior() == BEHAVIOR_AUTOMATIC;
bindHeader();
bindChannelDetails();
@@ -658,13 +659,14 @@ public class NotificationInfo extends LinearLayout implements NotificationGuts.G
try {
if (mChannelToUpdate != null) {
if (mUnlockImportance) {
- mChannelToUpdate.unlockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+ mINotificationManager.unlockNotificationChannel(
+ mPackageName, mAppUid, mChannelToUpdate.getId());
} else {
mChannelToUpdate.setImportance(mNewImportance);
mChannelToUpdate.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+ mINotificationManager.updateNotificationChannelForPackage(
+ mPackageName, mAppUid, mChannelToUpdate);
}
- mINotificationManager.updateNotificationChannelForPackage(
- mPackageName, mAppUid, mChannelToUpdate);
} else {
// For notifications with more than one channel, update notification enabled
// state. If the importance was lowered, we disable notifications.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 5cee5bd0cc4e..2a2a0b14a2d2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -835,7 +835,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
if (!mShouldDrawNotificationBackground) {
return;
}
-
+ final boolean clearUndershelf = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.SHOW_NEW_NOTIF_DISMISS, 0 /* show background by default */) == 1;
+ if (clearUndershelf) {
+ mBackgroundPaint.setColor(Color.TRANSPARENT);
+ invalidate();
+ return;
+ }
// Interpolate between semi-transparent notification panel background color
// and white AOD separator.
float colorInterpolation = MathUtils.smoothStep(0.4f /* start */, 1f /* end */,
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 76c5baf6e9f6..3622f1cd3952 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -36,6 +36,7 @@ import com.android.systemui.statusbar.policy.DataSaverController.Listener;
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.HotspotController.Callback;
import com.android.systemui.util.UserAwareController;
+import com.android.systemui.util.settings.SecureSettings;
import java.util.ArrayList;
import java.util.Objects;
@@ -60,6 +61,7 @@ public class AutoTileManager implements UserAwareController {
protected final Context mContext;
protected final QSTileHost mHost;
protected final Handler mHandler;
+ protected final SecureSettings mSecureSettings;
protected final AutoAddTracker mAutoTracker;
private final HotspotController mHotspotController;
private final DataSaverController mDataSaverController;
@@ -71,6 +73,7 @@ public class AutoTileManager implements UserAwareController {
public AutoTileManager(Context context, AutoAddTracker.Builder autoAddTrackerBuilder,
QSTileHost host,
@Background Handler handler,
+ SecureSettings secureSettings,
HotspotController hotspotController,
DataSaverController dataSaverController,
ManagedProfileController managedProfileController,
@@ -78,6 +81,7 @@ public class AutoTileManager implements UserAwareController {
CastController castController) {
mContext = context;
mHost = host;
+ mSecureSettings = secureSettings;
mCurrentUser = mHost.getUserContext().getUser();
mAutoTracker = autoAddTrackerBuilder.setUserId(mCurrentUser.getIdentifier()).build();
mHandler = handler;
@@ -170,7 +174,7 @@ public class AutoTileManager implements UserAwareController {
String spec = split[1];
// Populate all the settings. As they may not have been added in other users
AutoAddSetting s = new AutoAddSetting(
- mContext, mHandler, setting, mCurrentUser.getIdentifier(), spec);
+ mSecureSettings, mHandler, setting, mCurrentUser.getIdentifier(), spec);
mAutoAddSettingList.add(s);
} else {
Log.w(TAG, "Malformed item in array: " + tile);
@@ -321,13 +325,13 @@ public class AutoTileManager implements UserAwareController {
private final String mSpec;
AutoAddSetting(
- Context context,
+ SecureSettings secureSettings,
Handler handler,
String setting,
int userId,
String tileSpec
) {
- super(context, handler, setting, userId);
+ super(secureSettings, handler, setting, userId);
mSpec = tileSpec;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index ef4108b9762d..bd228933c8a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -86,9 +86,14 @@ public class KeyguardClockPositionAlgorithm {
private int mMaxShadeBottom;
/**
- * Minimum distance from the status bar.
+ * Recommended distance from the status bar without the lock icon.
*/
- private int mContainerTopPadding;
+ private int mContainerTopPaddingWithoutLockIcon;
+
+ /**
+ * Recommended distance from the status bar with the lock icon.
+ */
+ private int mContainerTopPaddingWithLockIcon;
/**
* @see NotificationPanelViewController#getExpandedFraction()
@@ -131,24 +136,31 @@ public class KeyguardClockPositionAlgorithm {
public void loadDimens(Resources res) {
mClockNotificationsMargin = res.getDimensionPixelSize(
R.dimen.keyguard_clock_notifications_margin);
+
+ mContainerTopPaddingWithoutLockIcon =
+ res.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin) / 2;
// Consider the lock icon when determining the minimum top padding between the status bar
// and top of the clock.
- mContainerTopPadding = Math.max(res.getDimensionPixelSize(
- R.dimen.keyguard_clock_top_margin),
- res.getDimensionPixelSize(R.dimen.keyguard_lock_height)
- + res.getDimensionPixelSize(R.dimen.keyguard_lock_padding)
- + res.getDimensionPixelSize(R.dimen.keyguard_clock_lock_margin));
+ mContainerTopPaddingWithLockIcon =
+ Math.max(res.getDimensionPixelSize(R.dimen.keyguard_clock_top_margin),
+ res.getDimensionPixelSize(R.dimen.keyguard_lock_height)
+ + res.getDimensionPixelSize(R.dimen.keyguard_lock_padding)
+ + res.getDimensionPixelSize(R.dimen.keyguard_clock_lock_margin));
mBurnInPreventionOffsetX = res.getDimensionPixelSize(
R.dimen.burn_in_prevention_offset_x);
mBurnInPreventionOffsetY = res.getDimensionPixelSize(
R.dimen.burn_in_prevention_offset_y);
}
- public void setup(int minTopMargin, int maxShadeBottom, int notificationStackHeight,
+ /**
+ * Sets up algorithm values.
+ */
+ public void setup(int statusBarMinHeight, int maxShadeBottom, int notificationStackHeight,
float panelExpansion, int parentHeight, int keyguardStatusHeight, int clockPreferredY,
boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float emptyDragAmount,
- boolean bypassEnabled, int unlockedStackScrollerPadding) {
- mMinTopMargin = minTopMargin + mContainerTopPadding;
+ boolean bypassEnabled, int unlockedStackScrollerPadding, boolean udfpsEnrolled) {
+ mMinTopMargin = statusBarMinHeight + (udfpsEnrolled ? mContainerTopPaddingWithoutLockIcon :
+ mContainerTopPaddingWithLockIcon);
mMaxShadeBottom = maxShadeBottom;
mNotificationStackHeight = notificationStackHeight;
mPanelExpansion = panelExpansion;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
index 77ae059a0cb9..289ff71dcb46 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone;
+import static android.view.View.GONE;
+
import static com.android.systemui.statusbar.phone.LockIcon.STATE_BIOMETRICS_ERROR;
import static com.android.systemui.statusbar.phone.LockIcon.STATE_LOCKED;
import static com.android.systemui.statusbar.phone.LockIcon.STATE_LOCK_OPEN;
@@ -502,6 +504,11 @@ public class LockscreenLockIconController {
* @return true if the visibility changed
*/
private boolean updateIconVisibility() {
+ if (mKeyguardUpdateMonitor.isUdfpsEnrolled()) {
+ boolean changed = mLockIcon.getVisibility() == GONE;
+ mLockIcon.setVisibility(GONE);
+ return changed;
+ }
boolean onAodOrDocked = mStatusBarStateController.isDozing() || mDocked;
boolean invisible = onAodOrDocked || mWakeAndUnlockRunning || mShowingLaunchAffordance;
boolean fingerprintOrBypass = mFingerprintUnlock
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index b185f48b0245..231d157322ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -77,6 +77,7 @@ import com.android.keyguard.dagger.KeyguardStatusViewComponent;
import com.android.systemui.DejankUtils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.biometrics.AuthController;
import com.android.systemui.classifier.Classifier;
import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main;
@@ -263,6 +264,7 @@ public class NotificationPanelViewController extends PanelViewController {
private final KeyguardBypassController mKeyguardBypassController;
private final KeyguardUpdateMonitor mUpdateMonitor;
private final ConversationNotificationManager mConversationNotificationManager;
+ private final AuthController mAuthController;
private final MediaHierarchyManager mMediaHierarchyManager;
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
@@ -516,7 +518,8 @@ public class NotificationPanelViewController extends PanelViewController {
NotificationStackScrollLayoutController notificationStackScrollLayoutController,
KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory,
NotificationGroupManagerLegacy groupManager,
- NotificationIconAreaController notificationIconAreaController) {
+ NotificationIconAreaController notificationIconAreaController,
+ AuthController authController) {
super(view, falsingManager, dozeLog, keyguardStateController,
(SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
latencyTracker, flingAnimationUtilsBuilder, statusBarTouchableRegionManager);
@@ -581,6 +584,7 @@ public class NotificationPanelViewController extends PanelViewController {
mLockscreenUserManager = notificationLockscreenUserManager;
mEntryManager = notificationEntryManager;
mConversationNotificationManager = conversationNotificationManager;
+ mAuthController = authController;
mView.setBackgroundColor(Color.TRANSPARENT);
OnAttachStateChangeListener onAttachStateChangeListener = new OnAttachStateChangeListener();
@@ -868,7 +872,8 @@ public class NotificationPanelViewController extends PanelViewController {
- mShelfHeight / 2.0f - mDarkIconSize / 2.0f),
clockPreferredY, hasCustomClock(),
hasVisibleNotifications, mInterpolatedDarkAmount, mEmptyDragAmount,
- bypassEnabled, getUnlockedStackScrollerPadding());
+ bypassEnabled, getUnlockedStackScrollerPadding(),
+ mUpdateMonitor.isUdfpsEnrolled());
mClockPositionAlgorithm.run(mClockPositionResult);
mKeyguardStatusViewController.updatePosition(
mClockPositionResult.clockX, mClockPositionResult.clockY, animateClock);
@@ -908,6 +913,13 @@ public class NotificationPanelViewController extends PanelViewController {
mNotificationStackScrollLayoutController.getHeight() - minPadding - shelfSize
- Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding)
- mKeyguardStatusViewController.getLogoutButtonHeight();
+
+ if (mUpdateMonitor.isUdfpsEnrolled()) {
+ availableSpace = mNotificationStackScrollLayoutController.getHeight()
+ - minPadding - shelfSize
+ - (mStatusBar.getDisplayHeight() - mAuthController.getUdfpsRegion().top);
+ }
+
int count = 0;
ExpandableView previousView = null;
for (int i = 0; i < mNotificationStackScrollLayoutController.getChildCount(); i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
index bbabaf429859..a59c87652632 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
@@ -22,7 +22,6 @@ import com.android.systemui.dagger.WMSingleton;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipBoundsHandler;
import com.android.wm.shell.pip.PipBoundsState;
@@ -107,10 +106,9 @@ public abstract class TvPipModule {
PipBoundsHandler pipBoundsHandler,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
Optional<SplitScreen> splitScreenOptional, DisplayController displayController,
- PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer,
- SystemWindows systemWindows) {
+ PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer) {
return new PipTaskOrganizer(context, pipBoundsState, pipBoundsHandler,
null /* menuActivityController */, pipSurfaceTransactionHelper, splitScreenOptional,
- displayController, pipUiEventLogger, shellTaskOrganizer, systemWindows);
+ displayController, pipUiEventLogger, shellTaskOrganizer);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index 1ca04af393ff..0f8fb7bbd0ec 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -131,10 +131,9 @@ public class WMShellModule {
PipMenuActivityController menuActivityController,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
Optional<SplitScreen> splitScreenOptional, DisplayController displayController,
- PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer,
- SystemWindows systemWindows) {
+ PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer) {
return new PipTaskOrganizer(context, pipBoundsState, pipBoundsHandler,
menuActivityController, pipSurfaceTransactionHelper, splitScreenOptional,
- displayController, pipUiEventLogger, shellTaskOrganizer, systemWindows);
+ displayController, pipUiEventLogger, shellTaskOrganizer);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index e6479ddaedb3..d78090a546c4 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -79,6 +79,7 @@ import com.android.internal.widget.ILockSettings;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor.BiometricAuthenticated;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.biometrics.AuthController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -156,6 +157,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
private LiveData<Integer> mRingerModeLiveData;
@Mock
private StatusBarStateController mStatusBarStateController;
+ @Mock
+ private AuthController mAuthController;
// Direct executor
private Executor mBackgroundExecutor = Runnable::run;
private TestableLooper mTestableLooper;
@@ -198,6 +201,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
when(mTelephonyManager.getServiceStateForSubscriber(anyInt()))
.thenReturn(new ServiceState());
when(mLockPatternUtils.getLockSettings()).thenReturn(mLockSettings);
+ when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
mSpiedContext.addMockSystemService(TrustManager.class, mTrustManager);
mSpiedContext.addMockSystemService(FingerprintManager.class, mFingerprintManager);
mSpiedContext.addMockSystemService(BiometricManager.class, mBiometricManager);
@@ -796,7 +800,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
TestableLooper.get(KeyguardUpdateMonitorTest.this).getLooper(),
mBroadcastDispatcher, mDumpManager,
mRingerModeTracker, mBackgroundExecutor,
- mStatusBarStateController, mLockPatternUtils);
+ mStatusBarStateController, mLockPatternUtils,
+ mAuthController);
setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index 0c87f59af822..59262cf3231b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -64,6 +64,8 @@ import com.android.systemui.R.dimen;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.settings.FakeSettings;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
import org.junit.Test;
@@ -84,6 +86,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
private ScreenDecorations mScreenDecorations;
private WindowManager mWindowManager;
private DisplayManager mDisplayManager;
+ private SecureSettings mSecureSettings;
private Handler mMainHandler;
@Mock
private TunerService mTunerService;
@@ -98,6 +101,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
mTestableLooper = TestableLooper.get(this);
mMainHandler = new Handler(mTestableLooper.getLooper());
+ mSecureSettings = new FakeSettings();
mWindowManager = mock(WindowManager.class);
WindowMetrics metrics = mContext.getSystemService(WindowManager.class)
@@ -111,7 +115,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
when(mDisplayManager.getDisplay(anyInt())).thenReturn(display);
mContext.addMockSystemService(DisplayManager.class, mDisplayManager);
- mScreenDecorations = spy(new ScreenDecorations(mContext, mMainHandler,
+ mScreenDecorations = spy(new ScreenDecorations(mContext, mMainHandler, mSecureSettings,
mBroadcastDispatcher, mTunerService, mUserTracker) {
@Override
public void start() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
index c923515fc8cc..a0ae35ffef00 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
@@ -287,6 +287,33 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
assertShowFadingAnimation(FADE_OUT_ALPHA);
}
+ @Test
+ public void showButton_hasAccessibilityWindowTitle() {
+ mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
+
+ ArgumentCaptor<WindowManager.LayoutParams> paramsArgumentCaptor = ArgumentCaptor.forClass(
+ WindowManager.LayoutParams.class);
+ verify(mWindowManager).addView(eq(mSpyImageView), paramsArgumentCaptor.capture());
+ assertEquals(getContext().getResources().getString(
+ com.android.internal.R.string.android_system_label),
+ paramsArgumentCaptor.getValue().accessibilityTitle);
+ }
+
+ @Test
+ public void onLocaleChanged_buttonIsShowing_updateA11yWindowTitle() {
+ final String newA11yWindowTitle = "new a11y window title";
+ mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
+
+ getContext().getOrCreateTestableResources().addOverride(
+ com.android.internal.R.string.android_system_label, newA11yWindowTitle);
+ mMagnificationModeSwitch.onConfigurationChanged(ActivityInfo.CONFIG_LOCALE);
+
+ ArgumentCaptor<WindowManager.LayoutParams> paramsArgumentCaptor = ArgumentCaptor.forClass(
+ WindowManager.LayoutParams.class);
+ verify(mWindowManager).updateViewLayout(eq(mSpyImageView), paramsArgumentCaptor.capture());
+ assertEquals(newA11yWindowTitle, paramsArgumentCaptor.getValue().accessibilityTitle);
+ }
+
private void assertModeUnchanged(int expectedMode) {
final int actualMode = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index f1606c5660ed..a39bc702900e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -41,6 +41,7 @@ import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.os.Handler;
import android.testing.AndroidTestingRunner;
+import android.testing.TestableResources;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -114,8 +115,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
when(mTransaction.remove(any())).thenReturn(mTransaction);
when(mTransaction.setGeometry(any(), any(), any(),
anyInt())).thenReturn(mTransaction);
- mResources = Mockito.spy(mContext.getResources());
- when(mContext.getResources()).thenReturn(mResources);
+ mResources = getContext().getOrCreateTestableResources().getResources();
mWindowMagnificationController = new WindowMagnificationController(mContext,
mHandler, mSfVsyncFrameProvider,
mMirrorWindowControl, mTransaction, mWindowMagnifierCallback);
@@ -222,7 +222,6 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
assertEquals(Surface.ROTATION_90, mWindowMagnificationController.mRotation);
}
-
@Test
public void onDensityChanged_enabled_updateDimensionsAndResetWindowMagnification() {
mInstrumentation.runOnMainSync(() -> {
@@ -310,4 +309,41 @@ public class WindowMagnificationControllerTest extends SysuiTestCase {
verify(mWindowManager).updateViewLayout(eq(mMirrorView), any());
}
+
+ @Test
+ public void enableWindowMagnification_hasA11yWindowTitle() {
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ Float.NaN);
+ });
+
+ ArgumentCaptor<WindowManager.LayoutParams> paramsArgumentCaptor = ArgumentCaptor.forClass(
+ WindowManager.LayoutParams.class);
+ verify(mWindowManager).addView(eq(mMirrorView), paramsArgumentCaptor.capture());
+ assertEquals(getContext().getResources().getString(
+ com.android.internal.R.string.android_system_label),
+ paramsArgumentCaptor.getValue().accessibilityTitle);
+ }
+
+ @Test
+ public void onLocaleChanged_enabled_updateA11yWindowTitle() {
+ final String newA11yWindowTitle = "new a11y window title";
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+ Float.NaN);
+ });
+ final TestableResources testableResources = getContext().getOrCreateTestableResources();
+ testableResources.addOverride(com.android.internal.R.string.android_system_label,
+ newA11yWindowTitle);
+ when(mContext.getResources()).thenReturn(testableResources.getResources());
+
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowMagnificationController.onConfigurationChanged(ActivityInfo.CONFIG_LOCALE);
+ });
+
+ ArgumentCaptor<WindowManager.LayoutParams> paramsArgumentCaptor = ArgumentCaptor.forClass(
+ WindowManager.LayoutParams.class);
+ verify(mWindowManager).updateViewLayout(eq(mMirrorView), paramsArgumentCaptor.capture());
+ assertEquals(newA11yWindowTitle, paramsArgumentCaptor.getValue().accessibilityTitle);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index 0186d7394ecb..42bb005b5144 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -494,8 +494,9 @@ public class AuthControllerTest extends SysuiTestCase {
@Test
public void testOnAodInterrupt() {
final int pos = 10;
- mAuthController.onAodInterrupt(pos, pos);
- verify(mUdfpsController).onAodInterrupt(eq(pos), eq(pos));
+ final float majorMinor = 5f;
+ mAuthController.onAodInterrupt(pos, pos, majorMinor, majorMinor);
+ verify(mUdfpsController).onAodInterrupt(eq(pos), eq(pos), eq(majorMinor), eq(majorMinor));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index a95396cccd66..82ffd46f7164 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -234,10 +234,10 @@ public class UdfpsControllerTest extends SysuiTestCase {
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
mFgExecutor.runAllReady();
// WHEN fingerprint is requested because of AOD interrupt
- mUdfpsController.onAodInterrupt(0, 0);
+ mUdfpsController.onAodInterrupt(0, 0, 2f, 3f);
// THEN the event is passed to the FingerprintManager
verify(mFingerprintManager).onPointerDown(eq(mUdfpsController.mSensorProps.sensorId), eq(0),
- eq(0), anyFloat(), anyFloat());
+ eq(0), eq(3f) /* minor */, eq(2f) /* major */);
// AND the scrim and dot is shown
verify(mUdfpsView).showScrimAndDot();
}
@@ -247,7 +247,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
// GIVEN AOD interrupt
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
mFgExecutor.runAllReady();
- mUdfpsController.onAodInterrupt(0, 0);
+ mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
// WHEN it is cancelled
mUdfpsController.onCancelAodInterrupt();
// THEN the scrim and dot is hidden
@@ -259,7 +259,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
// GIVEN AOD interrupt
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
mFgExecutor.runAllReady();
- mUdfpsController.onAodInterrupt(0, 0);
+ mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
// WHEN it times out
mFgExecutor.advanceClockToNext();
mFgExecutor.runAllReady();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 6d87cc3c3e38..4bbba56395f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -194,10 +194,13 @@ public class DozeTriggersTest extends SysuiTestCase {
public void testOnSensor_Fingerprint() {
final int screenX = 100;
final int screenY = 100;
+ final float minor = 2f;
+ final float major = 3f;
final int reason = DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS;
- mTriggers.onSensor(reason, screenX, screenY, null);
+ float[] rawValues = new float[]{screenX, screenY, minor, major};
+ mTriggers.onSensor(reason, screenX, screenY, rawValues);
verify(mHost).extendPulse(reason);
- verify(mAuthController).onAodInterrupt(eq(screenX), eq(screenY));
+ verify(mAuthController).onAodInterrupt(eq(screenX), eq(screenY), eq(minor), eq(major));
}
private void waitForSensorManager() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 521888658d68..6e216428992f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -50,6 +50,7 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
private static final String TEST_DEVICE_NAME_2 = "test_device_name_2";
private static final String TEST_DEVICE_ID_1 = "test_device_id_1";
private static final String TEST_DEVICE_ID_2 = "test_device_id_2";
+ private static final String TEST_SESSION_NAME = "test_session_name";
// Mock
private MediaOutputController mMediaOutputController = mock(MediaOutputController.class);
@@ -102,6 +103,14 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
}
@Test
+ public void getItemCount_withDynamicGroup_containExtraOneForGroup() {
+ when(mMediaOutputController.getSelectedMediaDevice()).thenReturn(mMediaDevices);
+ when(mMediaOutputController.isZeroMode()).thenReturn(false);
+
+ assertThat(mMediaOutputAdapter.getItemCount()).isEqualTo(mMediaDevices.size() + 1);
+ }
+
+ @Test
public void onBindViewHolder_zeroMode_bindPairNew_verifyView() {
when(mMediaOutputController.isZeroMode()).thenReturn(true);
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 2);
@@ -118,6 +127,45 @@ public class MediaOutputAdapterTest extends SysuiTestCase {
}
@Test
+ public void onBindViewHolder_bindGroup_withSessionName_verifyView() {
+ when(mMediaOutputController.getSelectedMediaDevice()).thenReturn(mMediaDevices);
+ when(mMediaOutputController.isZeroMode()).thenReturn(false);
+ when(mMediaOutputController.getSessionName()).thenReturn(TEST_SESSION_NAME);
+ mMediaOutputAdapter.getItemCount();
+ mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
+
+ assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_SESSION_NAME);
+ }
+
+ @Test
+ public void onBindViewHolder_bindGroup_noSessionName_verifyView() {
+ when(mMediaOutputController.getSelectedMediaDevice()).thenReturn(mMediaDevices);
+ when(mMediaOutputController.isZeroMode()).thenReturn(false);
+ when(mMediaOutputController.getSessionName()).thenReturn(null);
+ mMediaOutputAdapter.getItemCount();
+ mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
+
+ assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mDivider.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
+ assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(mContext.getString(
+ R.string.media_output_dialog_group));
+ }
+
+ @Test
public void onBindViewHolder_bindConnectedDevice_verifyView() {
mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/SecureSettingTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/SecureSettingTest.kt
new file mode 100644
index 000000000000..418fa61f3b06
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/SecureSettingTest.kt
@@ -0,0 +1,153 @@
+/*
+ * 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.systemui.qs
+
+import android.os.Handler
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.settings.FakeSettings
+import com.android.systemui.util.settings.SecureSettings
+import com.google.common.truth.Truth.assertThat
+import junit.framework.Assert.fail
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private typealias Callback = (Int, Boolean) -> Unit
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class SecureSettingTest : SysuiTestCase() {
+
+ companion object {
+ private const val TEST_SETTING = "setting"
+ private const val USER = 0
+ private const val OTHER_USER = 1
+ private val FAIL_CALLBACK: Callback = { _, _ -> fail("Callback should not be called") }
+ }
+
+ private lateinit var testableLooper: TestableLooper
+ private lateinit var setting: SecureSetting
+ private lateinit var secureSettings: SecureSettings
+
+ private lateinit var callback: Callback
+
+ @Before
+ fun setUp() {
+ testableLooper = TestableLooper.get(this)
+ secureSettings = FakeSettings()
+
+ setting = object : SecureSetting(
+ secureSettings,
+ Handler(testableLooper.looper),
+ TEST_SETTING,
+ USER
+ ) {
+ override fun handleValueChanged(value: Int, observedChange: Boolean) {
+ callback(value, observedChange)
+ }
+ }
+
+ // Default empty callback
+ callback = { _, _ -> Unit }
+ }
+
+ @After
+ fun tearDown() {
+ setting.isListening = false
+ }
+
+ @Test
+ fun testNotListeningByDefault() {
+ callback = FAIL_CALLBACK
+
+ assertThat(setting.isListening).isFalse()
+ secureSettings.putIntForUser(TEST_SETTING, 2, USER)
+ testableLooper.processAllMessages()
+ }
+
+ @Test
+ fun testChangedWhenListeningCallsCallback() {
+ var changed = false
+ callback = { _, _ -> changed = true }
+
+ setting.isListening = true
+ secureSettings.putIntForUser(TEST_SETTING, 2, USER)
+ testableLooper.processAllMessages()
+
+ assertThat(changed).isTrue()
+ }
+
+ @Test
+ fun testListensToCorrectSetting() {
+ callback = FAIL_CALLBACK
+
+ setting.isListening = true
+ secureSettings.putIntForUser("other", 2, USER)
+ testableLooper.processAllMessages()
+ }
+
+ @Test
+ fun testGetCorrectValue() {
+ secureSettings.putIntForUser(TEST_SETTING, 2, USER)
+ assertThat(setting.value).isEqualTo(2)
+
+ secureSettings.putIntForUser(TEST_SETTING, 4, USER)
+ assertThat(setting.value).isEqualTo(4)
+ }
+
+ @Test
+ fun testSetValue() {
+ setting.value = 5
+ assertThat(secureSettings.getIntForUser(TEST_SETTING, USER)).isEqualTo(5)
+ }
+
+ @Test
+ fun testChangeUser() {
+ setting.isListening = true
+ setting.setUserId(OTHER_USER)
+
+ setting.isListening = true
+ assertThat(setting.currentUser).isEqualTo(OTHER_USER)
+ }
+
+ @Test
+ fun testDoesntListenInOtherUsers() {
+ callback = FAIL_CALLBACK
+ setting.isListening = true
+
+ secureSettings.putIntForUser(TEST_SETTING, 3, OTHER_USER)
+ testableLooper.processAllMessages()
+ }
+
+ @Test
+ fun testListensToCorrectUserAfterChange() {
+ var changed = false
+ callback = { _, _ -> changed = true }
+
+ setting.isListening = true
+ setting.setUserId(OTHER_USER)
+ secureSettings.putIntForUser(TEST_SETTING, 2, OTHER_USER)
+ testableLooper.processAllMessages()
+
+ assertThat(changed).isTrue()
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
index 2006a75c0e16..bcfc83570345 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
@@ -29,6 +29,8 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.statusbar.policy.BatteryController
+import com.android.systemui.util.settings.FakeSettings
+import com.android.systemui.util.settings.SecureSettings
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
@@ -60,6 +62,7 @@ class BatterySaverTileTest : SysuiTestCase() {
private lateinit var qsLogger: QSLogger
@Mock
private lateinit var batteryController: BatteryController
+ private lateinit var secureSettings: SecureSettings
private lateinit var testableLooper: TestableLooper
private lateinit var tile: BatterySaverTile
@@ -70,6 +73,8 @@ class BatterySaverTileTest : SysuiTestCase() {
`when`(qsHost.userContext).thenReturn(userContext)
`when`(userContext.userId).thenReturn(USER)
+ secureSettings = FakeSettings()
+
tile = BatterySaverTile(
qsHost,
testableLooper.looper,
@@ -78,7 +83,8 @@ class BatterySaverTileTest : SysuiTestCase() {
statusBarStateController,
activityStarter,
qsLogger,
- batteryController)
+ batteryController,
+ secureSettings)
}
@Test
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 b482968fed59..4a2cbccad24d 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
@@ -860,6 +860,33 @@ public class NotificationInfoTest extends SysuiTestCase {
}
@Test
+ public void testHandleCloseControls_persistAutomatic()
+ throws Exception {
+ mNotificationChannel.unlockFields(USER_LOCKED_IMPORTANCE);
+ mNotificationInfo.bindNotification(
+ mMockPackageManager,
+ mMockINotificationManager,
+ mOnUserInteractionCallback,
+ mChannelEditorDialogController,
+ TEST_PACKAGE_NAME,
+ mNotificationChannel,
+ mNotificationChannelSet,
+ mEntry,
+ null,
+ null,
+ mUiEventLogger,
+ true,
+ false,
+ true,
+ true);
+
+ mNotificationInfo.handleCloseControls(true, false);
+ mTestableLooper.processAllMessages();
+ verify(mMockINotificationManager, times(1)).unlockNotificationChannel(
+ anyString(), eq(TEST_UID), any());
+ }
+
+ @Test
public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
throws Exception {
int originalImportance = mNotificationChannel.getImportance();
@@ -1015,16 +1042,17 @@ public class NotificationInfoTest extends SysuiTestCase {
mUiEventLogger,
true,
false,
- false,
- false);
+ true,
+ true);
mNotificationInfo.findViewById(R.id.automatic).performClick();
mNotificationInfo.findViewById(R.id.done).performClick();
mNotificationInfo.handleCloseControls(true, false);
mTestableLooper.processAllMessages();
- assertTrue(mNotificationChannel.hasUserSetImportance());
- assertEquals(mNotificationChannel.getImportance(), IMPORTANCE_DEFAULT);
+ verify(mMockINotificationManager, times(1)).unlockNotificationChannel(
+ anyString(), eq(TEST_UID), any());
+ assertEquals(IMPORTANCE_DEFAULT, mNotificationChannel.getImportance());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index 3ebb77a60e15..82d1f43e5e4e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -22,31 +22,22 @@ import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.isNotNull;
import static org.mockito.ArgumentMatchers.isNull;
-import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
-import android.content.ContentResolver;
import android.content.Context;
-import android.content.ContextWrapper;
import android.hardware.display.ColorDisplayManager;
import android.hardware.display.NightDisplayListener;
import android.os.Handler;
import android.os.UserHandle;
-import android.provider.Settings;
import android.testing.AndroidTestingRunner;
-import android.testing.TestableContentResolver;
-import android.testing.TestableContext;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
@@ -61,6 +52,8 @@ import com.android.systemui.statusbar.policy.CastController;
import com.android.systemui.statusbar.policy.CastController.CastDevice;
import com.android.systemui.statusbar.policy.DataSaverController;
import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.util.settings.FakeSettings;
+import com.android.systemui.util.settings.SecureSettings;
import org.junit.After;
import org.junit.Before;
@@ -100,10 +93,12 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Mock private Context mUserContext;
private AutoTileManager mAutoTileManager;
+ private SecureSettings mSecureSettings;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
+ mSecureSettings = new FakeSettings();
mContext.getOrCreateTestableResources().addOverride(
R.array.config_quickSettingsAutoAdd,
@@ -119,7 +114,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
when(mQsTileHost.getUserContext()).thenReturn(mUserContext);
when(mUserContext.getUser()).thenReturn(UserHandle.of(USER));
- mAutoTileManager = createAutoTileManager(new MyContextWrapper(mContext));
+ mAutoTileManager = createAutoTileManager(mContext);
mAutoTileManager.init();
}
@@ -138,6 +133,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
CastController castController) {
return new AutoTileManager(context, autoAddTrackerBuilder, mQsTileHost,
Handler.createAsync(TestableLooper.get(this).getLooper()),
+ mSecureSettings,
hotspotController,
dataSaverController,
managedProfileController,
@@ -342,7 +338,6 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Test
public void testSettingTileAdded_onChanged() {
changeValue(TEST_SETTING, 1);
- waitForIdleSync();
verify(mAutoAddTracker).setTileAdded(TEST_SPEC);
verify(mQsTileHost).addTile(TEST_SPEC);
}
@@ -350,7 +345,6 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Test
public void testSettingTileAddedComponentAtEnd_onChanged() {
changeValue(TEST_SETTING_COMPONENT, 1);
- waitForIdleSync();
verify(mAutoAddTracker).setTileAdded(TEST_CUSTOM_SPEC);
verify(mQsTileHost).addTile(ComponentName.unflattenFromString(TEST_COMPONENT)
, /* end */ true);
@@ -359,10 +353,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Test
public void testSettingTileAdded_onlyOnce() {
changeValue(TEST_SETTING, 1);
- waitForIdleSync();
- TestableLooper.get(this).processAllMessages();
changeValue(TEST_SETTING, 2);
- waitForIdleSync();
verify(mAutoAddTracker).setTileAdded(TEST_SPEC);
verify(mQsTileHost).addTile(TEST_SPEC);
}
@@ -370,7 +361,6 @@ public class AutoTileManagerTest extends SysuiTestCase {
@Test
public void testSettingTileNotAdded_onChangedTo0() {
changeValue(TEST_SETTING, 0);
- waitForIdleSync();
verify(mAutoAddTracker, never()).setTileAdded(TEST_SPEC);
verify(mQsTileHost, never()).addTile(TEST_SPEC);
}
@@ -380,7 +370,6 @@ public class AutoTileManagerTest extends SysuiTestCase {
when(mAutoAddTracker.isAdded(TEST_SPEC)).thenReturn(true);
changeValue(TEST_SETTING, 1);
- waitForIdleSync();
verify(mAutoAddTracker, never()).setTileAdded(TEST_SPEC);
verify(mQsTileHost, never()).addTile(TEST_SPEC);
}
@@ -401,28 +390,7 @@ public class AutoTileManagerTest extends SysuiTestCase {
// Will only notify if it's listening
private void changeValue(String key, int value) {
- SecureSetting s = mAutoTileManager.getSecureSettingForKey(key);
- Settings.Secure.putInt(mContext.getContentResolver(), key, value);
- if (s != null && s.isListening()) {
- s.onChange(false);
- }
- }
-
- class MyContextWrapper extends ContextWrapper {
-
- private TestableContentResolver mSpiedTCR;
-
- MyContextWrapper(TestableContext context) {
- super(context);
- mSpiedTCR = spy(context.getContentResolver());
- doNothing().when(mSpiedTCR).registerContentObserver(any(), anyBoolean(), any(),
- anyInt());
- doNothing().when(mSpiedTCR).unregisterContentObserver(any());
- }
-
- @Override
- public ContentResolver getContentResolver() {
- return mSpiedTCR;
- }
+ mSecureSettings.putIntForUser(key, value, USER);
+ TestableLooper.get(this).processAllMessages();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index 2042faba2b3a..83ef87a1066c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -384,7 +384,7 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight,
mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, mPreferredClockY,
mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG, false /* bypassEnabled */,
- 0 /* unlockedStackScrollerPadding */);
+ 0 /* unlockedStackScrollerPadding */, false /* udfpsEnrolled */);
mClockPositionAlgorithm.run(mClockPosition);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java
index 06d0331543da..aca34242e5fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LockscreenIconControllerTest.java
@@ -84,7 +84,6 @@ public class LockscreenIconControllerTest extends SysuiTestCase {
private LockscreenLockIconController mLockIconController;
private OnAttachStateChangeListener mOnAttachStateChangeListener;
-
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index cb56f1fbc054..e1f8596c2802 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -21,6 +21,7 @@ import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
@@ -58,6 +59,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.dagger.KeyguardStatusViewComponent;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.biometrics.AuthController;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.media.MediaHierarchyManager;
@@ -194,6 +196,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
private KeyguardStatusViewController mKeyguardStatusViewController;
@Mock
private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController;
+ @Mock
+ private AuthController mAuthController;
private NotificationPanelViewController mNotificationPanelViewController;
private View.AccessibilityDelegate mAccessibiltyDelegate;
@@ -201,6 +205,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+ when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
when(mHeadsUpCallback.getContext()).thenReturn(mContext);
when(mView.getResources()).thenReturn(mResources);
when(mResources.getConfiguration()).thenReturn(mConfiguration);
@@ -267,7 +272,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mNotificationStackScrollLayoutController,
mKeyguardStatusViewComponentFactory,
mGroupManager,
- mNotificationAreaController);
+ mNotificationAreaController,
+ mAuthController);
mNotificationPanelViewController.initDependencies(
mStatusBar,
mNotificationShelfController);
diff --git a/packages/VpnDialogs/AndroidManifest.xml b/packages/VpnDialogs/AndroidManifest.xml
index 374bd28a173c..ca4b5d4170c7 100644
--- a/packages/VpnDialogs/AndroidManifest.xml
+++ b/packages/VpnDialogs/AndroidManifest.xml
@@ -23,6 +23,9 @@
<uses-permission android:name="android.permission.CONTROL_ALWAYS_ON_VPN" />
<uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"/>
+ <!-- Query all packages on device on R+ -->
+ <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+
<application android:label="VpnDialogs"
android:allowBackup="false">
diff --git a/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-bn/strings.xml b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-bn/strings.xml
new file mode 100644
index 000000000000..3e9c962f8946
--- /dev/null
+++ b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-bn/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright (C) 2020 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="display_cutout_emulation_overlay" msgid="7305489596221077240">"পাঞ্চ হোল কাট-আউট"</string>
+</resources>
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index ad85784ca066..a1ad72c47784 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -84,7 +84,6 @@ import com.android.internal.util.Preconditions;
import com.android.internal.util.SyncResultReceiver;
import com.android.server.FgThread;
import com.android.server.LocalServices;
-import com.android.server.SystemService.TargetUser;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.infra.AbstractMasterSystemService;
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
@@ -170,7 +169,7 @@ public final class AutofillManagerService
// beneath it is brought back to top. Ideally, we should just hide the UI and
// bring it back when the activity resumes.
synchronized (mLock) {
- visitServicesLocked((s) -> s.destroyFinishedSessionsLocked());
+ visitServicesLocked((s) -> s.forceRemoveFinishedSessionsLocked());
}
mUi.hideAll(null);
}
@@ -386,18 +385,18 @@ public final class AutofillManagerService
}
// Called by Shell command.
- void destroySessions(@UserIdInt int userId, IResultReceiver receiver) {
- Slog.i(TAG, "destroySessions() for userId " + userId);
+ void removeAllSessions(@UserIdInt int userId, IResultReceiver receiver) {
+ Slog.i(TAG, "removeAllSessions() for userId " + userId);
enforceCallingPermissionForManagement();
synchronized (mLock) {
if (userId != UserHandle.USER_ALL) {
AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
if (service != null) {
- service.destroySessionsLocked();
+ service.forceRemoveAllSessionsLocked();
}
} else {
- visitServicesLocked((s) -> s.destroySessionsLocked());
+ visitServicesLocked((s) -> s.forceRemoveAllSessionsLocked());
}
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 864ead1485b5..32126987376a 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -215,14 +215,14 @@ final class AutofillManagerServiceImpl
@GuardedBy("mLock")
@Override // from PerUserSystemService
protected boolean updateLocked(boolean disabled) {
- destroySessionsLocked();
+ forceRemoveAllSessionsLocked();
final boolean enabledChanged = super.updateLocked(disabled);
if (enabledChanged) {
if (!isEnabledLocked()) {
final int sessionCount = mSessions.size();
for (int i = sessionCount - 1; i >= 0; i--) {
final Session session = mSessions.valueAt(i);
- session.removeSelfLocked();
+ session.removeFromServiceLocked();
}
}
sendStateToClients(/* resetClient= */ false);
@@ -442,7 +442,7 @@ final class AutofillManagerServiceImpl
if (sVerbose) Slog.v(TAG, "finishSessionLocked(): session finished on save? " + finished);
if (finished) {
- session.removeSelfLocked();
+ session.removeFromServiceLocked();
}
}
@@ -457,7 +457,7 @@ final class AutofillManagerServiceImpl
Slog.w(TAG, "cancelSessionLocked(): no session for " + sessionId + "(" + uid + ")");
return;
}
- session.removeSelfLocked();
+ session.removeFromServiceLocked();
}
@GuardedBy("mLock")
@@ -483,7 +483,7 @@ final class AutofillManagerServiceImpl
componentName.getPackageName());
Settings.Secure.putStringForUser(getContext().getContentResolver(),
Settings.Secure.AUTOFILL_SERVICE, null, mUserId);
- destroySessionsLocked();
+ forceRemoveAllSessionsLocked();
} else {
Slog.w(TAG, "disableOwnedServices(): ignored because current service ("
+ serviceInfo + ") does not match Settings (" + autoFillService + ")");
@@ -1107,35 +1107,41 @@ final class AutofillManagerServiceImpl
}
@GuardedBy("mLock")
- void destroySessionsLocked() {
- if (mSessions.size() == 0) {
+ void forceRemoveAllSessionsLocked() {
+ final int sessionCount = mSessions.size();
+ if (sessionCount == 0) {
mUi.destroyAll(null, null, false);
return;
}
- while (mSessions.size() > 0) {
- mSessions.valueAt(0).forceRemoveSelfLocked();
+
+ for (int i = sessionCount - 1; i >= 0; i--) {
+ mSessions.valueAt(i).forceRemoveFromServiceLocked();
}
}
@GuardedBy("mLock")
- void destroySessionsForAugmentedAutofillOnlyLocked() {
+ void forceRemoveForAugmentedOnlySessionsLocked() {
final int sessionCount = mSessions.size();
for (int i = sessionCount - 1; i >= 0; i--) {
- mSessions.valueAt(i).forceRemoveSelfIfForAugmentedAutofillOnlyLocked();
+ mSessions.valueAt(i).forceRemoveFromServiceIfForAugmentedOnlyLocked();
}
}
+ /**
+ * This method is called exclusively in response to {@code Intent.ACTION_CLOSE_SYSTEM_DIALOGS}.
+ * The method removes all sessions that are finished but showing SaveUI due to how SaveUI is
+ * managed (see b/64940307). Otherwise it will remove any augmented autofill generated windows.
+ */
// TODO(b/64940307): remove this method if SaveUI is refactored to be attached on activities
@GuardedBy("mLock")
- void destroyFinishedSessionsLocked() {
+ void forceRemoveFinishedSessionsLocked() {
final int sessionCount = mSessions.size();
for (int i = sessionCount - 1; i >= 0; i--) {
final Session session = mSessions.valueAt(i);
if (session.isSavingLocked()) {
if (sDebug) Slog.d(TAG, "destroyFinishedSessionsLocked(): " + session.id);
- session.forceRemoveSelfLocked();
- }
- else {
+ session.forceRemoveFromServiceLocked();
+ } else {
session.destroyAugmentedAutofillWindowsLocked();
}
}
@@ -1261,7 +1267,7 @@ final class AutofillManagerServiceImpl
Slog.v(TAG, "updateRemoteAugmentedAutofillService(): "
+ "destroying old remote service");
}
- destroySessionsForAugmentedAutofillOnlyLocked();
+ forceRemoveForAugmentedOnlySessionsLocked();
mRemoteAugmentedAutofillService.unbind();
mRemoteAugmentedAutofillService = null;
mRemoteAugmentedAutofillServiceInfo = null;
@@ -1663,7 +1669,7 @@ final class AutofillManagerServiceImpl
Slog.i(TAG, "Prune session " + sessionToRemove.id + " ("
+ sessionToRemove.getActivityTokenLocked() + ")");
}
- sessionToRemove.removeSelfLocked();
+ sessionToRemove.removeFromServiceLocked();
}
}
}
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
index bbe37a5df4f4..68e6290c987a 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java
@@ -355,7 +355,7 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand {
latch.countDown();
}
};
- return requestSessionCommon(pw, latch, () -> mService.destroySessions(userId, receiver));
+ return requestSessionCommon(pw, latch, () -> mService.removeAllSessions(userId, receiver));
}
private int requestList(PrintWriter pw) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 0302b2251f10..b48d71a51ce3 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -227,8 +227,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
private boolean mHasCallback;
/**
- * Extras sent by service on {@code onFillRequest()} calls; the first non-null extra is saved
- * and used on subsequent {@code onFillRequest()} and {@code onSaveRequest()} calls.
+ * Extras sent by service on {@code onFillRequest()} calls; the most recent non-null extra is
+ * saved and used on subsequent {@code onFillRequest()} and {@code onSaveRequest()} calls.
*/
@GuardedBy("mLock")
private Bundle mClientState;
@@ -1086,7 +1086,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if (showMessage) {
getUiForShowing().showError(message, this);
}
- removeSelf();
+ removeFromService();
}
// FillServiceCallbacks
@@ -1111,7 +1111,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
// Nothing left to do...
- removeSelf();
+ removeFromService();
}
// FillServiceCallbacks
@@ -1147,7 +1147,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
if (showMessage) {
getUiForShowing().showError(message, this);
}
- removeSelf();
+ removeFromService();
}
/**
@@ -1179,7 +1179,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
@Override
public void onServiceDied(@NonNull RemoteFillService service) {
Slog.w(TAG, "removing session because service died");
- forceRemoveSelfLocked();
+ forceRemoveFromServiceLocked();
}
// AutoFillUiCallback
@@ -1199,7 +1199,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
fillInIntent = createAuthFillInIntentLocked(requestId, extras);
if (fillInIntent == null) {
- forceRemoveSelfLocked();
+ forceRemoveFromServiceLocked();
return;
}
}
@@ -1255,7 +1255,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
}
mHandler.sendMessage(obtainMessage(
- Session::removeSelf, this));
+ Session::removeFromService, this));
}
// AutoFillUiCallback
@@ -1327,7 +1327,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
@Override
public void cancelSession() {
synchronized (mLock) {
- removeSelfLocked();
+ removeFromServiceLocked();
}
}
@@ -1347,7 +1347,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
return;
}
if (intent == null) {
- removeSelfLocked();
+ removeFromServiceLocked();
}
}
mHandler.sendMessage(obtainMessage(
@@ -1401,13 +1401,13 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
// Typically happens when app explicitly called cancel() while the service was showing
// the auth UI.
Slog.w(TAG, "setAuthenticationResultLocked(" + authenticationId + "): no responses");
- removeSelf();
+ removeFromService();
return;
}
final FillResponse authenticatedResponse = mResponses.get(requestId);
if (authenticatedResponse == null || data == null) {
Slog.w(TAG, "no authenticated response");
- removeSelf();
+ removeFromService();
return;
}
@@ -1418,7 +1418,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
final Dataset dataset = authenticatedResponse.getDatasets().get(datasetIdx);
if (dataset == null) {
Slog.w(TAG, "no dataset with index " + datasetIdx + " on fill response");
- removeSelf();
+ removeFromService();
return;
}
}
@@ -1504,7 +1504,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
Slog.d(TAG, "Rejecting empty/invalid auth result");
}
mService.resetLastAugmentedAutofillResponse();
- removeSelfLocked();
+ removeFromServiceLocked();
return;
}
@@ -2715,7 +2715,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
return;
}
if (sDebug) Slog.d(TAG, "Finishing session because URL bar changed");
- forceRemoveSelfLocked(AutofillManager.STATE_UNKNOWN_COMPAT_MODE);
+ forceRemoveFromServiceLocked(AutofillManager.STATE_UNKNOWN_COMPAT_MODE);
return;
}
if (!Objects.equals(value, viewState.getCurrentValue())) {
@@ -3226,7 +3226,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
// Nothing to be done, but need to notify client.
notifyUnavailableToClient(AutofillManager.STATE_FINISHED, autofillableIds);
- removeSelf();
+ removeFromService();
} else {
if ((flags & FLAG_PASSWORD_INPUT_TYPE) != 0) {
if (sVerbose) {
@@ -3393,20 +3393,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
@GuardedBy("mLock")
- private void logAugmentedAutofillRequestLocked(int mode,
- ComponentName augmentedRemoteServiceName, AutofillId focusedId, boolean isWhitelisted,
- Boolean isInline) {
- final String historyItem =
- "aug:id=" + id + " u=" + uid + " m=" + mode
- + " a=" + ComponentName.flattenToShortString(mComponentName)
- + " f=" + focusedId
- + " s=" + augmentedRemoteServiceName
- + " w=" + isWhitelisted
- + " i=" + isInline;
- mService.getMaster().logRequestLocked(historyItem);
- }
-
- @GuardedBy("mLock")
private void cancelAugmentedAutofillLocked() {
final RemoteAugmentedAutofillService remoteService = mService
.getRemoteAugmentedAutofillServiceLocked();
@@ -3574,7 +3560,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
setViewStatesLocked(null, dataset, ViewState.STATE_WAITING_DATASET_AUTH, false);
final Intent fillInIntent = createAuthFillInIntentLocked(requestId, mClientState);
if (fillInIntent == null) {
- forceRemoveSelfLocked();
+ forceRemoveFromServiceLocked();
return;
}
final int authenticationId = AutofillManager.makeAuthenticationId(requestId,
@@ -3923,12 +3909,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
/**
- * Cleans up this session.
+ * Destroy this session and perform any clean up work.
*
* <p>Typically called in 2 scenarios:
*
* <ul>
- * <li>When the session naturally finishes (i.e., from {@link #removeSelfLocked()}.
+ * <li>When the session naturally finishes (i.e., from {@link #removeFromServiceLocked()}.
* <li>When the service hosting the session is finished (for example, because the user
* disabled it).
* </ul>
@@ -3990,32 +3976,32 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
/**
- * Cleans up this session and remove it from the service always, even if it does have a pending
+ * Destroy this session and remove it from the service always, even if it does have a pending
* Save UI.
*/
@GuardedBy("mLock")
- void forceRemoveSelfLocked() {
- forceRemoveSelfLocked(AutofillManager.STATE_UNKNOWN);
+ void forceRemoveFromServiceLocked() {
+ forceRemoveFromServiceLocked(AutofillManager.STATE_UNKNOWN);
}
@GuardedBy("mLock")
- void forceRemoveSelfIfForAugmentedAutofillOnlyLocked() {
+ void forceRemoveFromServiceIfForAugmentedOnlyLocked() {
if (sVerbose) {
- Slog.v(TAG, "forceRemoveSelfIfForAugmentedAutofillOnly(" + this.id + "): "
+ Slog.v(TAG, "forceRemoveFromServiceIfForAugmentedOnlyLocked(" + this.id + "): "
+ mForAugmentedAutofillOnly);
}
if (!mForAugmentedAutofillOnly) return;
- forceRemoveSelfLocked();
+ forceRemoveFromServiceLocked();
}
@GuardedBy("mLock")
- void forceRemoveSelfLocked(int clientState) {
- if (sVerbose) Slog.v(TAG, "forceRemoveSelfLocked(): " + mPendingSaveUi);
+ void forceRemoveFromServiceLocked(int clientState) {
+ if (sVerbose) Slog.v(TAG, "forceRemoveFromServiceLocked(): " + mPendingSaveUi);
final boolean isPendingSaveUi = isSaveUiPendingLocked();
mPendingSaveUi = null;
- removeSelfLocked();
+ removeFromServiceLocked();
mUi.destroyAll(mPendingSaveUi, this, false);
if (!isPendingSaveUi) {
try {
@@ -4036,28 +4022,28 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
}
/**
- * Thread-safe version of {@link #removeSelfLocked()}.
+ * Thread-safe version of {@link #removeFromServiceLocked()}.
*/
- private void removeSelf() {
+ private void removeFromService() {
synchronized (mLock) {
- removeSelfLocked();
+ removeFromServiceLocked();
}
}
/**
- * Cleans up this session and remove it from the service, but but only if it does not have a
+ * Destroy this session and remove it from the service, but but only if it does not have a
* pending Save UI.
*/
@GuardedBy("mLock")
- void removeSelfLocked() {
- if (sVerbose) Slog.v(TAG, "removeSelfLocked(" + this.id + "): " + mPendingSaveUi);
+ void removeFromServiceLocked() {
+ if (sVerbose) Slog.v(TAG, "removeFromServiceLocked(" + this.id + "): " + mPendingSaveUi);
if (mDestroyed) {
- Slog.w(TAG, "Call to Session#removeSelfLocked() rejected - session: "
+ Slog.w(TAG, "Call to Session#removeFromServiceLocked() rejected - session: "
+ id + " destroyed");
return;
}
if (isSaveUiPendingLocked()) {
- Slog.i(TAG, "removeSelfLocked() ignored, waiting for pending save ui");
+ Slog.i(TAG, "removeFromServiceLocked() ignored, waiting for pending save ui");
return;
}
@@ -4139,6 +4125,20 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
requestLog.addTaggedData(tag, value);
}
+ @GuardedBy("mLock")
+ private void logAugmentedAutofillRequestLocked(int mode,
+ ComponentName augmentedRemoteServiceName, AutofillId focusedId, boolean isWhitelisted,
+ Boolean isInline) {
+ final String historyItem =
+ "aug:id=" + id + " u=" + uid + " m=" + mode
+ + " a=" + ComponentName.flattenToShortString(mComponentName)
+ + " f=" + focusedId
+ + " s=" + augmentedRemoteServiceName
+ + " w=" + isWhitelisted
+ + " i=" + isInline;
+ mService.getMaster().logRequestLocked(historyItem);
+ }
+
private void wtf(@Nullable Exception e, String fmt, Object...args) {
final String message = String.format(fmt, args);
synchronized (mLock) {
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 75bbec67c66e..ac6ed440093d 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -32,6 +32,7 @@ import android.app.backup.IBackupObserver;
import android.app.backup.IFullBackupRestoreObserver;
import android.app.backup.IRestoreSession;
import android.app.backup.ISelectBackupTransportCallback;
+import android.app.compat.CompatChanges;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
@@ -61,7 +62,6 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
-import com.android.server.SystemService.TargetUser;
import com.android.server.backup.utils.RandomAccessFileUtils;
import java.io.File;
@@ -509,6 +509,12 @@ public class BackupManagerService extends IBackupManager.Stub {
*/
@Override
public boolean isBackupServiceActive(int userId) {
+ int callingUid = Binder.getCallingUid();
+ if (CompatChanges.isChangeEnabled(
+ BackupManager.IS_BACKUP_SERVICE_ACTIVE_ENFORCE_PERMISSION_IN_SERVICE, callingUid)) {
+ mContext.enforceCallingPermission(android.Manifest.permission.BACKUP,
+ "isBackupServiceActive");
+ }
synchronized (mStateLock) {
return !mGlobalDisable && isBackupActivatedForUser(userId);
}
diff --git a/services/core/java/com/android/server/RescueParty.java b/services/core/java/com/android/server/RescueParty.java
index 9fc8f0b5a3c3..ef6dab5a45fb 100644
--- a/services/core/java/com/android/server/RescueParty.java
+++ b/services/core/java/com/android/server/RescueParty.java
@@ -56,6 +56,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -100,6 +101,10 @@ public class RescueParty {
private static final String PROP_VIRTUAL_DEVICE = "ro.hardware.virtual_device";
private static final String PROP_DEVICE_CONFIG_DISABLE_FLAG =
"persist.device_config.configuration.disable_rescue_party";
+ private static final String PROP_DISABLE_FACTORY_RESET_FLAG =
+ "persist.device_config.configuration.disable_rescue_party_factory_reset";
+ // The DeviceConfig namespace containing all RescueParty switches.
+ private static final String NAMESPACE_CONFIGURATION = "configuration";
private static final int PERSISTENT_MASK = ApplicationInfo.FLAG_PERSISTENT
| ApplicationInfo.FLAG_SYSTEM;
@@ -215,6 +220,10 @@ public class RescueParty {
if (SettingsToPropertiesMapper.isNativeFlagsResetPerformed()) {
String[] resetNativeCategories = SettingsToPropertiesMapper.getResetNativeCategories();
for (int i = 0; i < resetNativeCategories.length; i++) {
+ // Don't let RescueParty reset the namespace for RescueParty switches.
+ if (NAMESPACE_CONFIGURATION.equals(resetNativeCategories[i])) {
+ continue;
+ }
DeviceConfig.resetToDefaults(Settings.RESET_MODE_TRUSTED_DEFAULTS,
resetNativeCategories[i]);
}
@@ -225,8 +234,10 @@ public class RescueParty {
* Get the next rescue level. This indicates the next level of mitigation that may be taken.
*/
private static int getNextRescueLevel() {
+ int maxRescueLevel = SystemProperties.getBoolean(PROP_DISABLE_FACTORY_RESET_FLAG, false)
+ ? LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS : LEVEL_FACTORY_RESET;
return MathUtils.constrain(SystemProperties.getInt(PROP_RESCUE_LEVEL, LEVEL_NONE) + 1,
- LEVEL_NONE, LEVEL_FACTORY_RESET);
+ LEVEL_NONE, maxRescueLevel);
}
/**
@@ -349,12 +360,30 @@ public class RescueParty {
private static void resetDeviceConfig(Context context, int resetMode,
@Nullable String failedPackage) {
if (!shouldPerformScopedResets() || failedPackage == null) {
- DeviceConfig.resetToDefaults(resetMode, /*namespace=*/ null);
+ resetAllAffectedNamespaces(context, resetMode);
} else {
performScopedReset(context, resetMode, failedPackage);
}
}
+ private static void resetAllAffectedNamespaces(Context context, int resetMode) {
+ RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context);
+ Set<String> allAffectedNamespaces = rescuePartyObserver.getAllAffectedNamespaceSet();
+
+ Slog.w(TAG,
+ "Performing reset for all affected namespaces: "
+ + Arrays.toString(allAffectedNamespaces.toArray()));
+ Iterator<String> it = allAffectedNamespaces.iterator();
+ while (it.hasNext()) {
+ String namespace = it.next();
+ // Don't let RescueParty reset the namespace for RescueParty switches.
+ if (NAMESPACE_CONFIGURATION.equals(namespace)) {
+ continue;
+ }
+ DeviceConfig.resetToDefaults(resetMode, namespace);
+ }
+ }
+
private static boolean shouldPerformScopedResets() {
int rescueLevel = MathUtils.constrain(
SystemProperties.getInt(PROP_RESCUE_LEVEL, LEVEL_NONE),
@@ -367,16 +396,21 @@ public class RescueParty {
RescuePartyObserver rescuePartyObserver = RescuePartyObserver.getInstance(context);
Set<String> affectedNamespaces = rescuePartyObserver.getAffectedNamespaceSet(
failedPackage);
- if (affectedNamespaces == null) {
- DeviceConfig.resetToDefaults(resetMode, /*namespace=*/ null);
- } else {
+ // If we can't find namespaces affected for current package,
+ // skip this round of reset.
+ if (affectedNamespaces != null) {
Slog.w(TAG,
"Performing scoped reset for package: " + failedPackage
+ ", affected namespaces: "
+ Arrays.toString(affectedNamespaces.toArray()));
Iterator<String> it = affectedNamespaces.iterator();
while (it.hasNext()) {
- DeviceConfig.resetToDefaults(resetMode, it.next());
+ String namespace = it.next();
+ // Don't let RescueParty reset the namespace for RescueParty switches.
+ if (NAMESPACE_CONFIGURATION.equals(namespace)) {
+ continue;
+ }
+ DeviceConfig.resetToDefaults(resetMode, namespace);
}
}
}
@@ -514,6 +548,10 @@ public class RescueParty {
return mCallingPackageNamespaceSetMap.get(failedPackage);
}
+ private synchronized Set<String> getAllAffectedNamespaceSet() {
+ return new HashSet<String>(mNamespaceCallingPackageSetMap.keySet());
+ }
+
private synchronized Set<String> getCallingPackagesSet(String namespace) {
return mNamespaceCallingPackageSetMap.get(namespace);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 112814c69d9b..081493752e31 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4890,6 +4890,15 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
+ public boolean isIntentSenderImmutable(IIntentSender pendingResult) {
+ if (pendingResult instanceof PendingIntentRecord) {
+ final PendingIntentRecord res = (PendingIntentRecord) pendingResult;
+ return (res.key.flags & PendingIntent.FLAG_IMMUTABLE) != 0;
+ }
+ return false;
+ }
+
+ @Override
public boolean isIntentSenderAnActivity(IIntentSender pendingResult) {
if (!(pendingResult instanceof PendingIntentRecord)) {
return false;
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index 5e59a35fc4ee..cace260c3c26 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -247,6 +247,9 @@ public class AppProfiler {
private int mMemWatchDumpUid;
private boolean mMemWatchIsUserInitiated;
+ boolean mHasHomeProcess;
+ boolean mHasPreviousProcess;
+
/**
* Used to collect per-process CPU use for ANRs, battery stats, etc.
* Must acquire this object's lock when accessing it.
@@ -961,8 +964,8 @@ public class AppProfiler {
}
int factor = numTrimming / 3;
int minFactor = 2;
- if (mService.mAtmInternal.getHomeProcess() != null) minFactor++;
- if (mService.mAtmInternal.getPreviousProcess() != null) minFactor++;
+ if (mHasHomeProcess) minFactor++;
+ if (mHasPreviousProcess) minFactor++;
if (factor < minFactor) factor = minFactor;
int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
for (int i = 0; i < numOfLru; i++) {
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 9d49236191a9..01d0a6dec81a 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -500,6 +500,7 @@ public final class OomAdjuster {
final ProcessRecord topApp = mService.getTopAppLocked();
// Clear any pending ones because we are doing a full update now.
mPendingProcessSet.clear();
+ mService.mAppProfiler.mHasPreviousProcess = mService.mAppProfiler.mHasHomeProcess = false;
updateOomAdjLockedInner(oomAdjReason, topApp , null, null, true, true);
}
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index ccdd6a746239..463ba6d3d5ee 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1875,16 +1875,24 @@ class ProcessRecord implements WindowProcessListener {
boolean getCachedIsHomeProcess() {
if (mCachedIsHomeProcess == VALUE_INVALID) {
- mCachedIsHomeProcess = getWindowProcessController().isHomeProcess()
- ? VALUE_TRUE : VALUE_FALSE;
+ if (getWindowProcessController().isHomeProcess()) {
+ mCachedIsHomeProcess = VALUE_TRUE;
+ mService.mAppProfiler.mHasHomeProcess = true;
+ } else {
+ mCachedIsHomeProcess = VALUE_FALSE;
+ }
}
return mCachedIsHomeProcess == VALUE_TRUE;
}
boolean getCachedIsPreviousProcess() {
if (mCachedIsPreviousProcess == VALUE_INVALID) {
- mCachedIsPreviousProcess = getWindowProcessController().isPreviousProcess()
- ? VALUE_TRUE : VALUE_FALSE;
+ if (getWindowProcessController().isPreviousProcess()) {
+ mCachedIsPreviousProcess = VALUE_TRUE;
+ mService.mAppProfiler.mHasPreviousProcess = true;
+ } else {
+ mCachedIsPreviousProcess = VALUE_FALSE;
+ }
}
return mCachedIsPreviousProcess == VALUE_TRUE;
}
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index 60e59e389cf0..28afcbbb2a86 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -85,6 +85,7 @@ public class SettingsToPropertiesMapper {
DeviceConfig.NAMESPACE_INTELLIGENCE_CONTENT_SUGGESTIONS,
DeviceConfig.NAMESPACE_MEDIA_NATIVE,
DeviceConfig.NAMESPACE_NETD_NATIVE,
+ DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT,
DeviceConfig.NAMESPACE_RUNTIME_NATIVE,
DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT,
DeviceConfig.NAMESPACE_STORAGE_NATIVE_BOOT,
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 5379f3218a6e..2b2d9b55c46e 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -94,6 +94,7 @@ import android.app.AsyncNotedAppOp;
import android.app.RuntimeAppOpAccessMessage;
import android.app.SyncNotedAppOp;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -3015,6 +3016,25 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
+ private boolean isTrustedVoiceServiceProxy(String packageName, int code) {
+ if (code != OP_RECORD_AUDIO) {
+ return false;
+ }
+ final String voiceRecognitionComponent = Settings.Secure.getString(
+ mContext.getContentResolver(), Settings.Secure.VOICE_RECOGNITION_SERVICE);
+ final String voiceInteractionComponent = Settings.Secure.getString(
+ mContext.getContentResolver(), Settings.Secure.VOICE_INTERACTION_SERVICE);
+
+ final String voiceRecognitionServicePackageName =
+ voiceRecognitionComponent != null ? ComponentName.unflattenFromString(
+ voiceRecognitionComponent).getPackageName() : "";
+ final String voiceInteractionServicePackageName =
+ voiceInteractionComponent != null ? ComponentName.unflattenFromString(
+ voiceInteractionComponent).getPackageName() : "";
+ return Objects.equals(packageName, voiceRecognitionServicePackageName) && Objects.equals(
+ voiceRecognitionServicePackageName, voiceInteractionServicePackageName);
+ }
+
@Override
public int noteProxyOperation(int code, int proxiedUid, String proxiedPackageName,
String proxiedAttributionTag, int proxyUid, String proxyPackageName,
@@ -3030,9 +3050,12 @@ public class AppOpsService extends IAppOpsService.Stub {
return AppOpsManager.MODE_IGNORED;
}
+ // This is a workaround for R QPR, new API change is not allowed. We only allow the current
+ // voice recognizer is also the voice interactor to noteproxy op.
+ final boolean isTrustVoiceServiceProxy = isTrustedVoiceServiceProxy(proxyPackageName, code);
final boolean isProxyTrusted = mContext.checkPermission(
Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
- == PackageManager.PERMISSION_GRANTED;
+ == PackageManager.PERMISSION_GRANTED || isTrustVoiceServiceProxy;
final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
@@ -3494,9 +3517,12 @@ public class AppOpsService extends IAppOpsService.Stub {
return AppOpsManager.MODE_IGNORED;
}
+ // This is a workaround for R QPR, new API change is not allowed. We only allow the current
+ // voice recognizer is also the voice interactor to noteproxy op.
+ final boolean isTrustVoiceServiceProxy = isTrustedVoiceServiceProxy(proxyPackageName, code);
final boolean isProxyTrusted = mContext.checkPermission(
Manifest.permission.UPDATE_APP_OPS_STATS, -1, proxyUid)
- == PackageManager.PERMISSION_GRANTED;
+ == PackageManager.PERMISSION_GRANTED || isTrustVoiceServiceProxy;
final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY
: AppOpsManager.OP_FLAG_UNTRUSTED_PROXY;
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index cfc58a57c35f..52fc93f101ab 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4306,7 +4306,7 @@ public class AudioService extends IAudioService.Stub
/** @see AudioManager#playSoundEffect(int, float) */
public void playSoundEffectVolume(int effectType, float volume) {
// do not try to play the sound effect if the system stream is muted
- if (isStreamMutedByRingerOrZenMode(STREAM_SYSTEM)) {
+ if (isStreamMute(STREAM_SYSTEM)) {
return;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
index f7998ee8caeb..15f8c5373672 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/Face10.java
@@ -46,6 +46,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -81,14 +82,14 @@ import java.util.Map;
* Supports a single instance of the {@link android.hardware.biometrics.face.V1_0} or
* its extended minor versions.
*/
-class Face10 implements IHwBinder.DeathRecipient {
+class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
private static final String TAG = "Face10";
private static final int ENROLL_TIMEOUT_SEC = 75;
static final String NOTIFICATION_TAG = "FaceService";
static final int NOTIFICATION_ID = 1;
- @NonNull private final FaceSensorPropertiesInternal mFaceSensorProperties;
+ @NonNull private final FaceSensorPropertiesInternal mSensorProperties;
@NonNull private final Context mContext;
@NonNull private final BiometricScheduler mScheduler;
@NonNull private final Handler mHandler;
@@ -96,23 +97,22 @@ class Face10 implements IHwBinder.DeathRecipient {
@NonNull private final LockoutResetDispatcher mLockoutResetDispatcher;
@NonNull private final LockoutHalImpl mLockoutTracker;
@NonNull private final UsageStats mUsageStats;
- @NonNull private NotificationManager mNotificationManager;
- private final int mSensorId;
+ @NonNull private final NotificationManager mNotificationManager;
@NonNull private final Map<Integer, Long> mAuthenticatorIds;
-
@Nullable private IBiometricsFace mDaemon;
- private int mCurrentUserId = UserHandle.USER_NULL;
// If a challenge is generated, keep track of its owner. Since IBiometricsFace@1.0 only
// supports a single in-flight challenge, we must notify the interrupted owner that its
// challenge is no longer valid. The interrupted owner will be notified when the interrupter
// has finished.
@Nullable private FaceGenerateChallengeClient mCurrentChallengeOwner;
+ private int mCurrentUserId = UserHandle.USER_NULL;
+ private final int mSensorId;
private final UserSwitchObserver mUserSwitchObserver = new SynchronousUserSwitchObserver() {
@Override
public void onUserSwitching(int newUserId) {
scheduleInternalCleanup(newUserId);
- scheduleGetFeature(new Binder(), newUserId,
+ scheduleGetFeature(mSensorId, new Binder(), newUserId,
BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION,
null, mContext.getOpPackageName());
}
@@ -283,7 +283,7 @@ class Face10 implements IHwBinder.DeathRecipient {
@BiometricManager.Authenticators.Types int strength,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
boolean supportsSelfIllumination, int maxTemplatesAllowed) {
- mFaceSensorProperties = new FaceSensorPropertiesInternal(sensorId,
+ mSensorProperties = new FaceSensorPropertiesInternal(sensorId,
Utils.authenticatorStrengthToPropertyStrength(strength),
maxTemplatesAllowed, false /* supportsFaceDetect */, supportsSelfIllumination);
mContext = context;
@@ -375,9 +375,10 @@ class Face10 implements IHwBinder.DeathRecipient {
if (halId != 0) {
scheduleLoadAuthenticatorIds();
scheduleInternalCleanup(ActivityManager.getCurrentUser());
- scheduleGetFeature(new Binder(), ActivityManager.getCurrentUser(),
- BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION,
- null, mContext.getOpPackageName());
+ scheduleGetFeature(mSensorId, new Binder(),
+ ActivityManager.getCurrentUser(),
+ BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION, null,
+ mContext.getOpPackageName());
} else {
Slog.e(TAG, "Unable to set callback");
mDaemon = null;
@@ -386,116 +387,39 @@ class Face10 implements IHwBinder.DeathRecipient {
return mDaemon;
}
- @LockoutTracker.LockoutMode int getLockoutModeForUser(int userId) {
- return mLockoutTracker.getLockoutModeForUser(userId);
+ @Override
+ public boolean containsSensor(int sensorId) {
+ return mSensorId == sensorId;
}
- private void scheduleLoadAuthenticatorIds() {
- // Note that this can be performed on the scheduler (as opposed to being done immediately
- // when the HAL is (re)loaded, since
- // 1) If this is truly the first time it's being performed (e.g. system has just started),
- // this will be run very early and way before any applications need to generate keys.
- // 2) If this is being performed to refresh the authenticatorIds (e.g. HAL crashed and has
- // just been reloaded), the framework already has a cache of the authenticatorIds. This
- // is safe because authenticatorIds only change when A) new template has been enrolled,
- // or B) all templates are removed.
- mHandler.post(() -> {
- for (UserInfo user : UserManager.get(mContext).getAliveUsers()) {
- final int targetUserId = user.id;
- if (!mAuthenticatorIds.containsKey(targetUserId)) {
- scheduleUpdateActiveUserWithoutHandler(targetUserId);
- }
- }
- });
+ @Override
+ @NonNull
+ public List<FaceSensorPropertiesInternal> getSensorProperties() {
+ final List<FaceSensorPropertiesInternal> properties = new ArrayList<>();
+ properties.add(mSensorProperties);
+ return properties;
}
- /**
- * Schedules the {@link FaceUpdateActiveUserClient} without posting the work onto the
- * handler. Many/most APIs are user-specific. However, the HAL requires explicit "setActiveUser"
- * invocation prior to authenticate/enroll/etc. Thus, internally we usually want to schedule
- * this operation on the same lambda/runnable as those operations so that the ordering is
- * correct.
- */
- private void scheduleUpdateActiveUserWithoutHandler(int targetUserId) {
- final boolean hasEnrolled = !getEnrolledFaces(targetUserId).isEmpty();
- final FaceUpdateActiveUserClient client = new FaceUpdateActiveUserClient(mContext,
- mLazyDaemon, targetUserId, mContext.getOpPackageName(), mSensorId, mCurrentUserId,
- hasEnrolled, mAuthenticatorIds);
- mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
- @Override
- public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) {
- if (success) {
- mCurrentUserId = targetUserId;
- }
- }
- });
+ @Override
+ @NonNull
+ public List<Face> getEnrolledFaces(int sensorId, int userId) {
+ return FaceUtils.getInstance().getBiometricsForUser(mContext, userId);
}
- void scheduleResetLockout(int userId, @NonNull byte[] hardwareAuthToken) {
- mHandler.post(() -> {
- if (getEnrolledFaces(userId).isEmpty()) {
- Slog.w(TAG, "Ignoring lockout reset, no templates enrolled for user: " + userId);
- return;
- }
-
- scheduleUpdateActiveUserWithoutHandler(userId);
-
- final FaceResetLockoutClient client = new FaceResetLockoutClient(mContext,
- mLazyDaemon, userId, mContext.getOpPackageName(), mSensorId,
- hardwareAuthToken);
- mScheduler.scheduleClientMonitor(client);
- });
+ @Override
+ @LockoutTracker.LockoutMode
+ public int getLockoutModeForUser(int sensorId, int userId) {
+ return mLockoutTracker.getLockoutModeForUser(userId);
}
- void scheduleSetFeature(@NonNull IBinder token, int userId, int feature, boolean enabled,
- @NonNull byte[] hardwareAuthToken, @NonNull IFaceServiceReceiver receiver,
- @NonNull String opPackageName) {
- mHandler.post(() -> {
- final List<Face> faces = getEnrolledFaces(userId);
- if (faces.isEmpty()) {
- Slog.w(TAG, "Ignoring setFeature, no templates enrolled for user: " + userId);
- return;
- }
-
- scheduleUpdateActiveUserWithoutHandler(userId);
-
- final int faceId = faces.get(0).getBiometricId();
- final FaceSetFeatureClient client = new FaceSetFeatureClient(mContext,
- mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), userId,
- opPackageName, mSensorId, feature, enabled, hardwareAuthToken, faceId);
- mScheduler.scheduleClientMonitor(client);
- });
+ @Override
+ public long getAuthenticatorId(int sensorId, int userId) {
+ return mAuthenticatorIds.get(userId);
}
- void scheduleGetFeature(@NonNull IBinder token, int userId, int feature,
- @Nullable ClientMonitorCallbackConverter listener, @NonNull String opPackageName) {
- mHandler.post(() -> {
- final List<Face> faces = getEnrolledFaces(userId);
- if (faces.isEmpty()) {
- Slog.w(TAG, "Ignoring getFeature, no templates enrolled for user: " + userId);
- return;
- }
-
- scheduleUpdateActiveUserWithoutHandler(userId);
-
- final int faceId = faces.get(0).getBiometricId();
- final FaceGetFeatureClient client = new FaceGetFeatureClient(mContext, mLazyDaemon,
- token, listener, userId, opPackageName, mSensorId, feature, faceId);
- mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
- @Override
- public void onClientFinished(
- @NonNull ClientMonitor<?> clientMonitor, boolean success) {
- if (success && feature == BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION) {
- final int settingsValue = client.getValue() ? 1 : 0;
- Slog.d(TAG, "Updating attention value for user: " + userId
- + " to value: " + settingsValue);
- Settings.Secure.putIntForUser(mContext.getContentResolver(),
- Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
- settingsValue, userId);
- }
- }
- });
- });
+ @Override
+ public boolean isHardwareDetected(int sensorId) {
+ return getDaemon() != null;
}
/**
@@ -514,8 +438,9 @@ class Face10 implements IHwBinder.DeathRecipient {
* The only case of conflicting challenges is currently resetLockout --> enroll. So, the second
* option seems better as it prioritizes the new operation, which is user-facing.
*/
- void scheduleGenerateChallenge(@NonNull IBinder token, @NonNull IFaceServiceReceiver receiver,
- @NonNull String opPackageName) {
+ @Override
+ public void scheduleGenerateChallenge(int sensorId, int userId, @NonNull IBinder token,
+ @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
mHandler.post(() -> {
if (mCurrentChallengeOwner != null) {
final ClientMonitorCallbackConverter listener =
@@ -550,18 +475,20 @@ class Face10 implements IHwBinder.DeathRecipient {
});
}
- void scheduleRevokeChallenge(@NonNull IBinder token, @NonNull String owner) {
+ @Override
+ public void scheduleRevokeChallenge(int sensorId, int userId, @NonNull IBinder token,
+ @NonNull String opPackageName, long challenge) {
mHandler.post(() -> {
if (mCurrentChallengeOwner != null &&
- !mCurrentChallengeOwner.getOwnerString().contentEquals(owner)) {
- Slog.e(TAG, "scheduleRevokeChallenge, package: " + owner
+ !mCurrentChallengeOwner.getOwnerString().contentEquals(opPackageName)) {
+ Slog.e(TAG, "scheduleRevokeChallenge, package: " + opPackageName
+ " attempting to revoke challenge owned by: "
+ mCurrentChallengeOwner.getOwnerString());
return;
}
final FaceRevokeChallengeClient client = new FaceRevokeChallengeClient(mContext,
- mLazyDaemon, token, owner, mSensorId);
+ mLazyDaemon, token, opPackageName, mSensorId);
mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
@Override
public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor,
@@ -582,13 +509,19 @@ class Face10 implements IHwBinder.DeathRecipient {
final FaceGenerateChallengeClient previousChallengeOwner =
mCurrentChallengeOwner.getInterruptedClient();
mCurrentChallengeOwner = null;
+
Slog.d(TAG, "Previous challenge owner: " + previousChallengeOwner);
if (previousChallengeOwner != null) {
- try {
- previousChallengeOwner.getListener()
- .onChallengeInterruptFinished(mSensorId);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to notify interrupt finished", e);
+ final ClientMonitorCallbackConverter listener =
+ previousChallengeOwner.getListener();
+ if (listener == null) {
+ Slog.w(TAG, "Listener is null");
+ } else {
+ try {
+ listener.onChallengeInterruptFinished(mSensorId);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to notify interrupt finished", e);
+ }
}
}
}
@@ -596,9 +529,11 @@ class Face10 implements IHwBinder.DeathRecipient {
});
}
- void scheduleEnroll(@NonNull IBinder token, @NonNull byte[] hardwareAuthToken, int userId,
- @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName,
- @NonNull int[] disabledFeatures, @Nullable NativeHandle surfaceHandle) {
+ @Override
+ public void scheduleEnroll(int sensorId, @NonNull IBinder token,
+ @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFaceServiceReceiver receiver,
+ @NonNull String opPackageName, @NonNull int[] disabledFeatures,
+ @Nullable NativeHandle surfaceHandle) {
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
@@ -623,15 +558,18 @@ class Face10 implements IHwBinder.DeathRecipient {
});
}
- void cancelEnrollment(@NonNull IBinder token) {
+ @Override
+ public void cancelEnrollment(int sensorId, @NonNull IBinder token) {
mHandler.post(() -> {
mScheduler.cancelEnrollment(token);
});
}
- void scheduleAuthenticate(@NonNull IBinder token, long operationId, int userId, int cookie,
- @NonNull ClientMonitorCallbackConverter receiver, @NonNull String opPackageName,
- boolean restricted, int statsClient) {
+ @Override
+ public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
+ int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver,
+ @NonNull String opPackageName, boolean restricted, int statsClient,
+ boolean isKeyguard) {
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
@@ -644,19 +582,15 @@ class Face10 implements IHwBinder.DeathRecipient {
});
}
- void startPreparedClient(int cookie) {
- mHandler.post(() -> {
- mScheduler.startPreparedClient(cookie);
- });
- }
-
- void cancelAuthentication(@NonNull IBinder token) {
+ @Override
+ public void cancelAuthentication(int sensorId, @NonNull IBinder token) {
mHandler.post(() -> {
mScheduler.cancelAuthentication(token);
});
}
- void scheduleRemove(@NonNull IBinder token, int faceId, int userId,
+ @Override
+ public void scheduleRemove(int sensorId, @NonNull IBinder token, int faceId, int userId,
@NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
@@ -668,11 +602,82 @@ class Face10 implements IHwBinder.DeathRecipient {
});
}
+
+ @Override
+ public void scheduleResetLockout(int sensorId, int userId, @NonNull byte[] hardwareAuthToken) {
+ mHandler.post(() -> {
+ if (getEnrolledFaces(sensorId, userId).isEmpty()) {
+ Slog.w(TAG, "Ignoring lockout reset, no templates enrolled for user: " + userId);
+ return;
+ }
+
+ scheduleUpdateActiveUserWithoutHandler(userId);
+
+ final FaceResetLockoutClient client = new FaceResetLockoutClient(mContext,
+ mLazyDaemon, userId, mContext.getOpPackageName(), mSensorId,
+ hardwareAuthToken);
+ mScheduler.scheduleClientMonitor(client);
+ });
+ }
+
+ @Override
+ public void scheduleSetFeature(int sensorId, @NonNull IBinder token, int userId, int feature,
+ boolean enabled, @NonNull byte[] hardwareAuthToken,
+ @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName) {
+ mHandler.post(() -> {
+ final List<Face> faces = getEnrolledFaces(sensorId, userId);
+ if (faces.isEmpty()) {
+ Slog.w(TAG, "Ignoring setFeature, no templates enrolled for user: " + userId);
+ return;
+ }
+
+ scheduleUpdateActiveUserWithoutHandler(userId);
+
+ final int faceId = faces.get(0).getBiometricId();
+ final FaceSetFeatureClient client = new FaceSetFeatureClient(mContext,
+ mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), userId,
+ opPackageName, mSensorId, feature, enabled, hardwareAuthToken, faceId);
+ mScheduler.scheduleClientMonitor(client);
+ });
+ }
+
+ @Override
+ public void scheduleGetFeature(int sensorId, @NonNull IBinder token, int userId, int feature,
+ @Nullable ClientMonitorCallbackConverter listener, @NonNull String opPackageName) {
+ mHandler.post(() -> {
+ final List<Face> faces = getEnrolledFaces(sensorId, userId);
+ if (faces.isEmpty()) {
+ Slog.w(TAG, "Ignoring getFeature, no templates enrolled for user: " + userId);
+ return;
+ }
+
+ scheduleUpdateActiveUserWithoutHandler(userId);
+
+ final int faceId = faces.get(0).getBiometricId();
+ final FaceGetFeatureClient client = new FaceGetFeatureClient(mContext, mLazyDaemon,
+ token, listener, userId, opPackageName, mSensorId, feature, faceId);
+ mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
+ @Override
+ public void onClientFinished(
+ @NonNull ClientMonitor<?> clientMonitor, boolean success) {
+ if (success && feature == BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION) {
+ final int settingsValue = client.getValue() ? 1 : 0;
+ Slog.d(TAG, "Updating attention value for user: " + userId
+ + " to value: " + settingsValue);
+ Settings.Secure.putIntForUser(mContext.getContentResolver(),
+ Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
+ settingsValue, userId);
+ }
+ }
+ });
+ });
+ }
+
private void scheduleInternalCleanup(int userId) {
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
- final List<Face> enrolledList = getEnrolledFaces(userId);
+ final List<Face> enrolledList = getEnrolledFaces(mSensorId, userId);
final FaceInternalCleanupClient client = new FaceInternalCleanupClient(mContext,
mLazyDaemon, userId, mContext.getOpPackageName(), mSensorId, enrolledList,
FaceUtils.getInstance(), mAuthenticatorIds);
@@ -680,25 +685,28 @@ class Face10 implements IHwBinder.DeathRecipient {
});
}
- boolean isHardwareDetected() {
- final IBiometricsFace daemon = getDaemon();
- return daemon != null;
+ @Override
+ public void scheduleInternalCleanup(int sensorId, int userId) {
+ scheduleInternalCleanup(userId);
}
- @NonNull
- FaceSensorPropertiesInternal getFaceSensorProperties() {
- return mFaceSensorProperties;
+ @Override
+ public void startPreparedClient(int sensorId, int cookie) {
+ mHandler.post(() -> {
+ mScheduler.startPreparedClient(cookie);
+ });
}
- List<Face> getEnrolledFaces(int userId) {
- return FaceUtils.getInstance().getBiometricsForUser(mContext, userId);
+ @Override
+ public void dumpProtoState(int sensorId, ProtoOutputStream proto) {
}
- long getAuthenticatorId(int userId) {
- return mAuthenticatorIds.get(userId);
+ @Override
+ public void dumpProtoMetrics(int sensorId, FileDescriptor fd) {
}
- public void dump(@NonNull PrintWriter pw) {
+ @Override
+ public void dumpInternal(int sensorId, PrintWriter pw) {
PerformanceTracker performanceTracker =
PerformanceTracker.getInstanceForSensorId(mSensorId);
@@ -733,9 +741,51 @@ class Face10 implements IHwBinder.DeathRecipient {
pw.println(dump);
pw.println("HAL deaths since last reboot: " + performanceTracker.getHALDeathCount());
+ mScheduler.dump(pw);
mUsageStats.print(pw);
}
+ private void scheduleLoadAuthenticatorIds() {
+ // Note that this can be performed on the scheduler (as opposed to being done immediately
+ // when the HAL is (re)loaded, since
+ // 1) If this is truly the first time it's being performed (e.g. system has just started),
+ // this will be run very early and way before any applications need to generate keys.
+ // 2) If this is being performed to refresh the authenticatorIds (e.g. HAL crashed and has
+ // just been reloaded), the framework already has a cache of the authenticatorIds. This
+ // is safe because authenticatorIds only change when A) new template has been enrolled,
+ // or B) all templates are removed.
+ mHandler.post(() -> {
+ for (UserInfo user : UserManager.get(mContext).getAliveUsers()) {
+ final int targetUserId = user.id;
+ if (!mAuthenticatorIds.containsKey(targetUserId)) {
+ scheduleUpdateActiveUserWithoutHandler(targetUserId);
+ }
+ }
+ });
+ }
+
+ /**
+ * Schedules the {@link FaceUpdateActiveUserClient} without posting the work onto the
+ * handler. Many/most APIs are user-specific. However, the HAL requires explicit "setActiveUser"
+ * invocation prior to authenticate/enroll/etc. Thus, internally we usually want to schedule
+ * this operation on the same lambda/runnable as those operations so that the ordering is
+ * correct.
+ */
+ private void scheduleUpdateActiveUserWithoutHandler(int targetUserId) {
+ final boolean hasEnrolled = !getEnrolledFaces(mSensorId, targetUserId).isEmpty();
+ final FaceUpdateActiveUserClient client = new FaceUpdateActiveUserClient(mContext,
+ mLazyDaemon, targetUserId, mContext.getOpPackageName(), mSensorId, mCurrentUserId,
+ hasEnrolled, mAuthenticatorIds);
+ mScheduler.scheduleClientMonitor(client, new ClientMonitor.Callback() {
+ @Override
+ public void onClientFinished(@NonNull ClientMonitor<?> clientMonitor, boolean success) {
+ if (success) {
+ mCurrentUserId = targetUserId;
+ }
+ }
+ });
+ }
+
public void dumpHal(@NonNull FileDescriptor fd, @NonNull String[] args) {
// WARNING: CDD restricts image data from leaving TEE unencrypted on
// production devices:
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index 83f10c8e658b..a298e19e4b02 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -16,10 +16,12 @@
package com.android.server.biometrics.sensors.face;
+import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.MANAGE_BIOMETRIC;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricsProtoEnums;
@@ -32,7 +34,10 @@ import android.hardware.face.IFaceServiceReceiver;
import android.os.Binder;
import android.os.IBinder;
import android.os.NativeHandle;
+import android.os.UserHandle;
+import android.util.Pair;
import android.util.Slog;
+import android.util.proto.ProtoOutputStream;
import android.view.Surface;
import com.android.internal.util.DumpUtils;
@@ -46,7 +51,7 @@ import com.android.server.biometrics.sensors.LockoutTracker;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
/**
@@ -58,9 +63,65 @@ public class FaceService extends SystemService {
protected static final String TAG = "FaceService";
- private Face10 mFace10;
private final LockoutResetDispatcher mLockoutResetDispatcher;
private final LockPatternUtils mLockPatternUtils;
+ @NonNull
+ private List<ServiceProvider> mServiceProviders;
+
+ @Nullable
+ private ServiceProvider getProviderForSensor(int sensorId) {
+ for (ServiceProvider provider : mServiceProviders) {
+ if (provider.containsSensor(sensorId)) {
+ return provider;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * For devices with only a single provider, returns that provider. If no providers, or multiple
+ * providers exist, returns null.
+ */
+ @Nullable
+ private Pair<Integer, ServiceProvider> getSingleProvider() {
+ final List<FaceSensorPropertiesInternal> properties = getSensorProperties();
+ if (properties.size() != 1) {
+ Slog.e(TAG, "Multiple sensors found: " + properties.size());
+ return null;
+ }
+
+ // Theoretically we can just return the first provider, but maybe this is easier to
+ // understand.
+ final int sensorId = properties.get(0).sensorId;
+ for (ServiceProvider provider : mServiceProviders) {
+ if (provider.containsSensor(sensorId)) {
+ return new Pair<>(sensorId, provider);
+ }
+ }
+
+ Slog.e(TAG, "Single sensor, but provider not found");
+ return null;
+ }
+
+ @NonNull
+ private List<FaceSensorPropertiesInternal> getSensorProperties() {
+ final List<FaceSensorPropertiesInternal> properties = new ArrayList<>();
+ for (ServiceProvider provider : mServiceProviders) {
+ properties.addAll(provider.getSensorProperties());
+ }
+ return properties;
+ }
+
+ @NonNull
+ private List<Face> getEnrolledFaces(int userId, String opPackageName) {
+ final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for getEnrolledFaces, caller: " + opPackageName);
+ return Collections.emptyList();
+ }
+
+ return provider.second.getEnrolledFaces(provider.first, userId);
+ }
/**
* Receives the incoming binder calls from FaceManager.
@@ -69,13 +130,10 @@ public class FaceService extends SystemService {
@Override // Binder call
public List<FaceSensorPropertiesInternal> getSensorPropertiesInternal(
String opPackageName) {
- Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
-
- final List<FaceSensorPropertiesInternal> properties = new ArrayList<>();
+ Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
- if (mFace10 != null) {
- properties.add(mFace10.getFaceSensorProperties());
- }
+ final List<FaceSensorPropertiesInternal> properties =
+ FaceService.this.getSensorProperties();
Slog.d(TAG, "Retrieved sensor properties for: " + opPackageName
+ ", sensors: " + properties.size());
@@ -83,27 +141,31 @@ public class FaceService extends SystemService {
}
@Override // Binder call
- public void generateChallenge(IBinder token, int sensorId, IFaceServiceReceiver receiver,
- String opPackageName) {
+ public void generateChallenge(IBinder token, int sensorId, int userId,
+ IFaceServiceReceiver receiver, String opPackageName) {
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
- if (sensorId == mFace10.getFaceSensorProperties().sensorId) {
- mFace10.scheduleGenerateChallenge(token, receiver, opPackageName);
+
+ final ServiceProvider provider = getProviderForSensor(sensorId);
+ if (provider == null) {
+ Slog.w(TAG, "No matching sensor for generateChallenge, sensorId: " + sensorId);
return;
}
- Slog.w(TAG, "No matching sensor for generateChallenge, sensorId: " + sensorId);
+ provider.scheduleGenerateChallenge(sensorId, userId, token, receiver, opPackageName);
}
@Override // Binder call
- public void revokeChallenge(IBinder token, int sensorId, String owner) {
+ public void revokeChallenge(IBinder token, int sensorId, int userId, String opPackageName,
+ long challenge) {
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
- if (sensorId == mFace10.getFaceSensorProperties().sensorId) {
- mFace10.scheduleRevokeChallenge(token, owner);
+ final ServiceProvider provider = getProviderForSensor(sensorId);
+ if (provider == null) {
+ Slog.w(TAG, "No matching sensor for revokeChallenge, sensorId: " + sensorId);
return;
}
- Slog.w(TAG, "No matching sensor for revokeChallenge, sensorId: " + sensorId);
+ provider.scheduleRevokeChallenge(sensorId, userId, token, opPackageName, challenge);
}
@Override // Binder call
@@ -111,8 +173,16 @@ public class FaceService extends SystemService {
final IFaceServiceReceiver receiver, final String opPackageName,
final int[] disabledFeatures, Surface surface) {
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
- mFace10.scheduleEnroll(token, hardwareAuthToken, userId, receiver, opPackageName,
- disabledFeatures, convertSurfaceToNativeHandle(surface));
+
+ final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for enroll");
+ return;
+ }
+
+ provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId,
+ receiver, opPackageName, disabledFeatures,
+ convertSurfaceToNativeHandle(surface));
}
@Override // Binder call
@@ -126,7 +196,14 @@ public class FaceService extends SystemService {
@Override // Binder call
public void cancelEnrollment(final IBinder token) {
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
- mFace10.cancelEnrollment(token);
+
+ final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for cancelEnrollment");
+ return;
+ }
+
+ provider.second.cancelEnrollment(provider.first, token);
}
@Override // Binder call
@@ -141,9 +218,21 @@ public class FaceService extends SystemService {
final int statsClient = Utils.isKeyguard(getContext(), opPackageName)
? BiometricsProtoEnums.CLIENT_KEYGUARD
: BiometricsProtoEnums.CLIENT_UNKNOWN;
- mFace10.scheduleAuthenticate(token, operationId, userId, 0 /* cookie */,
+
+ // Keyguard check must be done on the caller's binder identity, since it also checks
+ // permission.
+ final boolean isKeyguard = Utils.isKeyguard(getContext(), opPackageName);
+
+ final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for authenticate");
+ return;
+ }
+
+ provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
+ 0 /* cookie */,
new ClientMonitorCallbackConverter(receiver), opPackageName, restricted,
- statsClient);
+ statsClient, isKeyguard);
}
@Override // Binder call
@@ -172,22 +261,42 @@ public class FaceService extends SystemService {
int callingUserId) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
+ final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for prepareForAuthentication");
+ return;
+ }
+
final boolean restricted = true; // BiometricPrompt is always restricted
- mFace10.scheduleAuthenticate(token, operationId, userId, cookie,
- new ClientMonitorCallbackConverter(sensorReceiver), opPackageName,
- restricted, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT);
+ provider.second.scheduleAuthenticate(provider.first, token, operationId, userId, cookie,
+ new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, restricted,
+ BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, false /* isKeyguard */);
}
@Override // Binder call
public void startPreparedClient(int cookie) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- mFace10.startPreparedClient(cookie);
+
+ final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for startPreparedClient");
+ return;
+ }
+
+ provider.second.startPreparedClient(provider.first, cookie);
}
@Override // Binder call
public void cancelAuthentication(final IBinder token, final String opPackageName) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- mFace10.cancelAuthentication(token);
+
+ final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for cancelAuthentication");
+ return;
+ }
+
+ provider.second.cancelAuthentication(provider.first, token);
}
@Override // Binder call
@@ -206,14 +315,29 @@ public class FaceService extends SystemService {
public void cancelAuthenticationFromService(final IBinder token, final String opPackageName,
int callingUid, int callingPid, int callingUserId) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- mFace10.cancelAuthentication(token);
+
+ final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for cancelAuthenticationFromService");
+ return;
+ }
+
+ provider.second.cancelAuthentication(provider.first, token);
}
@Override // Binder call
public void remove(final IBinder token, final int faceId, final int userId,
final IFaceServiceReceiver receiver, final String opPackageName) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- mFace10.scheduleRemove(token, faceId, userId, receiver, opPackageName);
+
+ final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for remove");
+ return;
+ }
+
+ provider.second.scheduleRemove(provider.first, token, faceId, userId, receiver,
+ opPackageName);
}
@Override
@@ -231,10 +355,28 @@ public class FaceService extends SystemService {
final long ident = Binder.clearCallingIdentity();
try {
- if (args.length > 1 && "--hal".equals(args[0])) {
- mFace10.dumpHal(fd, Arrays.copyOfRange(args, 1, args.length, args.getClass()));
+ if (args.length > 1 && "--proto".equals(args[0]) && "--state".equals(args[1])) {
+ final ProtoOutputStream proto = new ProtoOutputStream(fd);
+ for (ServiceProvider provider : mServiceProviders) {
+ for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
+ provider.dumpProtoState(props.sensorId, proto);
+ }
+ }
+ proto.flush();
+ } else if (args.length > 0 && "--proto".equals(args[0])) {
+ for (ServiceProvider provider : mServiceProviders) {
+ for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
+ provider.dumpProtoMetrics(props.sensorId, fd);
+ }
+ }
} else {
- mFace10.dump(pw);
+ for (ServiceProvider provider : mServiceProviders) {
+ for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) {
+ pw.println("Dumping for sensorId: " + props.sensorId
+ + ", provider: " + provider.getClass().getSimpleName());
+ provider.dumpInternal(props.sensorId, pw);
+ }
+ }
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -244,13 +386,15 @@ public class FaceService extends SystemService {
@Override // Binder call
public boolean isHardwareDetected(String opPackageName) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- if (mFace10 == null) {
- Slog.wtf(TAG, "No HAL, caller: " + opPackageName);
- return false;
- }
+
final long token = Binder.clearCallingIdentity();
try {
- return mFace10.isHardwareDetected();
+ final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for isHardwareDetected, caller: " + opPackageName);
+ return false;
+ }
+ return provider.second.isHardwareDetected(provider.first);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -259,25 +403,50 @@ public class FaceService extends SystemService {
@Override // Binder call
public List<Face> getEnrolledFaces(int userId, String opPackageName) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- return mFace10.getEnrolledFaces(userId);
+
+ if (userId != UserHandle.getCallingUserId()) {
+ Utils.checkPermission(getContext(), INTERACT_ACROSS_USERS);
+ }
+
+ return FaceService.this.getEnrolledFaces(userId, opPackageName);
}
@Override // Binder call
public boolean hasEnrolledFaces(int userId, String opPackageName) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- return !mFace10.getEnrolledFaces(userId).isEmpty();
+
+ if (userId != UserHandle.getCallingUserId()) {
+ Utils.checkPermission(getContext(), INTERACT_ACROSS_USERS);
+ }
+
+ return !FaceService.this.getEnrolledFaces(userId, opPackageName).isEmpty();
}
- @Override
- public @LockoutTracker.LockoutMode int getLockoutModeForUser(int userId) {
+ @Override // Binder call
+ @LockoutTracker.LockoutMode
+ public int getLockoutModeForUser(int userId) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- return mFace10.getLockoutModeForUser(userId);
+
+ final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for getLockoutModeForUser");
+ return LockoutTracker.LOCKOUT_NONE;
+ }
+
+ return provider.second.getLockoutModeForUser(provider.first, userId);
}
@Override // Binder call
public long getAuthenticatorId(int userId) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- return mFace10.getAuthenticatorId(userId);
+
+ final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for getAuthenticatorId");
+ return 0;
+ }
+
+ return provider.second.getAuthenticatorId(provider.first, userId);
}
@Override // Binder call
@@ -285,12 +454,13 @@ public class FaceService extends SystemService {
String opPackageName) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- if (sensorId == mFace10.getFaceSensorProperties().sensorId) {
- mFace10.scheduleResetLockout(userId, hardwareAuthToken);
+ final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for resetLockout, caller: " + opPackageName);
return;
}
- Slog.w(TAG, "No matching sensor for resetLockout, sensorId: " + sensorId);
+ provider.second.scheduleResetLockout(provider.first, userId, hardwareAuthToken);
}
@Override
@@ -298,15 +468,29 @@ public class FaceService extends SystemService {
final byte[] hardwareAuthToken, IFaceServiceReceiver receiver,
final String opPackageName) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- mFace10.scheduleSetFeature(token, userId, feature, enabled, hardwareAuthToken, receiver,
- opPackageName);
+
+ final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for setFeature");
+ return;
+ }
+
+ provider.second.scheduleSetFeature(provider.first, token, userId, feature, enabled,
+ hardwareAuthToken, receiver, opPackageName);
}
@Override
public void getFeature(final IBinder token, int userId, int feature,
IFaceServiceReceiver receiver, final String opPackageName) {
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
- mFace10.scheduleGetFeature(token, userId, feature,
+
+ final Pair<Integer, ServiceProvider> provider = getSingleProvider();
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for getFeature");
+ return;
+ }
+
+ provider.second.scheduleGetFeature(provider.first, token, userId, feature,
new ClientMonitorCallbackConverter(receiver), opPackageName);
}
@@ -314,7 +498,8 @@ public class FaceService extends SystemService {
public void initializeConfiguration(int sensorId,
@BiometricManager.Authenticators.Types int strength) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
- mFace10 = new Face10(getContext(), sensorId, strength, mLockoutResetDispatcher);
+ mServiceProviders.add(
+ new Face10(getContext(), sensorId, strength, mLockoutResetDispatcher));
}
}
@@ -322,6 +507,7 @@ public class FaceService extends SystemService {
super(context);
mLockoutResetDispatcher = new LockoutResetDispatcher(context);
mLockPatternUtils = new LockPatternUtils(context);
+ mServiceProviders = new ArrayList<>();
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
new file mode 100644
index 000000000000..e3fb750a1e14
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
@@ -0,0 +1,113 @@
+/*
+ * 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.biometrics.sensors.face;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.face.Face;
+import android.hardware.face.FaceSensorPropertiesInternal;
+import android.hardware.face.IFaceServiceReceiver;
+import android.os.IBinder;
+import android.os.NativeHandle;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+import com.android.server.biometrics.sensors.LockoutTracker;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * Superset of features across all the face HAL interfaces that are available to the framework. This
+ * is more or less mapped to the public and private APIs that {@link FaceManager} provides, and
+ * is used at the system server layer to provide easy mapping between requests and providers.
+ *
+ * Note that providers support both single-sensor and multi-sensor HALs. In either case,
+ * {@link FaceService} must ensure that providers are only requested to perform operations
+ * on sensors that they own.
+ *
+ * For methods other than {@link #containsSensor(int)}, the caller must ensure that the sensorId
+ * is supported by the provider. For example:
+ * if (serviceProvider.containsSensor(sensorId)) {
+ * serviceProvider.operation(sensorId, ...);
+ * }
+ *
+ * For operations that are supported by some providers but not others, clients are required
+ * to check (e.g. via {@link FaceManager#getSensorPropertiesInternal()}) that the code path isn't
+ * taken. ServiceProviders will provide a no-op for unsupported operations to fail safely.
+ */
+public interface ServiceProvider {
+ /**
+ * Checks if the specified sensor is owned by this provider.
+ */
+ boolean containsSensor(int sensorId);
+
+ @NonNull
+ List<FaceSensorPropertiesInternal> getSensorProperties();
+
+ @NonNull
+ List<Face> getEnrolledFaces(int sensorId, int userId);
+
+ @LockoutTracker.LockoutMode
+ int getLockoutModeForUser(int sensorId, int userId);
+
+ long getAuthenticatorId(int sensorId, int userId);
+
+ boolean isHardwareDetected(int sensorId);
+
+ void scheduleGenerateChallenge(int sensorId, int userId, @NonNull IBinder token,
+ @NonNull IFaceServiceReceiver receiver, String opPackageName);
+
+ void scheduleRevokeChallenge(int sensorId, int userId, @NonNull IBinder token,
+ @NonNull String opPackageName, long challenge);
+
+ void scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken,
+ int userId, @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName,
+ @NonNull int[] disabledFeatures, @Nullable NativeHandle surfaceHandle);
+
+ void cancelEnrollment(int sensorId, @NonNull IBinder token);
+
+ void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
+ int cookie, @NonNull ClientMonitorCallbackConverter callback,
+ @NonNull String opPackageName, boolean restricted, int statsClient, boolean isKeyguard);
+
+
+ void cancelAuthentication(int sensorId, @NonNull IBinder token);
+
+ void scheduleRemove(int sensorId, @NonNull IBinder token, int faceId, int userId,
+ @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName);
+
+ void scheduleResetLockout(int sensorId, int userId, @NonNull byte[] hardwareAuthToken);
+
+ void scheduleSetFeature(int sensorId, @NonNull IBinder token, int userId, int feature,
+ boolean enabled, @NonNull byte[] hardwareAuthToken,
+ @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName);
+
+ void scheduleGetFeature(int sensorId, @NonNull IBinder token, int userId, int feature,
+ @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName);
+
+ void startPreparedClient(int sensorId, int cookie);
+
+ void scheduleInternalCleanup(int sensorId, int userId);
+
+ void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto);
+
+ void dumpProtoMetrics(int sensorId, @NonNull FileDescriptor fd);
+
+ void dumpInternal(int sensorId, @NonNull PrintWriter pw);
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index c88247f59871..265ba0545395 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -469,6 +469,27 @@ public class FingerprintService extends SystemService {
}
@Override // Binder call
+ public boolean hasEnrolledTemplatesForAnySensor(int userId,
+ @NonNull List<FingerprintSensorPropertiesInternal> sensors,
+ @NonNull String opPackageName) {
+ Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
+
+ for (FingerprintSensorPropertiesInternal prop : sensors) {
+ final ServiceProvider provider = getProviderForSensor(prop.sensorId);
+ if (provider == null) {
+ Slog.w(TAG, "Null provider for sensorId: " + prop.sensorId
+ + ", caller: " + opPackageName);
+ continue;
+ }
+
+ if (!provider.getEnrolledFingerprints(prop.sensorId, userId).isEmpty()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override // Binder call
public @LockoutTracker.LockoutMode int getLockoutModeForUser(int userId) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index a806e3f61bc8..8c766d682bf7 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -646,8 +646,7 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
@Override
public boolean isHardwareDetected(int sensorId) {
- final IBiometricsFingerprint daemon = getDaemon();
- return daemon != null;
+ return getDaemon() != null;
}
@Override
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 88867fcfc46f..a4ae9c87c694 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -15,6 +15,7 @@
*/
package com.android.server.camera;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
@@ -39,6 +40,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.FrameworkStatsLog;
@@ -48,6 +50,8 @@ import com.android.server.SystemService;
import com.android.server.SystemService.TargetUser;
import com.android.server.wm.WindowManagerInternal;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -79,10 +83,19 @@ public class CameraServiceProxy extends SystemService
// Handler message codes
private static final int MSG_SWITCH_USER = 1;
+ private static final int MSG_NOTIFY_DEVICE_STATE = 2;
private static final int RETRY_DELAY_TIME = 20; //ms
private static final int RETRY_TIMES = 60;
+ @IntDef(flag = true, prefix = { "DEVICE_STATE_" }, value = {
+ ICameraService.DEVICE_STATE_BACK_COVERED,
+ ICameraService.DEVICE_STATE_FRONT_COVERED,
+ ICameraService.DEVICE_STATE_FOLDED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface DeviceStateFlags {}
+
// Maximum entries to keep in usage history before dumping out
private static final int MAX_USAGE_HISTORY = 100;
@@ -94,6 +107,15 @@ public class CameraServiceProxy extends SystemService
private final Object mLock = new Object();
private Set<Integer> mEnabledCameraUsers;
private int mLastUser;
+ // The current set of device state flags. May be different from mLastReportedDeviceState if the
+ // native camera service has not been notified of the change.
+ @GuardedBy("mLock")
+ @DeviceStateFlags
+ private int mDeviceState;
+ // The most recent device state flags reported to the native camera server.
+ @GuardedBy("mLock")
+ @DeviceStateFlags
+ private int mLastReportedDeviceState;
private ICameraService mCameraServiceRaw;
@@ -185,6 +207,7 @@ public class CameraServiceProxy extends SystemService
return;
}
notifySwitchWithRetries(RETRY_TIMES);
+ notifyDeviceStateWithRetries(RETRY_TIMES);
}
@Override
@@ -218,12 +241,55 @@ public class CameraServiceProxy extends SystemService
mLogWriterService.allowCoreThreadTimeOut(true);
}
+ /**
+ * Sets the device state bits set within {@code deviceStateFlags} leaving all other bits the
+ * same.
+ * <p>
+ * Calling requires permission {@link android.Manifest.permission#CAMERA_SEND_SYSTEM_EVENTS}.
+ *
+ * @param deviceStateFlags a bitmask of the device state bits that should be set.
+ *
+ * @see #clearDeviceStateFlags(int)
+ */
+ public void setDeviceStateFlags(@DeviceStateFlags int deviceStateFlags) {
+ synchronized (mLock) {
+ mHandler.removeMessages(MSG_NOTIFY_DEVICE_STATE);
+ mDeviceState |= deviceStateFlags;
+ if (mDeviceState != mLastReportedDeviceState) {
+ notifyDeviceStateWithRetriesLocked(RETRY_TIMES);
+ }
+ }
+ }
+
+ /**
+ * Clears the device state bits set within {@code deviceStateFlags} leaving all other bits the
+ * same.
+ * <p>
+ * Calling requires permission {@link android.Manifest.permission#CAMERA_SEND_SYSTEM_EVENTS}.
+ *
+ * @param deviceStateFlags a bitmask of the device state bits that should be cleared.
+ *
+ * @see #setDeviceStateFlags(int)
+ */
+ public void clearDeviceStateFlags(@DeviceStateFlags int deviceStateFlags) {
+ synchronized (mLock) {
+ mHandler.removeMessages(MSG_NOTIFY_DEVICE_STATE);
+ mDeviceState &= ~deviceStateFlags;
+ if (mDeviceState != mLastReportedDeviceState) {
+ notifyDeviceStateWithRetriesLocked(RETRY_TIMES);
+ }
+ }
+ }
+
@Override
public boolean handleMessage(Message msg) {
switch(msg.what) {
case MSG_SWITCH_USER: {
notifySwitchWithRetries(msg.arg1);
} break;
+ case MSG_NOTIFY_DEVICE_STATE: {
+ notifyDeviceStateWithRetries(msg.arg1);
+ } break;
default: {
Slog.e(TAG, "CameraServiceProxy error, invalid message: " + msg.what);
} break;
@@ -386,6 +452,25 @@ public class CameraServiceProxy extends SystemService
}
}
+ @Nullable
+ private ICameraService getCameraServiceRawLocked() {
+ if (mCameraServiceRaw == null) {
+ IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME);
+ if (cameraServiceBinder == null) {
+ return null;
+ }
+ try {
+ cameraServiceBinder.linkToDeath(this, /*flags*/ 0);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Could not link to death of native camera service");
+ return null;
+ }
+
+ mCameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
+ }
+ return mCameraServiceRaw;
+ }
+
private void switchUserLocked(int userHandle) {
Set<Integer> currentUserHandles = getEnabledUserHandles(userHandle);
mLastUser = userHandle;
@@ -431,20 +516,10 @@ public class CameraServiceProxy extends SystemService
private boolean notifyCameraserverLocked(int eventType, Set<Integer> updatedUserHandles) {
// Forward the user switch event to the native camera service running in the cameraserver
// process.
- if (mCameraServiceRaw == null) {
- IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME);
- if (cameraServiceBinder == null) {
- Slog.w(TAG, "Could not notify cameraserver, camera service not available.");
- return false; // Camera service not active, cannot evict user clients.
- }
- try {
- cameraServiceBinder.linkToDeath(this, /*flags*/ 0);
- } catch (RemoteException e) {
- Slog.w(TAG, "Could not link to death of native camera service");
- return false;
- }
-
- mCameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
+ ICameraService cameraService = getCameraServiceRawLocked();
+ if (cameraService == null) {
+ Slog.w(TAG, "Could not notify cameraserver, camera service not available.");
+ return false;
}
try {
@@ -457,6 +532,43 @@ public class CameraServiceProxy extends SystemService
return true;
}
+ private void notifyDeviceStateWithRetries(int retries) {
+ synchronized (mLock) {
+ notifyDeviceStateWithRetriesLocked(retries);
+ }
+ }
+
+ private void notifyDeviceStateWithRetriesLocked(int retries) {
+ if (notifyDeviceStateChangeLocked(mDeviceState)) {
+ return;
+ }
+ if (retries <= 0) {
+ return;
+ }
+ Slog.i(TAG, "Could not notify camera service of device state change, retrying...");
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_NOTIFY_DEVICE_STATE, retries - 1,
+ 0, null), RETRY_DELAY_TIME);
+ }
+
+ private boolean notifyDeviceStateChangeLocked(@DeviceStateFlags int deviceState) {
+ // Forward the state to the native camera service running in the cameraserver process.
+ ICameraService cameraService = getCameraServiceRawLocked();
+ if (cameraService == null) {
+ Slog.w(TAG, "Could not notify cameraserver, camera service not available.");
+ return false;
+ }
+
+ try {
+ mCameraServiceRaw.notifyDeviceStateChange(deviceState);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Could not notify cameraserver, remote exception: " + e);
+ // Not much we can do if camera service is dead.
+ return false;
+ }
+ mLastReportedDeviceState = deviceState;
+ return true;
+ }
+
private void updateActivityCount(String cameraId, int newCameraState, int facing,
String clientName, int apiLevel) {
synchronized(mLock) {
diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java
index bc3bff1b966f..ff3193182501 100644
--- a/services/core/java/com/android/server/compat/CompatChange.java
+++ b/services/core/java/com/android/server/compat/CompatChange.java
@@ -18,7 +18,7 @@ package com.android.server.compat;
import android.annotation.Nullable;
import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledAfter;
+import android.compat.annotation.EnabledSince;
import android.content.pm.ApplicationInfo;
import com.android.internal.compat.CompatibilityChangeInfo;
@@ -43,8 +43,8 @@ public final class CompatChange extends CompatibilityChangeInfo {
* A change ID to be used only in the CTS test for this SystemApi
*/
@ChangeId
- @EnabledAfter(targetSdkVersion = 1234) // Needs to be > test APK targetSdkVersion.
- private static final long CTS_SYSTEM_API_CHANGEID = 149391281; // This is a bug id.
+ @EnabledSince(targetSdkVersion = 1235) // Needs to be > test APK targetSdkVersion.
+ static final long CTS_SYSTEM_API_CHANGEID = 149391281; // This is a bug id.
/**
* Callback listener for when compat changes are updated for a package.
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index e4f52f1fc927..77d5411f5f7f 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -381,6 +381,9 @@ public class PlatformCompat extends IPlatformCompat.Stub {
if (change.getLoggingOnly()) {
return false;
}
+ if (change.getId() == CompatChange.CTS_SYSTEM_API_CHANGEID) {
+ return false;
+ }
if (change.getEnableSinceTargetSdk() > 0) {
if (change.getEnableSinceTargetSdk() < sMinTargetSdk
|| change.getEnableSinceTargetSdk() > sMaxTargetSdk) {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 6a3e7b7a0ecd..b10cd12cdba5 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -227,8 +227,35 @@ public final class DisplayManagerService extends SystemService {
private final CopyOnWriteArrayList<DisplayTransactionListener> mDisplayTransactionListeners =
new CopyOnWriteArrayList<DisplayTransactionListener>();
- // Display power controller.
- private DisplayPowerController mDisplayPowerController;
+ /** All {@link DisplayPowerController}s indexed by {@link LogicalDisplay} ID. */
+ private final SparseArray<DisplayPowerController> mDisplayPowerControllers =
+ new SparseArray<>();
+
+ /** {@link DisplayBlanker} used by all {@link DisplayPowerController}s. */
+ private final DisplayBlanker mDisplayBlanker = new DisplayBlanker() {
+ @Override
+ public void requestDisplayState(int displayId, int state, float brightness) {
+ // The order of operations is important for legacy reasons.
+ if (state == Display.STATE_OFF) {
+ requestGlobalDisplayStateInternal(state, brightness);
+ }
+
+ mDisplayPowerCallbacks.onDisplayStateChange(state);
+
+ if (state != Display.STATE_OFF) {
+ requestGlobalDisplayStateInternal(state, brightness);
+ }
+ }
+ };
+
+ /**
+ * Used to inform {@link com.android.server.power.PowerManagerService} of changes to display
+ * state.
+ */
+ private DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks;
+
+ /** The {@link Handler} used by all {@link DisplayPowerController}s. */
+ private Handler mPowerHandler;
// The overall display state, independent of changes that might influence one
// display or another in particular.
@@ -419,14 +446,16 @@ public final class DisplayManagerService extends SystemService {
final int newUserId = to.getUserIdentifier();
final int userSerial = getUserManager().getUserSerialNumber(newUserId);
synchronized (mSyncRoot) {
+ final DisplayPowerController displayPowerController = mDisplayPowerControllers.get(
+ Display.DEFAULT_DISPLAY);
if (mCurrentUserId != newUserId) {
mCurrentUserId = newUserId;
BrightnessConfiguration config =
mPersistentDataStore.getBrightnessConfiguration(userSerial);
- mDisplayPowerController.setBrightnessConfiguration(config);
+ displayPowerController.setBrightnessConfiguration(config);
handleSettingsChange();
}
- mDisplayPowerController.onSwitchUser(newUserId);
+ displayPowerController.onSwitchUser(newUserId);
}
}
@@ -957,6 +986,7 @@ public final class DisplayManagerService extends SystemService {
recordStableDisplayStatsIfNeededLocked(display);
recordTopInsetLocked(display);
}
+ addDisplayPowerControllerLocked(displayId);
DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
@@ -990,6 +1020,7 @@ public final class DisplayManagerService extends SystemService {
private void handleLogicalDisplayRemovedLocked(@NonNull LogicalDisplay display) {
final int displayId = display.getDisplayIdLocked();
+ mDisplayPowerControllers.delete(displayId);
DisplayManagerGlobal.invalidateLocalDisplayInfoCaches();
sendDisplayEventLocked(displayId, DisplayManagerGlobal.EVENT_DISPLAY_REMOVED);
scheduleTraversalLocked(false);
@@ -1111,7 +1142,7 @@ public final class DisplayManagerService extends SystemService {
mPersistentDataStore.saveIfNeeded();
}
if (userId == mCurrentUserId) {
- mDisplayPowerController.setBrightnessConfiguration(c);
+ mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY).setBrightnessConfiguration(c);
}
}
}
@@ -1143,7 +1174,8 @@ public final class DisplayManagerService extends SystemService {
final int userSerial = getUserManager().getUserSerialNumber(mCurrentUserId);
BrightnessConfiguration config =
mPersistentDataStore.getBrightnessConfiguration(userSerial);
- mDisplayPowerController.setBrightnessConfiguration(config);
+ mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY).setBrightnessConfiguration(
+ config);
}
}
@@ -1350,25 +1382,31 @@ public final class DisplayManagerService extends SystemService {
}
void setAutoBrightnessLoggingEnabled(boolean enabled) {
- if (mDisplayPowerController != null) {
- synchronized (mSyncRoot) {
- mDisplayPowerController.setAutoBrightnessLoggingEnabled(enabled);
+ synchronized (mSyncRoot) {
+ final DisplayPowerController displayPowerController = mDisplayPowerControllers.get(
+ Display.DEFAULT_DISPLAY);
+ if (displayPowerController != null) {
+ displayPowerController.setAutoBrightnessLoggingEnabled(enabled);
}
}
}
void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
- if (mDisplayPowerController != null) {
- synchronized (mSyncRoot) {
- mDisplayPowerController.setDisplayWhiteBalanceLoggingEnabled(enabled);
+ synchronized (mSyncRoot) {
+ final DisplayPowerController displayPowerController = mDisplayPowerControllers.get(
+ Display.DEFAULT_DISPLAY);
+ if (displayPowerController != null) {
+ displayPowerController.setDisplayWhiteBalanceLoggingEnabled(enabled);
}
}
}
void setAmbientColorTemperatureOverride(float cct) {
- if (mDisplayPowerController != null) {
- synchronized (mSyncRoot) {
- mDisplayPowerController.setAmbientColorTemperatureOverride(cct);
+ synchronized (mSyncRoot) {
+ final DisplayPowerController displayPowerController = mDisplayPowerControllers.get(
+ Display.DEFAULT_DISPLAY);
+ if (displayPowerController != null) {
+ displayPowerController.setAmbientColorTemperatureOverride(cct);
}
}
}
@@ -1594,8 +1632,11 @@ public final class DisplayManagerService extends SystemService {
+ ", mWifiDisplayScanRequested=" + callback.mWifiDisplayScanRequested);
}
- if (mDisplayPowerController != null) {
- mDisplayPowerController.dump(pw);
+ final int displayPowerControllerCount = mDisplayPowerControllers.size();
+ pw.println();
+ pw.println("Display Power Controllers: size=" + displayPowerControllerCount);
+ for (int i = 0; i < displayPowerControllerCount; i++) {
+ mDisplayPowerControllers.valueAt(i).dump(pw);
}
pw.println();
@@ -1668,6 +1709,22 @@ public final class DisplayManagerService extends SystemService {
}
}
+ private void initializeDisplayPowerControllersLocked() {
+ mLogicalDisplayMapper.forEachLocked((logicalDisplay) -> addDisplayPowerControllerLocked(
+ logicalDisplay.getDisplayIdLocked()));
+ }
+
+ private void addDisplayPowerControllerLocked(int displayId) {
+ if (mPowerHandler == null) {
+ // initPowerManagement has not yet been called.
+ return;
+ }
+ final DisplayPowerController displayPowerController = new DisplayPowerController(
+ mContext, mDisplayPowerCallbacks, mPowerHandler, mSensorManager,
+ mDisplayBlanker, displayId);
+ mDisplayPowerControllers.append(displayId, displayPowerController);
+ }
+
private final class DisplayManagerHandler extends Handler {
public DisplayManagerHandler(Looper looper) {
super(looper, null, true /*async*/);
@@ -2187,7 +2244,8 @@ public final class DisplayManagerService extends SystemService {
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- return mDisplayPowerController.getBrightnessEvents(userId, hasUsageStats);
+ return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+ .getBrightnessEvents(userId, hasUsageStats);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -2204,7 +2262,8 @@ public final class DisplayManagerService extends SystemService {
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- return mDisplayPowerController.getAmbientBrightnessStats(userId);
+ return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+ .getAmbientBrightnessStats(userId);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -2252,7 +2311,8 @@ public final class DisplayManagerService extends SystemService {
BrightnessConfiguration config =
mPersistentDataStore.getBrightnessConfiguration(userSerial);
if (config == null) {
- config = mDisplayPowerController.getDefaultBrightnessConfiguration();
+ config = mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+ .getDefaultBrightnessConfiguration();
}
return config;
}
@@ -2269,7 +2329,8 @@ public final class DisplayManagerService extends SystemService {
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- return mDisplayPowerController.getDefaultBrightnessConfiguration();
+ return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+ .getDefaultBrightnessConfiguration();
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -2292,7 +2353,8 @@ public final class DisplayManagerService extends SystemService {
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- mDisplayPowerController.setTemporaryBrightness(brightness);
+ mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+ .setTemporaryBrightness(brightness);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -2307,7 +2369,8 @@ public final class DisplayManagerService extends SystemService {
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- mDisplayPowerController.setTemporaryAutoBrightnessAdjustment(adjustment);
+ mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+ .setTemporaryAutoBrightnessAdjustment(adjustment);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -2428,25 +2491,10 @@ public final class DisplayManagerService extends SystemService {
public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager) {
synchronized (mSyncRoot) {
- DisplayBlanker blanker = new DisplayBlanker() {
- @Override
- public void requestDisplayState(int displayId, int state, float brightness) {
- // The order of operations is important for legacy reasons.
- if (state == Display.STATE_OFF) {
- requestGlobalDisplayStateInternal(state, brightness);
- }
-
- callbacks.onDisplayStateChange(state);
-
- if (state != Display.STATE_OFF) {
- requestGlobalDisplayStateInternal(state, brightness);
- }
- }
- };
- mDisplayPowerController = new DisplayPowerController(
- mContext, callbacks, handler, sensorManager, blanker,
- Display.DEFAULT_DISPLAY);
+ mDisplayPowerCallbacks = callbacks;
mSensorManager = sensorManager;
+ mPowerHandler = handler;
+ initializeDisplayPowerControllersLocked();
}
mHandler.sendEmptyMessage(MSG_LOAD_BRIGHTNESS_CONFIGURATION);
@@ -2456,14 +2504,16 @@ public final class DisplayManagerService extends SystemService {
public boolean requestPowerState(DisplayPowerRequest request,
boolean waitForNegativeProximity) {
synchronized (mSyncRoot) {
- return mDisplayPowerController.requestPowerState(request, waitForNegativeProximity);
+ return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+ .requestPowerState(request, waitForNegativeProximity);
}
}
@Override
public boolean isProximitySensorAvailable() {
synchronized (mSyncRoot) {
- return mDisplayPowerController.isProximitySensorAvailable();
+ return mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+ .isProximitySensorAvailable();
}
}
@@ -2552,7 +2602,8 @@ public final class DisplayManagerService extends SystemService {
@Override
public void persistBrightnessTrackerState() {
synchronized (mSyncRoot) {
- mDisplayPowerController.persistBrightnessTrackerState();
+ mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+ .persistBrightnessTrackerState();
}
}
@@ -2584,7 +2635,8 @@ public final class DisplayManagerService extends SystemService {
@Override
public void ignoreProximitySensorUntilChanged() {
- mDisplayPowerController.ignoreProximitySensorUntilChanged();
+ mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY)
+ .ignoreProximitySensorUntilChanged();
}
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 0211876c864d..309271c6addc 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1815,6 +1815,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
public void dump(final PrintWriter pw) {
synchronized (mLock) {
pw.println();
+ pw.println("Display Power Controller:");
+ pw.println(" mDisplayId=" + mDisplayId);
+
+ pw.println();
pw.println("Display Power Controller Locked State:");
pw.println(" mDisplayReadyLocked=" + mDisplayReadyLocked);
pw.println(" mPendingRequestLocked=" + mPendingRequestLocked);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index fe4fd3805994..9dc00792f80b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -495,17 +495,17 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
private byte[] getSupportedShortAudioDescriptorsFromConfig(
List<DeviceConfig> deviceConfig, @AudioCodec int[] audioFormatCodes) {
DeviceConfig deviceConfigToUse = null;
+ String audioDeviceName = SystemProperties.get(
+ Constants.PROPERTY_SYSTEM_AUDIO_MODE_AUDIO_PORT,
+ "VX_AUDIO_DEVICE_IN_HDMI_ARC");
for (DeviceConfig device : deviceConfig) {
- // TODO(amyjojo) use PROPERTY_SYSTEM_AUDIO_MODE_AUDIO_PORT to get the audio device name
- if (device.name.equals("VX_AUDIO_DEVICE_IN_HDMI_ARC")) {
+ if (device.name.equals(audioDeviceName)) {
deviceConfigToUse = device;
break;
}
}
if (deviceConfigToUse == null) {
- // TODO(amyjojo) use PROPERTY_SYSTEM_AUDIO_MODE_AUDIO_PORT to get the audio device name
- Slog.w(TAG, "sadConfig.xml does not have required device info for "
- + "VX_AUDIO_DEVICE_IN_HDMI_ARC");
+ Slog.w(TAG, "sadConfig.xml does not have required device info for " + audioDeviceName);
return new byte[0];
}
HashMap<Integer, byte[]> map = new HashMap<>();
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
index 7d766285bdfa..fe97f701e089 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageValidator.java
@@ -122,7 +122,25 @@ public class HdmiCecMessageValidator {
addValidationInfo(Constants.MESSAGE_RECORD_STATUS,
new RecordStatusInfoValidator(), DEST_DIRECT);
- // TODO: Handle messages for the Timer Programming.
+ addValidationInfo(
+ Constants.MESSAGE_CLEAR_ANALOG_TIMER, new AnalogueTimerValidator(), DEST_DIRECT);
+ addValidationInfo(
+ Constants.MESSAGE_CLEAR_DIGITAL_TIMER, new DigitalTimerValidator(), DEST_DIRECT);
+ addValidationInfo(
+ Constants.MESSAGE_CLEAR_EXTERNAL_TIMER, new ExternalTimerValidator(), DEST_DIRECT);
+ addValidationInfo(
+ Constants.MESSAGE_SET_ANALOG_TIMER, new AnalogueTimerValidator(), DEST_DIRECT);
+ addValidationInfo(
+ Constants.MESSAGE_SET_DIGITAL_TIMER, new DigitalTimerValidator(), DEST_DIRECT);
+ addValidationInfo(
+ Constants.MESSAGE_SET_EXTERNAL_TIMER, new ExternalTimerValidator(), DEST_DIRECT);
+ addValidationInfo(
+ Constants.MESSAGE_SET_TIMER_PROGRAM_TITLE, new AsciiValidator(1, 14), DEST_DIRECT);
+ addValidationInfo(
+ Constants.MESSAGE_TIMER_CLEARED_STATUS,
+ new TimerClearedStatusValidator(),
+ DEST_DIRECT);
+ addValidationInfo(Constants.MESSAGE_TIMER_STATUS, new TimerStatusValidator(), DEST_DIRECT);
// Messages for the System Information.
FixedLengthValidator oneByteValidator = new FixedLengthValidator(1);
@@ -343,6 +361,277 @@ public class HdmiCecMessageValidator {
return true;
}
+ /**
+ * Check if the given value is a valid day of month. A valid value is one which falls within the
+ * range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
+ *
+ * @param value day of month
+ * @return true if the day of month is valid
+ */
+ private boolean isValidDayOfMonth(int value) {
+ return isWithinRange(value, 1, 31);
+ }
+
+ /**
+ * Check if the given value is a valid month of year. A valid value is one which falls within
+ * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
+ *
+ * @param value month of year
+ * @return true if the month of year is valid
+ */
+ private boolean isValidMonthOfYear(int value) {
+ return isWithinRange(value, 1, 12);
+ }
+
+ /**
+ * Check if the given value is a valid hour. A valid value is one which falls within the range
+ * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
+ *
+ * @param value hour
+ * @return true if the hour is valid
+ */
+ private boolean isValidHour(int value) {
+ return isWithinRange(value, 0, 23);
+ }
+
+ /**
+ * Check if the given value is a valid minute. A valid value is one which falls within the range
+ * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
+ *
+ * @param value minute
+ * @return true if the minute is valid
+ */
+ private boolean isValidMinute(int value) {
+ return isWithinRange(value, 0, 59);
+ }
+
+ /**
+ * Check if the given value is a valid duration hours. A valid value is one which falls within
+ * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
+ *
+ * @param value duration hours
+ * @return true if the duration hours is valid
+ */
+ private boolean isValidDurationHours(int value) {
+ return isWithinRange(value, 0, 99);
+ }
+
+ /**
+ * Check if the given value is a valid recording sequence. A valid value is adheres to range
+ * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
+ *
+ * @param value recording sequence
+ * @return true if the given recording sequence is valid
+ */
+ private boolean isValidRecordingSequence(int value) {
+ value = value & 0xFF;
+ // Validate bit 7 is set to zero
+ if ((value & 0x80) != 0x00) {
+ return false;
+ }
+ // Validate than not more than one bit is set
+ return (Integer.bitCount(value) <= 1);
+ }
+
+ /**
+ * Check if the given value is a valid analogue broadcast type. A valid value is one which falls
+ * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section
+ * 17)
+ *
+ * @param value analogue broadcast type
+ * @return true if the analogue broadcast type is valid
+ */
+ private boolean isValidAnalogueBroadcastType(int value) {
+ return isWithinRange(value, 0x00, 0x02);
+ }
+
+ /**
+ * Check if the given value is a valid analogue frequency. A valid value is one which falls
+ * within the range description defined in CEC 1.4 Specification : Operand Descriptions (Section
+ * 17)
+ *
+ * @param value analogue frequency
+ * @return true if the analogue frequency is valid
+ */
+ private boolean isValidAnalogueFrequency(int value) {
+ value = value & 0xFFFF;
+ return (value != 0x000 && value != 0xFFFF);
+ }
+
+ /**
+ * Check if the given value is a valid broadcast system. A valid value is one which falls within
+ * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
+ *
+ * @param value broadcast system
+ * @return true if the broadcast system is valid
+ */
+ private boolean isValidBroadcastSystem(int value) {
+ return isWithinRange(value, 0, 31);
+ }
+
+ /**
+ * Check if the given value is a ARIB type. A valid value is one which falls within the range
+ * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
+ *
+ * @param value Digital Broadcast System
+ * @return true if the Digital Broadcast System is ARIB type
+ */
+ private boolean isAribDbs(int value) {
+ return (value == 0x00 || isWithinRange(value, 0x08, 0x0A));
+ }
+
+ /**
+ * Check if the given value is a ATSC type. A valid value is one which falls within the range
+ * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
+ *
+ * @param value Digital Broadcast System
+ * @return true if the Digital Broadcast System is ATSC type
+ */
+ private boolean isAtscDbs(int value) {
+ return (value == 0x01 || isWithinRange(value, 0x10, 0x12));
+ }
+
+ /**
+ * Check if the given value is a DVB type. A valid value is one which falls within the range
+ * description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
+ *
+ * @param value Digital Broadcast System
+ * @return true if the Digital Broadcast System is DVB type
+ */
+ private boolean isDvbDbs(int value) {
+ return (value == 0x02 || isWithinRange(value, 0x18, 0x1B));
+ }
+
+ /**
+ * Check if the given value is a valid Digital Broadcast System. A valid value is one which
+ * falls within the range description defined in CEC 1.4 Specification : Operand Descriptions
+ * (Section 17)
+ *
+ * @param value Digital Broadcast System
+ * @return true if the Digital Broadcast System is valid
+ */
+ private boolean isValidDigitalBroadcastSystem(int value) {
+ return (isAribDbs(value) || isAtscDbs(value) || isDvbDbs(value));
+ }
+
+ /**
+ * Check if the given value is a valid Digital Service Identification. A valid value is one
+ * which falls within the range description defined in CEC 1.4 Specification : Operand
+ * Descriptions (Section 17)
+ *
+ * @param params Digital Timer Message parameters
+ * @param offset start offset of Digital Service Identification
+ * @return true if the Digital Service Identification is valid
+ */
+ private boolean isValidDigitalServiceIdentification(byte[] params, int offset) {
+ // MSB contains Service Identification Method
+ int serviceIdentificationMethod = params[offset] & 0x80;
+ // Last 7 bits contains Digital Broadcast System
+ int digitalBroadcastSystem = params[offset] & 0x7F;
+ offset = offset + 1;
+ if (serviceIdentificationMethod == 0x00) {
+ // Services identified by Digital IDs
+ if (isAribDbs(digitalBroadcastSystem)) {
+ // Validate ARIB type have 6 byte data
+ return params.length - offset >= 6;
+ } else if (isAtscDbs(digitalBroadcastSystem)) {
+ // Validate ATSC type have 4 byte data
+ return params.length - offset >= 4;
+ } else if (isDvbDbs(digitalBroadcastSystem)) {
+ // Validate DVB type have 6 byte data
+ return params.length - offset >= 6;
+ }
+ } else if (serviceIdentificationMethod == 0x80) {
+ // Services identified by Channel
+ if (isValidDigitalBroadcastSystem(digitalBroadcastSystem)) {
+ // First 6 bits contain Channel Number Format
+ int channelNumberFormat = params[offset] & 0xFC;
+ if (channelNumberFormat == 0x04) {
+ // Validate it contains 1-part Channel Number data (16 bits)
+ return params.length - offset >= 3;
+ } else if (channelNumberFormat == 0x08) {
+ // Validate it contains Major Channel Number and Minor Channel Number (26 bits)
+ return params.length - offset >= 4;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Check if the given value is a valid External Plug. A valid value is one which falls within
+ * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
+ *
+ * @param value External Plug
+ * @return true if the External Plug is valid
+ */
+ private boolean isValidExternalPlug(int value) {
+ return isWithinRange(value, 1, 255);
+ }
+
+ /**
+ * Check if the given value is a valid External Source. A valid value is one which falls within
+ * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
+ *
+ * @param value External Source Specifier
+ * @return true if the External Source is valid
+ */
+ private boolean isValidExternalSource(byte[] params, int offset) {
+ int externalSourceSpecifier = params[offset];
+ offset = offset + 1;
+ if (externalSourceSpecifier == 0x04) {
+ // External Plug
+ return isValidExternalPlug(params[offset]);
+ } else if (externalSourceSpecifier == 0x05) {
+ // External Physical Address
+ // Validate it contains 2 bytes Physical Address
+ if (params.length - offset >= 2) {
+ return isValidPhysicalAddress(params, offset);
+ }
+ }
+ return false;
+ }
+
+ private boolean isValidProgrammedInfo(int programedInfo) {
+ return (isWithinRange(programedInfo, 0x00, 0x0B));
+ }
+
+ private boolean isValidNotProgrammedErrorInfo(int nonProgramedErrorInfo) {
+ return (isWithinRange(nonProgramedErrorInfo, 0x00, 0x0E));
+ }
+
+ private boolean isValidTimerStatusData(byte[] params, int offset) {
+ int programedIndicator = params[offset] & 0x10;
+ boolean durationAvailable = false;
+ if (programedIndicator == 0x10) {
+ // Programmed
+ int programedInfo = params[offset] & 0x0F;
+ if (isValidProgrammedInfo(programedInfo)) {
+ if (programedInfo == 0x09 || programedInfo == 0x0B) {
+ durationAvailable = true;
+ } else {
+ return true;
+ }
+ }
+ } else {
+ // Non programmed
+ int nonProgramedErrorInfo = params[offset] & 0x0F;
+ if (isValidNotProgrammedErrorInfo(nonProgramedErrorInfo)) {
+ if (nonProgramedErrorInfo == 0x0E) {
+ durationAvailable = true;
+ } else {
+ return true;
+ }
+ }
+ }
+ offset = offset + 1;
+ // Duration Available (2 bytes)
+ if (durationAvailable && params.length - offset >= 2) {
+ return (isValidDurationHours(params[offset]) && isValidMinute(params[offset + 1]));
+ }
+ return false;
+ }
+
private class PhysicalAddressValidator implements ParameterValidator {
@Override
public int isValid(byte[] params) {
@@ -472,4 +761,106 @@ public class HdmiCecMessageValidator {
return toErrorCode(isWithinRange(params[0], mMinValue, mMaxValue));
}
}
+
+ /**
+ * Check if the given Analogue Timer message parameters are valid. Valid parameters should
+ * adhere to message description of Analogue Timer defined in CEC 1.4 Specification : Message
+ * Descriptions for Timer Programming Feature (CEC Table 12)
+ */
+ private class AnalogueTimerValidator implements ParameterValidator {
+ @Override
+ public int isValid(byte[] params) {
+ if (params.length < 11) {
+ return ERROR_PARAMETER_SHORT;
+ }
+ return toErrorCode(
+ isValidDayOfMonth(params[0]) // Day of Month
+ && isValidMonthOfYear(params[1]) // Month of Year
+ && isValidHour(params[2]) // Start Time - Hour
+ && isValidMinute(params[3]) // Start Time - Minute
+ && isValidDurationHours(params[4]) // Duration - Duration Hours
+ && isValidMinute(params[5]) // Duration - Minute
+ && isValidRecordingSequence(params[6]) // Recording Sequence
+ && isValidAnalogueBroadcastType(params[7]) // Analogue Broadcast Type
+ && isValidAnalogueFrequency(
+ HdmiUtils.twoBytesToInt(params, 8)) // Analogue Frequency
+ && isValidBroadcastSystem(params[10])); // Broadcast System
+ }
+ }
+
+ /**
+ * Check if the given Digital Timer message parameters are valid. Valid parameters should adhere
+ * to message description of Digital Timer defined in CEC 1.4 Specification : Message
+ * Descriptions for Timer Programming Feature (CEC Table 12)
+ */
+ private class DigitalTimerValidator implements ParameterValidator {
+ @Override
+ public int isValid(byte[] params) {
+ if (params.length < 11) {
+ return ERROR_PARAMETER_SHORT;
+ }
+ return toErrorCode(
+ isValidDayOfMonth(params[0]) // Day of Month
+ && isValidMonthOfYear(params[1]) // Month of Year
+ && isValidHour(params[2]) // Start Time - Hour
+ && isValidMinute(params[3]) // Start Time - Minute
+ && isValidDurationHours(params[4]) // Duration - Duration Hours
+ && isValidMinute(params[5]) // Duration - Minute
+ && isValidRecordingSequence(params[6]) // Recording Sequence
+ && isValidDigitalServiceIdentification(
+ params, 7)); // Digital Service Identification
+ }
+ }
+
+ /**
+ * Check if the given External Timer message parameters are valid. Valid parameters should
+ * adhere to message description of External Timer defined in CEC 1.4 Specification : Message
+ * Descriptions for Timer Programming Feature (CEC Table 12)
+ */
+ private class ExternalTimerValidator implements ParameterValidator {
+ @Override
+ public int isValid(byte[] params) {
+ if (params.length < 9) {
+ return ERROR_PARAMETER_SHORT;
+ }
+ return toErrorCode(
+ isValidDayOfMonth(params[0]) // Day of Month
+ && isValidMonthOfYear(params[1]) // Month of Year
+ && isValidHour(params[2]) // Start Time - Hour
+ && isValidMinute(params[3]) // Start Time - Minute
+ && isValidDurationHours(params[4]) // Duration - Duration Hours
+ && isValidMinute(params[5]) // Duration - Minute
+ && isValidRecordingSequence(params[6]) // Recording Sequence
+ && isValidExternalSource(params, 7)); // External Source
+ }
+ }
+
+ /**
+ * Check if the given timer cleared status parameter is valid. A valid parameter should lie
+ * within the range description defined in CEC 1.4 Specification : Operand Descriptions
+ * (Section 17)
+ */
+ private class TimerClearedStatusValidator implements ParameterValidator {
+ @Override
+ public int isValid(byte[] params) {
+ if (params.length < 1) {
+ return ERROR_PARAMETER_SHORT;
+ }
+ return toErrorCode(isWithinRange(params[0], 0x00, 0x02) || (params[0] & 0xFF) == 0x80);
+ }
+ }
+
+ /**
+ * Check if the given timer status data parameter is valid. A valid parameter should lie within
+ * the range description defined in CEC 1.4 Specification : Operand Descriptions (Section 17)
+ */
+ private class TimerStatusValidator implements ParameterValidator {
+ @Override
+ public int isValid(byte[] params) {
+ if (params.length < 1) {
+ return ERROR_PARAMETER_SHORT;
+ }
+ return toErrorCode(isValidTimerStatusData(params, 0));
+ }
+ }
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 16a4b7250598..683a4b67cc63 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -15,6 +15,7 @@
package com.android.server.inputmethod;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.server.inputmethod.InputMethodManagerServiceProto.ACCESSIBILITY_REQUESTING_NO_SOFT_KEYBOARD;
import static android.server.inputmethod.InputMethodManagerServiceProto.BACK_DISPOSITION;
import static android.server.inputmethod.InputMethodManagerServiceProto.BOUND_TO_METHOD;
@@ -110,6 +111,7 @@ import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
@@ -234,7 +236,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
static final int MSG_SET_ACTIVE = 3020;
static final int MSG_SET_INTERACTIVE = 3030;
static final int MSG_REPORT_FULLSCREEN_MODE = 3045;
- static final int MSG_REPORT_PRE_RENDERED = 3060;
static final int MSG_APPLY_IME_VISIBILITY = 3070;
static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000;
@@ -317,8 +318,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private static final class DebugFlags {
static final DebugFlag FLAG_OPTIMIZE_START_INPUT =
new DebugFlag("debug.optimize_startinput", false);
- static final DebugFlag FLAG_PRE_RENDER_IME_VIEWS =
- new DebugFlag("persist.pre_render_ime_views", false);
}
@UserIdInt
@@ -448,10 +447,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
final ClientDeathRecipient clientDeathRecipient;
boolean sessionRequested;
- // Determines if IMEs should be pre-rendered.
- // DebugFlag can be flipped anytime. This flag is kept per-client to maintain behavior
- // through the life of the current client.
- boolean shouldPreRenderIme;
SessionState curSession;
@Override
@@ -3113,6 +3108,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@Override
public boolean showSoftInput(IInputMethodClient client, IBinder windowToken, int flags,
ResultReceiver resultReceiver) {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showSoftInput");
int uid = Binder.getCallingUid();
synchronized (mMethodMap) {
if (!calledFromValidUserLocked()) {
@@ -3140,6 +3136,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
SoftInputShowHideReason.SHOW_SOFT_INPUT);
} finally {
Binder.restoreCallingIdentity(ident);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
}
@@ -3232,6 +3229,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
final long ident = Binder.clearCallingIdentity();
try {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideSoftInput");
if (mCurClient == null || client == null
|| mCurClient.client.asBinder() != client.asBinder()) {
// We need to check if this is the current client with
@@ -3255,15 +3253,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
SoftInputShowHideReason.HIDE_SOFT_INPUT);
} finally {
Binder.restoreCallingIdentity(ident);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
}
boolean hideCurrentInputLocked(IBinder windowToken, int flags, ResultReceiver resultReceiver,
@SoftInputShowHideReason int reason) {
- if (mCurClient == null || mCurClient.curSession == null) {
- return false;
- }
if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
&& (mShowExplicitlyRequested || mShowForced)) {
if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
@@ -3320,43 +3316,52 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
Slog.e(TAG, "windowToken cannot be null.");
return InputBindResult.NULL;
}
- final int callingUserId = UserHandle.getCallingUserId();
- final int userId;
- if (attribute != null && attribute.targetInputMethodUser != null
- && attribute.targetInputMethodUser.getIdentifier() != callingUserId) {
- mContext.enforceCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
- "Using EditorInfo.targetInputMethodUser requires INTERACT_ACROSS_USERS_FULL.");
- userId = attribute.targetInputMethodUser.getIdentifier();
- if (!mUserManagerInternal.isUserRunning(userId)) {
- // There is a chance that we hit here because of race condition. Let's just return
- // an error code instead of crashing the caller process, which at least has
- // INTERACT_ACROSS_USERS_FULL permission thus is likely to be an important process.
- Slog.e(TAG, "User #" + userId + " is not running.");
- return InputBindResult.INVALID_USER;
+ try {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
+ "IMMS.startInputOrWindowGainedFocus");
+ final int callingUserId = UserHandle.getCallingUserId();
+ final int userId;
+ if (attribute != null && attribute.targetInputMethodUser != null
+ && attribute.targetInputMethodUser.getIdentifier() != callingUserId) {
+ mContext.enforceCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ "Using EditorInfo.targetInputMethodUser requires"
+ + " INTERACT_ACROSS_USERS_FULL.");
+ userId = attribute.targetInputMethodUser.getIdentifier();
+ if (!mUserManagerInternal.isUserRunning(userId)) {
+ // There is a chance that we hit here because of race condition. Let's just
+ // return an error code instead of crashing the caller process, which at least
+ // has INTERACT_ACROSS_USERS_FULL permission thus is likely to be an important
+ // process.
+ Slog.e(TAG, "User #" + userId + " is not running.");
+ return InputBindResult.INVALID_USER;
+ }
+ } else {
+ userId = callingUserId;
}
- } else {
- userId = callingUserId;
- }
- final InputBindResult result;
- synchronized (mMethodMap) {
- final long ident = Binder.clearCallingIdentity();
- try {
- result = startInputOrWindowGainedFocusInternalLocked(startInputReason, client,
- windowToken, startInputFlags, softInputMode, windowFlags, attribute,
- inputContext, missingMethods, unverifiedTargetSdkVersion, userId);
- } finally {
- Binder.restoreCallingIdentity(ident);
+ final InputBindResult result;
+ synchronized (mMethodMap) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ result = startInputOrWindowGainedFocusInternalLocked(startInputReason, client,
+ windowToken, startInputFlags, softInputMode, windowFlags, attribute,
+ inputContext, missingMethods, unverifiedTargetSdkVersion, userId);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
+ if (result == null) {
+ // This must never happen, but just in case.
+ Slog.wtf(TAG, "InputBindResult is @NonNull. startInputReason="
+ + InputMethodDebug.startInputReasonToString(startInputReason)
+ + " windowFlags=#" + Integer.toHexString(windowFlags)
+ + " editorInfo=" + attribute);
+ return InputBindResult.NULL;
+ }
+
+ return result;
+ } finally {
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
- if (result == null) {
- // This must never happen, but just in case.
- Slog.wtf(TAG, "InputBindResult is @NonNull. startInputReason="
- + InputMethodDebug.startInputReasonToString(startInputReason)
- + " windowFlags=#" + Integer.toHexString(windowFlags)
- + " editorInfo=" + attribute);
- return InputBindResult.NULL;
- }
- return result;
}
@NonNull
@@ -3440,14 +3445,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return InputBindResult.USER_SWITCHING;
}
- // Main feature flag that overrides other conditions and forces IME preRendering.
- if (DEBUG) {
- Slog.v(TAG, "IME PreRendering main flag: "
- + DebugFlags.FLAG_PRE_RENDER_IME_VIEWS.value() + ", LowRam: " + mIsLowRam);
- }
- // pre-rendering not supported on low-ram devices.
- cs.shouldPreRenderIme = DebugFlags.FLAG_PRE_RENDER_IME_VIEWS.value() && !mIsLowRam;
-
final boolean sameWindowFocused = mCurFocusedWindow == windowToken;
final boolean isTextEditor = (startInputFlags & StartInputFlags.IS_TEXT_EDITOR) != 0;
final boolean startInputByWinGainedFocus =
@@ -4141,20 +4138,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
@BinderThread
- private void reportPreRendered(IBinder token, EditorInfo info) {
- synchronized (mMethodMap) {
- if (!calledWithValidTokenLocked(token)) {
- return;
- }
- if (mCurClient != null && mCurClient.client != null) {
- executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(
- MSG_REPORT_PRE_RENDERED, info, mCurClient));
- }
- }
- }
-
- @BinderThread
private void applyImeVisibility(IBinder token, IBinder windowToken, boolean setVisible) {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.applyImeVisibility");
synchronized (mMethodMap) {
if (!calledWithValidTokenLocked(token)) {
return;
@@ -4176,6 +4161,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mWindowManagerInternal.showImePostLayout(mShowRequestWindowMap.get(windowToken));
}
}
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
private void setInputMethodWithSubtypeIdLocked(IBinder token, String id, int subtypeId) {
@@ -4203,6 +4189,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@BinderThread
private void hideMySoftInput(@NonNull IBinder token, int flags) {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideMySoftInput");
synchronized (mMethodMap) {
if (!calledWithValidTokenLocked(token)) {
return;
@@ -4217,10 +4204,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
Binder.restoreCallingIdentity(ident);
}
}
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@BinderThread
private void showMySoftInput(@NonNull IBinder token, int flags) {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showMySoftInput");
synchronized (mMethodMap) {
if (!calledWithValidTokenLocked(token)) {
return;
@@ -4233,6 +4222,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
Binder.restoreCallingIdentity(ident);
}
}
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
void setEnabledSessionInMainThread(SessionState session) {
@@ -4430,7 +4420,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
try {
setEnabledSessionInMainThread(session);
session.method.startInput(startInputToken, inputContext, missingMethods,
- editorInfo, restarting, session.client.shouldPreRenderIme);
+ editorInfo, restarting);
} catch (RemoteException e) {
}
args.recycle();
@@ -4488,20 +4478,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
return true;
}
- case MSG_REPORT_PRE_RENDERED: {
- args = (SomeArgs) msg.obj;
- final EditorInfo info = (EditorInfo) args.arg1;
- final ClientState clientState = (ClientState) args.arg2;
- try {
- clientState.client.reportPreRendered(info);
- } catch (RemoteException e) {
- Slog.w(TAG, "Got RemoteException sending "
- + "reportPreRendered(" + info + ") notification to pid="
- + clientState.pid + " uid=" + clientState.uid);
- }
- args.recycle();
- return true;
- }
case MSG_APPLY_IME_VISIBILITY: {
final boolean setVisible = msg.arg1 != 0;
final ClientState clientState = (ClientState) msg.obj;
@@ -5347,7 +5323,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@ShellCommandResult
private int refreshDebugProperties() {
DebugFlags.FLAG_OPTIMIZE_START_INPUT.refresh();
- DebugFlags.FLAG_PRE_RENDER_IME_VIEWS.refresh();
return ShellCommandResult.SUCCESS;
}
@@ -5822,12 +5797,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@BinderThread
@Override
- public void reportPreRendered(EditorInfo info) {
- mImms.reportPreRendered(mToken, info);
- }
-
- @BinderThread
- @Override
public void applyImeVisibility(IBinder windowToken, boolean setVisible) {
mImms.applyImeVisibility(mToken, windowToken, setVisible);
}
diff --git a/services/core/java/com/android/server/location/ContextHubServiceUtil.java b/services/core/java/com/android/server/location/ContextHubServiceUtil.java
index 76cd9ceaf7c4..9145eca9ad6f 100644
--- a/services/core/java/com/android/server/location/ContextHubServiceUtil.java
+++ b/services/core/java/com/android/server/location/ContextHubServiceUtil.java
@@ -30,12 +30,16 @@ import android.hardware.location.ContextHubTransaction;
import android.hardware.location.NanoAppBinary;
import android.hardware.location.NanoAppMessage;
import android.hardware.location.NanoAppState;
+import android.os.Binder;
+import android.os.Build;
import android.util.Log;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* A class encapsulating helper functions used by the ContextHubService class
@@ -45,6 +49,9 @@ import java.util.List;
private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
private static final String CONTEXT_HUB_PERMISSION = Manifest.permission.ACCESS_CONTEXT_HUB;
+ // A set of packages that have already been warned regarding the ACCESS_CONTEXT_HUB permission.
+ private static final Set<String> PERMISSION_WARNED_PACKAGES = new HashSet<String>();
+
/**
* Creates a ConcurrentHashMap of the Context Hub ID to the ContextHubInfo object given an
* ArrayList of HIDL ContextHub objects.
@@ -95,6 +102,7 @@ import java.util.List;
/**
* Creates a primitive integer array given a Collection<Integer>.
+ *
* @param collection the collection to iterate
* @return the primitive integer array
*/
@@ -200,10 +208,25 @@ import java.util.List;
*/
/* package */
static void checkPermissions(Context context) {
- if (context.checkCallingPermission(HARDWARE_PERMISSION) != PERMISSION_GRANTED
- && context.checkCallingPermission(CONTEXT_HUB_PERMISSION) != PERMISSION_GRANTED) {
+ boolean hasLocationHardwarePermission = (context.checkCallingPermission(HARDWARE_PERMISSION)
+ == PERMISSION_GRANTED);
+ boolean hasAccessContextHubPermission = (context.checkCallingPermission(
+ CONTEXT_HUB_PERMISSION) == PERMISSION_GRANTED);
+
+ if (!hasLocationHardwarePermission && !hasAccessContextHubPermission) {
throw new SecurityException(
- "LOCATION_HARDWARE or ACCESS_CONTEXT_HUB permission required to use Context Hub");
+ "LOCATION_HARDWARE or ACCESS_CONTEXT_HUB permission required to use Context "
+ + "Hub");
+ }
+
+ if (!hasAccessContextHubPermission && !Build.IS_USER) {
+ String pkgName = context.getPackageManager().getNameForUid(Binder.getCallingUid());
+ if (!PERMISSION_WARNED_PACKAGES.contains(pkgName)) {
+ Log.w(TAG, pkgName
+ + ": please use the ACCESS_CONTEXT_HUB permission rather than "
+ + "LOCATION_HARDWARE (will be removed for Context Hub APIs in T)");
+ PERMISSION_WARNED_PACKAGES.add(pkgName);
+ }
}
}
diff --git a/services/core/java/com/android/server/location/LocationProviderManager.java b/services/core/java/com/android/server/location/LocationProviderManager.java
index f25c65192066..f8d1195be7fd 100644
--- a/services/core/java/com/android/server/location/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/LocationProviderManager.java
@@ -38,6 +38,7 @@ import static com.android.server.location.LocationPermissions.PERMISSION_NONE;
import static java.lang.Math.max;
import static java.lang.Math.min;
+import android.annotation.IntDef;
import android.annotation.Nullable;
import android.app.AlarmManager.OnAlarmListener;
import android.app.PendingIntent;
@@ -107,6 +108,8 @@ import com.android.server.location.util.UserInfoHelper;
import com.android.server.location.util.UserInfoHelper.UserListener;
import java.io.FileDescriptor;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -142,6 +145,14 @@ class LocationProviderManager extends
// will just be scheduled immediately
private static final long MIN_REQUEST_DELAY_MS = 30 * 1000;
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({STATE_STARTED, STATE_STOPPING, STATE_STOPPED})
+ private @interface State {}
+
+ private static final int STATE_STARTED = 0;
+ private static final int STATE_STOPPING = 1;
+ private static final int STATE_STOPPED = 2;
+
protected interface LocationTransport {
void deliverOnLocationChanged(Location location, @Nullable Runnable onCompleteCallback)
@@ -1082,7 +1093,7 @@ class LocationProviderManager extends
protected final Context mContext;
@GuardedBy("mLock")
- private boolean mStarted;
+ private @State int mState;
// maps of user id to value
@GuardedBy("mLock")
@@ -1148,7 +1159,7 @@ class LocationProviderManager extends
mContext = context;
mName = Objects.requireNonNull(name);
mPassiveManager = passiveManager;
- mStarted = false;
+ mState = STATE_STOPPED;
mEnabled = new SparseBooleanArray(2);
mLastLocations = new SparseArray<>(2);
@@ -1180,7 +1191,8 @@ class LocationProviderManager extends
public void startManager() {
synchronized (mLock) {
- mStarted = true;
+ Preconditions.checkState(mState == STATE_STOPPED);
+ mState = STATE_STARTED;
mUserHelper.addListener(mUserChangedListener);
mSettingsHelper.addOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
@@ -1197,6 +1209,9 @@ class LocationProviderManager extends
public void stopManager() {
synchronized (mLock) {
+ Preconditions.checkState(mState == STATE_STARTED);
+ mState = STATE_STOPPING;
+
final long identity = Binder.clearCallingIdentity();
try {
onEnabledChanged(UserHandle.USER_ALL);
@@ -1205,11 +1220,19 @@ class LocationProviderManager extends
Binder.restoreCallingIdentity(identity);
}
+ setRealProvider(null);
+ setMockProvider(null);
+
mUserHelper.removeListener(mUserChangedListener);
mSettingsHelper.removeOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
+ // if external entities are registering listeners it's their responsibility to
+ // unregister them before stopManager() is called
Preconditions.checkState(mEnabledListeners.isEmpty());
- mStarted = false;
+
+ mEnabled.clear();
+ mLastLocations.clear();
+ mState = STATE_STOPPED;
}
}
@@ -1252,21 +1275,21 @@ class LocationProviderManager extends
public void addEnabledListener(ProviderEnabledListener listener) {
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
mEnabledListeners.add(listener);
}
}
public void removeEnabledListener(ProviderEnabledListener listener) {
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
mEnabledListeners.remove(listener);
}
}
- public void setRealProvider(AbstractLocationProvider provider) {
+ public void setRealProvider(@Nullable AbstractLocationProvider provider) {
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
final long identity = Binder.clearCallingIdentity();
try {
@@ -1279,7 +1302,7 @@ class LocationProviderManager extends
public void setMockProvider(@Nullable MockProvider provider) {
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
mLocationEventLog.logProviderMocked(mName, provider != null);
@@ -1408,7 +1431,7 @@ class LocationProviderManager extends
Location location;
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
LastLocation lastLocation = mLastLocations.get(userId);
if (lastLocation == null) {
location = null;
@@ -1430,7 +1453,7 @@ class LocationProviderManager extends
public void injectLastLocation(Location location, int userId) {
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
if (getLastLocationUnsafe(userId, PERMISSION_FINE, false, Long.MAX_VALUE) == null) {
setLastLocation(location, userId);
}
@@ -1478,7 +1501,7 @@ class LocationProviderManager extends
permissionLevel);
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
final long ident = Binder.clearCallingIdentity();
try {
putRegistration(callback.asBinder(), registration);
@@ -1520,7 +1543,7 @@ class LocationProviderManager extends
permissionLevel);
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
final long ident = Binder.clearCallingIdentity();
try {
putRegistration(listener.asBinder(), registration);
@@ -1539,7 +1562,7 @@ class LocationProviderManager extends
permissionLevel);
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
final long identity = Binder.clearCallingIdentity();
try {
putRegistration(pendingIntent, registration);
@@ -1551,7 +1574,7 @@ class LocationProviderManager extends
public void unregisterLocationRequest(ILocationListener listener) {
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
final long identity = Binder.clearCallingIdentity();
try {
removeRegistration(listener.asBinder());
@@ -1563,7 +1586,7 @@ class LocationProviderManager extends
public void unregisterLocationRequest(PendingIntent pendingIntent) {
synchronized (mLock) {
- Preconditions.checkState(mStarted);
+ Preconditions.checkState(mState != STATE_STOPPED);
final long identity = Binder.clearCallingIdentity();
try {
removeRegistration(pendingIntent);
@@ -1890,6 +1913,10 @@ class LocationProviderManager extends
private void onUserChanged(int userId, int change) {
synchronized (mLock) {
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+
switch (change) {
case UserListener.CURRENT_USER_CHANGED:
updateRegistrations(
@@ -1907,6 +1934,10 @@ class LocationProviderManager extends
private void onLocationEnabledChanged(int userId) {
synchronized (mLock) {
+ if (mState == STATE_STOPPED) {
+ return;
+ }
+
onEnabledChanged(userId);
}
}
@@ -2105,7 +2136,7 @@ class LocationProviderManager extends
Preconditions.checkArgument(userId >= 0);
- boolean enabled = mStarted
+ boolean enabled = mState == STATE_STARTED
&& mProvider.getState().allowed
&& mSettingsHelper.isLocationEnabled(userId);
diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index e25e605cf7d2..0c1e91d9bf24 100644
--- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -583,8 +583,10 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
mDownloadPsdsWakeLock.setReferenceCounted(true);
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
- mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP), 0);
- mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT), 0);
+ mWakeupIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_WAKEUP),
+ PendingIntent.FLAG_IMMUTABLE);
+ mTimeoutIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ALARM_TIMEOUT),
+ PendingIntent.FLAG_IMMUTABLE);
// App ops service to keep track of who is accessing the GPS
mAppOps = mContext.getSystemService(AppOpsManager.class);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4f4f3c64b1b4..1516cded50a6 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3526,6 +3526,20 @@ public class NotificationManagerService extends SystemService {
}
@Override
+ public void unlockNotificationChannel(String pkg, int uid, String channelId) {
+ checkCallerIsSystemOrSystemUiOrShell("Caller not system or sysui or shell");
+ mPreferencesHelper.unlockNotificationChannelImportance(pkg, uid, channelId);
+ handleSavePolicyFile();
+ }
+
+ @Override
+ public void unlockAllNotificationChannels() {
+ checkCallerIsSystem();
+ mPreferencesHelper.unlockAllNotificationChannels();
+ handleSavePolicyFile();
+ }
+
+ @Override
public ParceledListSlice<NotificationChannel> getNotificationChannelsForPackage(String pkg,
int uid, boolean includeDeleted) {
enforceSystemOrSystemUI("getNotificationChannelsForPackage");
@@ -5498,6 +5512,8 @@ public class NotificationManagerService extends SystemService {
pw.println(" mCallState=" + callStateToString(mCallState));
pw.println(" mSystemReady=" + mSystemReady);
pw.println(" mMaxPackageEnqueueRate=" + mMaxPackageEnqueueRate);
+ pw.println(" hideSilentStatusBar="
+ + mPreferencesHelper.shouldHideSilentStatusIcons());
}
pw.println(" mArchive=" + mArchive.toString());
Iterator<Pair<StatusBarNotification, Integer>> iter = mArchive.descendingIterator();
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 77713a60db4d..2f990c62305f 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -18,6 +18,7 @@ package com.android.server.notification;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.NotificationChannel.PLACEHOLDER_CONVERSATION_ID;
+import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_NONE;
@@ -955,6 +956,23 @@ public class PreferencesHelper implements RankingConfig {
channel.unlockFields(channel.getUserLockedFields());
}
+ void unlockNotificationChannelImportance(String pkg, int uid, String updatedChannelId) {
+ Objects.requireNonNull(updatedChannelId);
+ synchronized (mPackagePreferences) {
+ PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
+ if (r == null) {
+ throw new IllegalArgumentException("Invalid package");
+ }
+
+ NotificationChannel channel = r.channels.get(updatedChannelId);
+ if (channel == null || channel.isDeleted()) {
+ throw new IllegalArgumentException("Channel does not exist");
+ }
+ channel.unlockFields(USER_LOCKED_IMPORTANCE);
+ }
+ }
+
+
@Override
public void updateNotificationChannel(String pkg, int uid, NotificationChannel updatedChannel,
boolean fromUser) {
@@ -2389,6 +2407,18 @@ public class PreferencesHelper implements RankingConfig {
return mBadgingEnabled.get(userId, DEFAULT_SHOW_BADGE);
}
+ public void unlockAllNotificationChannels() {
+ synchronized (mPackagePreferences) {
+ final int numPackagePreferences = mPackagePreferences.size();
+ for (int i = 0; i < numPackagePreferences; i++) {
+ final PackagePreferences r = mPackagePreferences.valueAt(i);
+ for (NotificationChannel channel : r.channels.values()) {
+ channel.unlockFields(USER_LOCKED_IMPORTANCE);
+ }
+ }
+ }
+ }
+
private void updateConfig() {
mRankingHandler.requestSort();
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index b679c0fbab83..dd338655732b 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -1563,7 +1563,7 @@ public class LauncherAppsService extends SystemService {
continue;
}
try {
- listener.onPackageProgressChanged(mUser, mPackageName, progress);
+ listener.onPackageLoadingProgressChanged(mUser, mPackageName, progress);
} catch (RemoteException re) {
Slog.d(TAG, "Callback failed ", re);
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 5d2928e1a854..57b80eab61e6 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -3058,6 +3058,31 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
+ /**
+ * Cleans up the relevant stored files and information of all child sessions.
+ * <p>Cleaning up the stored files and session information is necessary for
+ * preventing the orphan children sessions.
+ * <ol>
+ * <li>To call {@link #destroyInternal()} cleans up the stored files.</li>
+ * <li>To call {@link #dispatchSessionFinished(int, String, Bundle)} to trigger the
+ * procedure to clean up the information in PackageInstallerService.</li>
+ * </ol></p>
+ */
+ private void maybeCleanUpChildSessions() {
+ if (!isMultiPackage()) {
+ return;
+ }
+
+ final List<PackageInstallerSession> childSessions = getChildSessions();
+ final int size = childSessions.size();
+ for (int i = 0; i < size; ++i) {
+ final PackageInstallerSession session = childSessions.get(i);
+ session.destroyInternal();
+ session.dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned"
+ + " because the parent session is abandoned", null);
+ }
+ }
+
private void abandonNonStaged() {
synchronized (mLock) {
assertCallerIsOwnerOrRootLocked();
@@ -3068,6 +3093,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
destroyInternal();
}
dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null);
+ maybeCleanUpChildSessions();
}
private void abandonStaged() {
@@ -3092,6 +3118,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
cleanStageDir(childSessions);
destroyInternal();
dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null);
+ maybeCleanUpChildSessions();
};
if (mInPreRebootVerification) {
// Pre-reboot verification is ongoing. It is not safe to clean up the session yet.
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index cdd347beba0a..b3f49ade35c8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2737,7 +2737,7 @@ public class PackageManagerService extends IPackageManager.Stub
context, lock, installer, installLock, new PackageAbiHelperImpl(),
backgroundHandler,
(i, pm) -> new ComponentResolver(i.getUserManagerService(), pm.mPmInternal, lock),
- (i, pm) -> PermissionManagerService.create(context, lock),
+ (i, pm) -> PermissionManagerService.create(context),
(i, pm) -> new UserManagerService(context, pm,
new UserDataPreparer(installer, installLock, context, onlyCore),
lock),
@@ -19606,7 +19606,7 @@ public class PackageManagerService extends IPackageManager.Stub
ps.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId);
}
- mSettings.writeRuntimePermissionsForUserLPr(userId, false);
+ writeRuntimePermissionsForUserLPrTEMP(userId, false);
}
// Regardless of writeSettings we need to ensure that this restriction
// state propagation is persisted
@@ -25752,7 +25752,7 @@ public class PackageManagerService extends IPackageManager.Stub
public void writePermissionSettings(int[] userIds, boolean async) {
synchronized (mLock) {
for (int userId : userIds) {
- mSettings.writeRuntimePermissionsForUserLPr(userId, !async);
+ writeRuntimePermissionsForUserLPrTEMP(userId, !async);
}
}
}
@@ -26401,6 +26401,17 @@ public class PackageManagerService extends IPackageManager.Stub
mSettings.writeLPr();
}
+ /**
+ * Temporary method that wraps mSettings.writeRuntimePermissionsForUserLPr() and calls
+ * mPermissionManager.writeLegacyPermissionStateTEMP() beforehand.
+ *
+ * TODO(zhanghai): This should be removed once we finish migration of permission storage.
+ */
+ private void writeRuntimePermissionsForUserLPrTEMP(@UserIdInt int userId, boolean async) {
+ mPermissionManager.writeLegacyPermissionStateTEMP();
+ mSettings.writeRuntimePermissionsForUserLPr(userId, async);
+ }
+
@Override
public IBinder getHoldLockToken() {
if (!Build.IS_DEBUGGABLE) {
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index e99e301e6da1..3fcf02cd9bd8 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -674,20 +674,6 @@ public class StagingManager {
return;
}
- if ((session.params.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
- // If rollback is available for this session, notify the rollback
- // manager of the apk session so it can properly enable rollback.
- final RollbackManagerInternal rm =
- LocalServices.getService(RollbackManagerInternal.class);
- try {
- // TODO(b/136257624): extra apk session id in rollback is now redundant.
- rm.notifyStagedApkSession(session.sessionId, session.sessionId);
- } catch (RuntimeException re) {
- Slog.e(TAG, "Failed to notifyStagedApkSession for session: "
- + session.sessionId, re);
- }
- }
-
final LocalIntentReceiverSync receiver = new LocalIntentReceiverSync();
session.installStagedSession(receiver.getIntentSender());
final Intent result = receiver.getResult();
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 7f29cd94bfca..24082b86132c 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -3993,7 +3993,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public @UserManager.RemoveResult int removeUserOrSetEphemeral(@UserIdInt int userId) {
Slog.i(LOG_TAG, "removeUserOrSetEphemeral u" + userId);
- checkManageUsersPermission("Only the system can remove users");
+ checkManageOrCreateUsersPermission("Only the system can remove users");
final String restriction = getUserRemovalRestriction(userId);
if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(restriction, false)) {
Slog.w(LOG_TAG, "Cannot remove user. " + restriction + " is enabled.");
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 300206a679a2..84f98239a39c 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -208,7 +208,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
/** Lock to protect internal data access */
- private final Object mLock;
+ private final Object mLock = new Object();
/** Internal connection to the package manager */
private final PackageManagerInternal mPackageManagerInt;
@@ -271,13 +271,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private PermissionPolicyInternal mPermissionPolicyInternal;
/**
- * For each foreground/background permission the mapping:
- * Background permission -> foreground permissions
- */
- @GuardedBy("mLock")
- private ArrayMap<String, List<String>> mBackgroundPermissions;
-
- /**
* A permission backup might contain apps that are not installed. In this case we delay the
* restoration until the app is installed.
*
@@ -295,7 +288,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@GuardedBy("mLock")
private CheckPermissionDelegate mCheckPermissionDelegate;
- @GuardedBy("mLock")
+ @NonNull
private final OnPermissionChangeListeners mOnPermissionChangeListeners;
@GuardedBy("mLock")
@@ -372,14 +365,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
};
- PermissionManagerService(Context context,
- @NonNull Object externalLock) {
- this(context, externalLock, new Injector(context));
+ PermissionManagerService(@NonNull Context context) {
+ this(context, new Injector(context));
}
@VisibleForTesting
- PermissionManagerService(Context context, @NonNull Object externalLock,
- @NonNull Injector injector) {
+ PermissionManagerService(@NonNull Context context, @NonNull Injector injector) {
mInjector = injector;
// The package info cache is the cache for package and permission information.
// Disable the package info and package permission caches locally but leave the
@@ -388,7 +379,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
mInjector.disablePackageNamePermissionCache();
mContext = context;
- mLock = externalLock;
mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
mUserManagerInt = LocalServices.getService(UserManagerInternal.class);
mAppOpsManager = context.getSystemService(AppOpsManager.class);
@@ -447,8 +437,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
* NOTE: The external lock is temporary and should be removed. This needs to be a
* lock created by the permission manager itself.
*/
- public static PermissionManagerServiceInternal create(Context context,
- @NonNull Object externalLock) {
+ @NonNull
+ public static PermissionManagerServiceInternal create(@NonNull Context context) {
final PermissionManagerServiceInternal permMgrInt =
LocalServices.getService(PermissionManagerServiceInternal.class);
if (permMgrInt != null) {
@@ -457,8 +447,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
PermissionManagerService permissionService =
(PermissionManagerService) ServiceManager.getService("permissionmgr");
if (permissionService == null) {
- permissionService =
- new PermissionManagerService(context, externalLock);
+ permissionService = new PermissionManagerService(context);
ServiceManager.addService("permissionmgr", permissionService);
}
return LocalServices.getService(PermissionManagerServiceInternal.class);
@@ -959,6 +948,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return PackageManager.PERMISSION_DENIED;
}
+ @GuardedBy("mLock")
private boolean checkSinglePermissionInternalLocked(@NonNull UidPermissionState uidState,
@NonNull String permissionName, boolean isInstantApp) {
if (!uidState.isPermissionGranted(permissionName)) {
@@ -1029,6 +1019,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return PackageManager.PERMISSION_DENIED;
}
+ @GuardedBy("mLock")
private boolean checkSingleUidPermissionInternalLocked(int uid,
@NonNull String permissionName) {
ArraySet<String> permissions = mSystemPermissions.get(uid);
@@ -1094,9 +1085,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS,
"addOnPermissionsChangeListener");
- synchronized (mLock) {
- mOnPermissionChangeListeners.addListenerLocked(listener);
- }
+ mOnPermissionChangeListeners.addListener(listener);
}
@Override
@@ -1104,9 +1093,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (mPackageManagerInt.getInstantAppPackageName(Binder.getCallingUid()) != null) {
throw new SecurityException("Instant applications don't have access to this method");
}
- synchronized (mLock) {
- mOnPermissionChangeListeners.removeListenerLocked(listener);
- }
+ mOnPermissionChangeListeners.removeListener(listener);
}
@Override
@@ -3068,6 +3055,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
*
* @return The updated value of the {@code updatedUserIds} parameter
*/
+ @GuardedBy("mLock")
private @NonNull int[] revokePermissionsNoLongerImplicitLocked(@NonNull UidPermissionState ps,
@NonNull AndroidPackage pkg, int userId, @NonNull int[] updatedUserIds) {
String pkgName = pkg.getPackageName();
@@ -3120,6 +3108,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
* @param ps The permission state of the package
* @param pkg The package requesting the permissions
*/
+ @GuardedBy("mLock")
private void inheritPermissionStateToNewImplicitPermissionLocked(
@NonNull ArraySet<String> sourcePerms, @NonNull String newPerm,
@NonNull UidPermissionState ps, @NonNull AndroidPackage pkg) {
@@ -3191,6 +3180,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
*
* @return List of users for which the permission state has been changed
*/
+ @GuardedBy("mLock")
private @NonNull int[] setInitialGrantForNewImplicitPermissionsLocked(
@NonNull UidPermissionState origPs, @NonNull UidPermissionState ps,
@NonNull AndroidPackage pkg, @NonNull ArraySet<String> newImplicitPermissions,
@@ -3582,11 +3572,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
+ packageName + " (" + pkg.getPath()
+ ") not in privapp-permissions whitelist");
if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
- if (mPrivappPermissionsViolations == null) {
- mPrivappPermissionsViolations = new ArraySet<>();
+ synchronized (mLock) {
+ if (mPrivappPermissionsViolations == null) {
+ mPrivappPermissionsViolations = new ArraySet<>();
+ }
+ mPrivappPermissionsViolations.add(packageName + " (" + pkg.getPath() + "): "
+ + permissionName);
}
- mPrivappPermissionsViolations.add(packageName + " (" + pkg.getPath() + "): "
- + permissionName);
}
}
}
@@ -3952,6 +3944,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return affectedUserId;
}
+ @GuardedBy("mLock")
private boolean revokeUnusedSharedUserPermissionsLocked(
List<AndroidPackage> pkgList, UidPermissionState uidState) {
// Collect all used permissions in the UID
@@ -4044,35 +4037,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
/**
- * Cache background->foreground permission mapping.
- *
- * <p>This is only run once.
- */
- private void cacheBackgroundToForegoundPermissionMapping() {
- synchronized (mLock) {
- if (mBackgroundPermissions == null) {
- // Cache background -> foreground permission mapping.
- // Only system declares background permissions, hence mapping does never change.
- mBackgroundPermissions = new ArrayMap<>();
- for (Permission bp : mRegistry.getPermissions()) {
- if (bp.getBackgroundPermission() != null) {
- String fgPerm = bp.getName();
- String bgPerm = bp.getBackgroundPermission();
-
- List<String> fgPerms = mBackgroundPermissions.get(bgPerm);
- if (fgPerms == null) {
- fgPerms = new ArrayList<>();
- mBackgroundPermissions.put(bgPerm, fgPerms);
- }
-
- fgPerms.add(fgPerm);
- }
- }
- }
- }
- }
-
- /**
* Update all packages on the volume, <u>beside</u> the changing package. If the changing
* package is set too, all packages are updated.
*/
@@ -4145,8 +4109,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
flags |= UPDATE_PERMISSIONS_ALL;
}
- cacheBackgroundToForegoundPermissionMapping();
-
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "restorePermissionState");
// Now update the permissions for all packages.
if ((flags & UPDATE_PERMISSIONS_ALL) != 0) {
@@ -4252,7 +4214,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
});
}
- mRegistry.removePermission(bp.getName());
+ synchronized (mLock) {
+ mRegistry.removePermission(bp.getName());
+ }
continue;
}
final AndroidPackage sourcePkg =
@@ -4551,6 +4515,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return builder.toString();
}
+ @GuardedBy("mLock")
private int calculateCurrentPermissionFootprintLocked(@NonNull Permission permissionTree) {
int size = 0;
for (final Permission permission : mRegistry.getPermissions()) {
@@ -4559,6 +4524,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return size;
}
+ @GuardedBy("mLock")
private void enforcePermissionCapLocked(PermissionInfo info, Permission tree) {
// We calculate the max size of permissions defined by this uid and throw
// if that plus the size of 'info' would exceed our stated maximum.
@@ -4572,9 +4538,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private void systemReady() {
mSystemReady = true;
- if (mPrivappPermissionsViolations != null) {
- throw new IllegalStateException("Signature|privileged permissions not in "
- + "privapp-permissions whitelist: " + mPrivappPermissionsViolations);
+
+ synchronized (mLock) {
+ if (mPrivappPermissionsViolations != null) {
+ throw new IllegalStateException("Signature|privileged permissions not in "
+ + "privapp-permissions whitelist: " + mPrivappPermissionsViolations);
+ }
}
mPermissionControllerManager = mContext.getSystemService(PermissionControllerManager.class);
@@ -4642,29 +4611,21 @@ public class PermissionManagerService extends IPermissionManager.Stub {
mMetricsLogger.write(log);
}
- /**
- * Get the mapping of background permissions to their foreground permissions.
- *
- * <p>Only initialized in the system server.
- *
- * @return the map &lt;bg permission -> list&lt;fg perm&gt;&gt;
- */
- public @Nullable ArrayMap<String, List<String>> getBackgroundPermissions() {
- return mBackgroundPermissions;
- }
-
+ @GuardedBy("mLock")
@Nullable
private UidPermissionState getUidStateLocked(@NonNull PackageSetting ps,
@UserIdInt int userId) {
return getUidStateLocked(ps.getAppId(), userId);
}
+ @GuardedBy("mLock")
@Nullable
private UidPermissionState getUidStateLocked(@NonNull AndroidPackage pkg,
@UserIdInt int userId) {
return getUidStateLocked(pkg.getUid(), userId);
}
+ @GuardedBy("mLock")
@Nullable
private UidPermissionState getUidStateLocked(@AppIdInt int appId, @UserIdInt int userId) {
final UserPermissionState userState = mState.getUserState(userId);
@@ -4707,6 +4668,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
});
}
+ @GuardedBy("mLock")
private void readLegacyPermissionStatesLocked(@NonNull UidPermissionState uidState,
@NonNull Collection<LegacyPermissionState.PermissionState> permissionStates) {
for (final LegacyPermissionState.PermissionState permissionState : permissionStates) {
@@ -5371,12 +5333,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
- public void addListenerLocked(IOnPermissionsChangeListener listener) {
+ public void addListener(IOnPermissionsChangeListener listener) {
mPermissionListeners.register(listener);
-
}
- public void removeListenerLocked(IOnPermissionsChangeListener listener) {
+ public void removeListener(IOnPermissionsChangeListener listener) {
mPermissionListeners.unregister(listener);
}
diff --git a/services/core/java/com/android/server/policy/DisplayFoldController.java b/services/core/java/com/android/server/policy/DisplayFoldController.java
index f8e26fc57b95..b007a75c1ca5 100644
--- a/services/core/java/com/android/server/policy/DisplayFoldController.java
+++ b/services/core/java/com/android/server/policy/DisplayFoldController.java
@@ -16,8 +16,10 @@
package com.android.server.policy;
+import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Rect;
+import android.hardware.ICameraService;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
@@ -26,11 +28,13 @@ import android.hardware.display.DisplayManagerInternal;
import android.os.Handler;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.util.Slog;
import android.view.DisplayInfo;
import android.view.IDisplayFoldListener;
import com.android.server.DisplayThread;
import com.android.server.LocalServices;
+import com.android.server.camera.CameraServiceProxy;
import com.android.server.wm.WindowManagerInternal;
/**
@@ -38,11 +42,13 @@ import com.android.server.wm.WindowManagerInternal;
* TODO(b/126160895): Move DisplayFoldController from PhoneWindowManager to DisplayPolicy.
*/
class DisplayFoldController {
-
private static final String TAG = "DisplayFoldController";
private final WindowManagerInternal mWindowManagerInternal;
private final DisplayManagerInternal mDisplayManagerInternal;
+ // Camera service proxy can be disabled through a config.
+ @Nullable
+ private final CameraServiceProxy mCameraServiceProxy;
private final int mDisplayId;
private final Handler mHandler;
@@ -58,10 +64,12 @@ class DisplayFoldController {
private final DisplayFoldDurationLogger mDurationLogger = new DisplayFoldDurationLogger();
DisplayFoldController(WindowManagerInternal windowManagerInternal,
- DisplayManagerInternal displayManagerInternal, int displayId, Rect foldedArea,
+ DisplayManagerInternal displayManagerInternal,
+ @Nullable CameraServiceProxy cameraServiceProxy, int displayId, Rect foldedArea,
Handler handler) {
mWindowManagerInternal = windowManagerInternal;
mDisplayManagerInternal = displayManagerInternal;
+ mCameraServiceProxy = cameraServiceProxy;
mDisplayId = displayId;
mFoldedArea = new Rect(foldedArea);
mHandler = handler;
@@ -116,6 +124,16 @@ class DisplayFoldController {
}
}
+ if (mCameraServiceProxy != null) {
+ if (folded) {
+ mCameraServiceProxy.setDeviceStateFlags(ICameraService.DEVICE_STATE_FOLDED);
+ } else {
+ mCameraServiceProxy.clearDeviceStateFlags(ICameraService.DEVICE_STATE_FOLDED);
+ }
+ } else {
+ Slog.w(TAG, "Camera service unavailable to toggle folded state.");
+ }
+
mDurationLogger.setDeviceFolded(folded);
mDurationLogger.logFocusedAppWithFoldState(folded, mFocusedApp);
mFolded = folded;
@@ -193,8 +211,13 @@ class DisplayFoldController {
}
static DisplayFoldController create(Context context, int displayId) {
+ final WindowManagerInternal windowManagerService =
+ LocalServices.getService(WindowManagerInternal.class);
final DisplayManagerInternal displayService =
LocalServices.getService(DisplayManagerInternal.class);
+ final CameraServiceProxy cameraServiceProxy =
+ LocalServices.getService(CameraServiceProxy.class);
+
final String configFoldedArea = context.getResources().getString(
com.android.internal.R.string.config_foldedArea);
final Rect foldedArea;
@@ -204,7 +227,7 @@ class DisplayFoldController {
foldedArea = Rect.unflattenFromString(configFoldedArea);
}
- return new DisplayFoldController(LocalServices.getService(WindowManagerInternal.class),
- displayService, displayId, foldedArea, DisplayThread.getHandler());
+ return new DisplayFoldController(windowManagerService, displayService, cameraServiceProxy,
+ displayId, foldedArea, DisplayThread.getHandler());
}
}
diff --git a/services/core/java/com/android/server/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java
index 06edd19a376a..1a4a22203e57 100644
--- a/services/core/java/com/android/server/power/AttentionDetector.java
+++ b/services/core/java/com/android/server/power/AttentionDetector.java
@@ -18,6 +18,7 @@ package com.android.server.power;
import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE;
+import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.SynchronousUserSwitchObserver;
import android.attention.AttentionManagerInternal;
@@ -42,6 +43,7 @@ import com.android.server.LocalServices;
import com.android.server.wm.WindowManagerInternal;
import java.io.PrintWriter;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
@@ -66,6 +68,9 @@ public class AttentionDetector {
/** Default value in absence of {@link DeviceConfig} override. */
static final long DEFAULT_PRE_DIM_CHECK_DURATION_MILLIS = 2_000;
+ @VisibleForTesting
+ protected long mPreDimCheckDurationMillis;
+
/** DeviceConfig flag name, describes how long to run the check beyond the screen dim event. */
static final String KEY_POST_DIM_CHECK_DURATION_MILLIS =
"post_dim_check_duration_millis";
@@ -73,12 +78,28 @@ public class AttentionDetector {
/** Default value in absence of {@link DeviceConfig} override. */
static final long DEFAULT_POST_DIM_CHECK_DURATION_MILLIS = 0;
+ private long mRequestedPostDimTimeoutMillis;
+
+ /**
+ * Keep the last used post dim timeout for the dumpsys (it can't be longer the dim duration).
+ */
+ private long mEffectivePostDimTimeoutMillis;
+
/**
* DeviceConfig flag name, describes the limit of how long the device can remain unlocked due to
* attention checking.
*/
static final String KEY_MAX_EXTENSION_MILLIS = "max_extension_millis";
+ /**
+ * The default value for the maximum time, in millis, that the phone can stay unlocked because
+ * of attention events, triggered by any user.
+ */
+ @VisibleForTesting
+ protected long mDefaultMaximumExtensionMillis;
+
+ private long mMaximumExtensionMillis;
+
private Context mContext;
private boolean mIsSettingEnabled;
@@ -88,13 +109,6 @@ public class AttentionDetector {
*/
private final Runnable mOnUserAttention;
- /**
- * The default value for the maximum time, in millis, that the phone can stay unlocked because
- * of attention events, triggered by any user.
- */
- @VisibleForTesting
- protected long mDefaultMaximumExtensionMillis;
-
private final Object mLock;
/**
@@ -137,9 +151,6 @@ public class AttentionDetector {
@VisibleForTesting
AttentionCallbackInternalImpl mCallback;
- /** Keep the last used post dim timeout for the dumpsys. */
- private long mLastPostDimTimeout;
-
public AttentionDetector(Runnable onUserAttention, Object lock) {
mOnUserAttention = onUserAttention;
mLock = lock;
@@ -180,6 +191,11 @@ public class AttentionDetector {
updateEnabledFromSettings(context);
}
}, UserHandle.USER_ALL);
+
+ readValuesFromDeviceConfig();
+ DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ context.getMainExecutor(),
+ (properties) -> onDeviceConfigChange(properties.getKeyset()));
}
/** To be called in {@link PowerManagerService#updateUserActivitySummaryLocked}. */
@@ -192,8 +208,8 @@ public class AttentionDetector {
}
final long now = SystemClock.uptimeMillis();
- final long whenToCheck = nextScreenDimming - getPreDimCheckDurationMillis();
- final long whenToStopExtending = mLastUserActivityTime + getMaxExtensionMillis();
+ final long whenToCheck = nextScreenDimming - mPreDimCheckDurationMillis;
+ final long whenToStopExtending = mLastUserActivityTime + mMaximumExtensionMillis;
if (now < whenToCheck) {
if (DEBUG) {
Slog.d(TAG, "Do not check for attention yet, wait " + (whenToCheck - now));
@@ -220,9 +236,11 @@ public class AttentionDetector {
mRequestId++;
mLastActedOnNextScreenDimming = nextScreenDimming;
mCallback = new AttentionCallbackInternalImpl(mRequestId);
+ mEffectivePostDimTimeoutMillis = Math.min(mRequestedPostDimTimeoutMillis,
+ dimDurationMillis);
Slog.v(TAG, "Checking user attention, ID: " + mRequestId);
final boolean sent = mAttentionManager.checkAttention(
- getPreDimCheckDurationMillis() + getPostDimCheckDurationMillis(dimDurationMillis),
+ mPreDimCheckDurationMillis + mEffectivePostDimTimeoutMillis,
mCallback);
if (!sent) {
mRequested.set(false);
@@ -294,9 +312,9 @@ public class AttentionDetector {
public void dump(PrintWriter pw) {
pw.println("AttentionDetector:");
pw.println(" mIsSettingEnabled=" + mIsSettingEnabled);
- pw.println(" mMaxExtensionMillis=" + getMaxExtensionMillis());
- pw.println(" preDimCheckDurationMillis=" + getPreDimCheckDurationMillis());
- pw.println(" postDimCheckDurationMillis=" + mLastPostDimTimeout);
+ pw.println(" mMaxExtensionMillis=" + mMaximumExtensionMillis);
+ pw.println(" mPreDimCheckDurationMillis=" + mPreDimCheckDurationMillis);
+ pw.println(" mEffectivePostDimTimeout=" + mEffectivePostDimTimeoutMillis);
pw.println(" mLastUserActivityTime(excludingAttention)=" + mLastUserActivityTime);
pw.println(" mAttentionServiceSupported=" + isAttentionServiceSupported());
pw.println(" mRequested=" + mRequested);
@@ -319,7 +337,7 @@ public class AttentionDetector {
/** How long to check <b>after</b> the screen dims, capped at the dim duration. */
@VisibleForTesting
- protected long getPostDimCheckDurationMillis(long dimDurationMillis) {
+ protected long getPostDimCheckDurationMillis() {
final long millis = DeviceConfig.getLong(NAMESPACE_ATTENTION_MANAGER_SERVICE,
KEY_POST_DIM_CHECK_DURATION_MILLIS,
DEFAULT_POST_DIM_CHECK_DURATION_MILLIS);
@@ -328,9 +346,7 @@ public class AttentionDetector {
Slog.w(TAG, "Bad flag value supplied for: " + KEY_POST_DIM_CHECK_DURATION_MILLIS);
return DEFAULT_POST_DIM_CHECK_DURATION_MILLIS;
}
-
- mLastPostDimTimeout = Math.min(millis, dimDurationMillis);
- return mLastPostDimTimeout;
+ return millis;
}
/** How long the device can remain unlocked due to attention checking. */
@@ -348,6 +364,32 @@ public class AttentionDetector {
return millis;
}
+ private void onDeviceConfigChange(@NonNull Set<String> keys) {
+ for (String key : keys) {
+ switch (key) {
+ case KEY_MAX_EXTENSION_MILLIS:
+ case KEY_POST_DIM_CHECK_DURATION_MILLIS:
+ case KEY_PRE_DIM_CHECK_DURATION_MILLIS:
+ readValuesFromDeviceConfig();
+ return;
+ default:
+ Slog.i(TAG, "Ignoring change on " + key);
+ }
+ }
+ }
+
+ private void readValuesFromDeviceConfig() {
+ mMaximumExtensionMillis = getMaxExtensionMillis();
+ mPreDimCheckDurationMillis = getPreDimCheckDurationMillis();
+ mRequestedPostDimTimeoutMillis = getPostDimCheckDurationMillis();
+
+ Slog.i(TAG, "readValuesFromDeviceConfig():"
+ + "\nmMaximumExtensionMillis=" + mMaximumExtensionMillis
+ + "\nmPreDimCheckDurationMillis=" + mPreDimCheckDurationMillis
+ + "\nmRequestedPostDimTimeoutMillis=" + mRequestedPostDimTimeoutMillis);
+
+ }
+
@VisibleForTesting
final class AttentionCallbackInternalImpl extends AttentionCallbackInternal {
private final int mId;
diff --git a/services/core/java/com/android/server/rollback/Rollback.java b/services/core/java/com/android/server/rollback/Rollback.java
index 2db6043f1c0a..2d51cf9a5083 100644
--- a/services/core/java/com/android/server/rollback/Rollback.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -146,11 +146,6 @@ class Rollback {
private @RollbackState int mState;
/**
- * The id of the post-reboot apk session for a staged install, if any.
- */
- private int mApkSessionId = -1;
-
- /**
* True if we are expecting the package manager to call restoreUserData
* for this rollback because it has just been committed but the rollback
* has not yet been fully applied.
@@ -236,7 +231,7 @@ class Rollback {
* Constructs a pre-populated Rollback instance.
*/
Rollback(RollbackInfo info, File backupDir, Instant timestamp, int stagedSessionId,
- @RollbackState int state, int apkSessionId, boolean restoreUserDataInProgress,
+ @RollbackState int state, boolean restoreUserDataInProgress,
int userId, String installerPackageName, SparseIntArray extensionVersions) {
this.info = info;
mUserId = userId;
@@ -245,7 +240,6 @@ class Rollback {
mTimestamp = timestamp;
mStagedSessionId = stagedSessionId;
mState = state;
- mApkSessionId = apkSessionId;
mRestoreUserDataInProgress = restoreUserDataInProgress;
mExtensionVersions = Objects.requireNonNull(extensionVersions);
// TODO(b/120200473): Include this field during persistence. This field will be used to
@@ -727,25 +721,6 @@ class Rollback {
}
/**
- * Returns the id of the post-reboot apk session for a staged install, if any.
- */
- @WorkerThread
- int getApkSessionId() {
- assertInWorkerThread();
- return mApkSessionId;
- }
-
- /**
- * Sets the id of the post-reboot apk session for a staged install.
- */
- @WorkerThread
- void setApkSessionId(int apkSessionId) {
- assertInWorkerThread();
- mApkSessionId = apkSessionId;
- RollbackStore.saveRollback(this);
- }
-
- /**
* Returns true if we are expecting the package manager to call restoreUserData for this
* rollback because it has just been committed but the rollback has not yet been fully applied.
*/
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerInternal.java b/services/core/java/com/android/server/rollback/RollbackManagerInternal.java
index b473b8ca9859..dbda4a85fd9d 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerInternal.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerInternal.java
@@ -53,13 +53,4 @@ public interface RollbackManagerInternal {
* @return The rollback id if rollback was enabled successfully, or -1 if not.
*/
int notifyStagedSession(int sessionId);
-
- /**
- * Used by the staging manager to notify the RollbackManager of the apk
- * session for a staged session.
- *
- * @param originalSessionId The original session ID where this apk session belongs
- * @param apkSessionId The ID of this apk session
- */
- void notifyStagedApkSession(int originalSessionId, int apkSessionId);
}
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 1e89e06617d3..b34d46ff1a0c 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -28,6 +28,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
+import android.content.pm.ModuleInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
@@ -53,7 +54,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.ext.SdkExtensions;
import android.provider.DeviceConfig;
-import android.util.IntArray;
import android.util.Log;
import android.util.LongArrayQueue;
import android.util.Slog;
@@ -151,10 +151,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba
// Accessed on the handler thread only.
private final List<Rollback> mRollbacks = new ArrayList<>();
- // Apk sessions from a staged session with no matching rollback.
- // Accessed on the handler thread only.
- private final IntArray mOrphanedApkSessionIds = new IntArray();
-
private final RollbackStore mRollbackStore;
private final Context mContext;
@@ -646,8 +642,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba
onPackageReplaced(apexPackageName);
}
- mOrphanedApkSessionIds.clear();
-
mPackageHealthObserver.onBootCompletedAsync();
});
}
@@ -782,25 +776,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba
return false;
}
- // Check to see if this is the apk session for a staged session with
- // rollback enabled.
- for (int i = 0; i < mRollbacks.size(); ++i) {
- Rollback rollback = mRollbacks.get(i);
- if (rollback.getApkSessionId() == parentSession.getSessionId()) {
- // This is the apk session for a staged session with rollback enabled. We do
- // not need to create a new rollback for this session.
- return true;
- }
- }
-
- // Check to see if this is the apk session for a staged session for which rollback was
- // cancelled.
- if (mOrphanedApkSessionIds.indexOf(parentSession.getSessionId()) != -1) {
- Slog.w(TAG, "Not enabling rollback for apk as no matching staged session "
- + "rollback exists");
- return false;
- }
-
// See if we already have a Rollback that contains this package
// session. If not, create a new Rollback for the parent session
// that we will use for all the packages in the session.
@@ -1038,37 +1013,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba
});
}
- @ExtThread
- @Override
- public void notifyStagedApkSession(int originalSessionId, int apkSessionId) {
- assertNotInWorkerThread();
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
- throw new SecurityException("notifyStagedApkSession may only be called by the system.");
- }
- getHandler().post(() -> {
- assertInWorkerThread();
- Rollback rollback = null;
- for (int i = 0; i < mRollbacks.size(); ++i) {
- Rollback candidate = mRollbacks.get(i);
- if (candidate.getStagedSessionId() == originalSessionId) {
- rollback = candidate;
- break;
- }
- }
- if (rollback == null) {
- // Did not find rollback matching originalSessionId.
- Slog.e(TAG, "notifyStagedApkSession did not find rollback for session "
- + originalSessionId
- + ". Adding orphaned apk session " + apkSessionId);
- mOrphanedApkSessionIds.add(apkSessionId);
- }
-
- if (rollback != null) {
- rollback.setApkSessionId(apkSessionId);
- }
- });
- }
-
/**
* Returns true if the installer is allowed to enable rollback for the
* given named package, false otherwise.
@@ -1088,8 +1032,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba
Manifest.permission.TEST_MANAGE_ROLLBACKS,
installerPackageName) == PackageManager.PERMISSION_GRANTED;
- // For now only allow rollbacks for allowlisted packages or for testing.
- return (isRollbackAllowlisted(packageName) && manageRollbacksGranted)
+ // For now only allow rollbacks for modules, allowlisted packages, or for testing.
+ return (isRollbackAllowed(packageName) && manageRollbacksGranted)
|| testManageRollbacksGranted;
}
@@ -1097,8 +1041,24 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub implements Rollba
* Returns true is this package is eligible for enabling rollback.
*/
@AnyThread
- private boolean isRollbackAllowlisted(String packageName) {
- return SystemConfig.getInstance().getRollbackWhitelistedPackages().contains(packageName);
+ private boolean isRollbackAllowed(String packageName) {
+ return SystemConfig.getInstance().getRollbackWhitelistedPackages().contains(packageName)
+ || isModule(packageName);
+ }
+ /**
+ * Returns true if the package name is the name of a module.
+ */
+ @AnyThread
+ private boolean isModule(String packageName) {
+ PackageManager pm = mContext.getPackageManager();
+ final ModuleInfo moduleInfo;
+ try {
+ moduleInfo = pm.getModuleInfo(packageName, 0);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+
+ return moduleInfo != null;
}
/**
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 44a63367dab5..2ee87e67e467 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -267,7 +267,6 @@ class RollbackStore {
dataJson.put("timestamp", rollback.getTimestamp().toString());
dataJson.put("stagedSessionId", rollback.getStagedSessionId());
dataJson.put("state", rollback.getStateAsString());
- dataJson.put("apkSessionId", rollback.getApkSessionId());
dataJson.put("restoreUserDataInProgress", rollback.isRestoreUserDataInProgress());
dataJson.put("userId", rollback.getUserId());
dataJson.putOpt("installerPackageName", rollback.getInstallerPackageName());
@@ -319,7 +318,6 @@ class RollbackStore {
Instant.parse(dataJson.getString("timestamp")),
dataJson.getInt("stagedSessionId"),
rollbackStateFromString(dataJson.getString("state")),
- dataJson.getInt("apkSessionId"),
dataJson.getBoolean("restoreUserDataInProgress"),
dataJson.optInt("userId", UserHandle.SYSTEM.getIdentifier()),
dataJson.optString("installerPackageName", ""),
diff --git a/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java b/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
index e72c185a0d2d..f9ef994a523a 100644
--- a/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
+++ b/services/core/java/com/android/server/rollback/WatchdogRollbackLogger.java
@@ -36,6 +36,7 @@ import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
import android.content.rollback.PackageRollbackInfo;
import android.content.rollback.RollbackInfo;
+import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Slog;
@@ -216,6 +217,34 @@ public final class WatchdogRollbackLogger {
failingPackageName,
new byte[]{});
}
+
+ logTestProperties(logPackage, type, rollbackReason, failingPackageName);
+ }
+
+ /**
+ * Writes properties which will be used by rollback tests to check if particular rollback
+ * events have occurred.
+ *
+ * persist.sys.rollbacktest.enabled: true if rollback tests are running
+ * persist.sys.rollbacktest.EVENT_TYPE: true if a particular rollback event has occurred
+ * ex: persist.sys.rollbacktest.ROLLBACK_INITIATE is true if ROLLBACK_INITIATE has happened
+ * persist.sys.rollbacktest.EVENT_TYPE.logPackage: the package to associate the rollback with
+ * persist.sys.rollbacktest.EVENT_TYPE.rollbackReason: the reason Watchdog triggered a rollback
+ * persist.sys.rollbacktest.EVENT_TYPE.failedPackageName: the failing package or process which
+ * triggered the rollback
+ */
+ private static void logTestProperties(@Nullable VersionedPackage logPackage, int type,
+ int rollbackReason, @NonNull String failingPackageName) {
+ // This property should be on only during the tests
+ final String prefix = "persist.sys.rollbacktest.";
+ if (!SystemProperties.getBoolean(prefix + "enabled", false)) {
+ return;
+ }
+ String key = prefix + rollbackTypeToString(type);
+ SystemProperties.set(key, String.valueOf(true));
+ SystemProperties.set(key + ".logPackage", logPackage != null ? logPackage.toString() : "");
+ SystemProperties.set(key + ".rollbackReason", rollbackReasonToString(rollbackReason));
+ SystemProperties.set(key + ".failedPackageName", failingPackageName);
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 7433a3a53ad8..d3b1ac6e6096 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -247,6 +247,13 @@ public class StatsPullAtomService extends SystemService {
// 20% as a conservative estimate.
private static final int MAX_PROCSTATS_RAW_SHARD_SIZE = (int) (MAX_PROCSTATS_SHARD_SIZE * 1.20);
+ /**
+ * Threshold to filter out small CPU times at frequency per UID. Those small values appear
+ * because of more precise accounting in a BPF program. Discarding them reduces the data by at
+ * least 20% with negligible error.
+ */
+ private static final int MIN_CPU_TIME_PER_UID_FREQ = 10;
+
private final Object mThermalLock = new Object();
@GuardedBy("mThermalLock")
private IThermalService mThermalService;
@@ -1509,7 +1516,7 @@ public class StatsPullAtomService extends SystemService {
int pullCpuTimePerUidFreqLocked(int atomTag, List<StatsEvent> pulledData) {
mCpuUidFreqTimeReader.readAbsolute((uid, cpuFreqTimeMs) -> {
for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
- if (cpuFreqTimeMs[freqIndex] != 0) {
+ if (cpuFreqTimeMs[freqIndex] >= MIN_CPU_TIME_PER_UID_FREQ) {
pulledData.add(FrameworkStatsLog.buildStatsEvent(
atomTag, uid, freqIndex, cpuFreqTimeMs[freqIndex]));
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 0a7f08bfbe8c..f65a5024bdea 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -4489,7 +4489,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
detachChildren();
}
if (app != null) {
- app.invalidateOomScoreReferenceState(false /* computeNow */);
+ app.computeProcessActivityState();
}
switch (state) {
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index a068d2b7c823..4dea3c09cc31 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -63,6 +63,9 @@ 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.LockTaskController.LOCK_TASK_AUTH_ALLOWLISTED;
+import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE;
+import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
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.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
@@ -70,9 +73,6 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.Task.ActivityState.PAUSED;
import static com.android.server.wm.Task.ActivityState.PAUSING;
import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK;
-import static com.android.server.wm.Task.LOCK_TASK_AUTH_ALLOWLISTED;
-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.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.wm.Task.TAG_CLEANUP;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 910a1a2c69b2..f92f231758a4 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1665,11 +1665,6 @@ class ActivityStarter {
final Task taskToAffiliate = (mLaunchTaskBehind && mSourceRecord != null)
? mSourceRecord.getTask() : null;
setNewTask(taskToAffiliate);
- if (mService.getLockTaskController().isLockTaskModeViolation(
- mStartActivity.getTask())) {
- Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
- return START_RETURN_LOCK_TASK_MODE_VIOLATION;
- }
} else if (mAddingToTask) {
addOrReparentStartingActivity(targetTask, "adding to task");
}
@@ -1848,10 +1843,17 @@ class ActivityStarter {
final boolean isNewClearTask =
(mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK);
- if (!newTask && mService.getLockTaskController().isLockTaskModeViolation(targetTask,
- isNewClearTask)) {
- Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
- return START_RETURN_LOCK_TASK_MODE_VIOLATION;
+ if (!newTask) {
+ if (mService.getLockTaskController().isLockTaskModeViolation(targetTask,
+ isNewClearTask)) {
+ Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
+ return START_RETURN_LOCK_TASK_MODE_VIOLATION;
+ }
+ } else {
+ if (mService.getLockTaskController().isNewTaskLockTaskModeViolation(mStartActivity)) {
+ Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
+ return START_RETURN_LOCK_TASK_MODE_VIOLATION;
+ }
}
return START_SUCCESS;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index eb86d37225bc..f649a2f9f5a6 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -533,9 +533,6 @@ public abstract class ActivityTaskManagerInternal {
/** Flush recent tasks to disk. */
public abstract void flushRecentTasks();
- public abstract WindowProcessController getHomeProcess();
- public abstract WindowProcessController getPreviousProcess();
-
public abstract void clearLockedTasks(String reason);
public abstract void updateUserConfiguration();
public abstract boolean canShowErrorDialogs();
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 608d37395b28..df915a64e482 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -117,13 +117,13 @@ import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEI
import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
import static com.android.server.wm.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG;
import static com.android.server.wm.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
+import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_DONT_LOCK;
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.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.ActivityState.DESTROYED;
import static com.android.server.wm.Task.ActivityState.DESTROYING;
-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.WindowContainer.POSITION_TOP;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
@@ -7324,20 +7324,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
@Override
- public WindowProcessController getHomeProcess() {
- synchronized (mGlobalLock) {
- return mHomeProcess;
- }
- }
-
- @Override
- public WindowProcessController getPreviousProcess() {
- synchronized (mGlobalLock) {
- return mPreviousProcess;
- }
- }
-
- @Override
public void clearLockedTasks(String reason) {
synchronized (mGlobalLock) {
getLockTaskController().clearLockedTasks(reason);
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index f647bea950f2..472678cf8e37 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -22,184 +22,41 @@ import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_AUTO;
import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_DISABLED;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
-import android.os.Environment;
-import android.os.FileUtils;
import android.provider.Settings;
-import android.util.AtomicFile;
-import android.util.Slog;
-import android.util.Xml;
import android.view.Display;
-import android.view.DisplayAddress;
import android.view.DisplayInfo;
import android.view.IWindowManager;
import android.view.Surface;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.FastXmlSerializer;
-import com.android.internal.util.XmlUtils;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.wm.DisplayContent.ForceScalingMode;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
+import java.util.Objects;
/**
- * Current persistent settings about a display
+ * Current persistent settings about a display. Provides policies for display settings and
+ * delegates the persistence and lookup of settings values to the supplied {@link SettingsProvider}.
*/
class DisplayWindowSettings {
- private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayWindowSettings" : TAG_WM;
-
- private static final String SYSTEM_DIRECTORY = "system";
- private static final String DISPLAY_SETTINGS_FILE_NAME = "display_settings.xml";
- private static final String VENDOR_DISPLAY_SETTINGS_PATH = "etc/" + DISPLAY_SETTINGS_FILE_NAME;
- private static final String WM_DISPLAY_COMMIT_TAG = "wm-displays";
-
- private static final int IDENTIFIER_UNIQUE_ID = 0;
- private static final int IDENTIFIER_PORT = 1;
- @IntDef(prefix = { "IDENTIFIER_" }, value = {
- IDENTIFIER_UNIQUE_ID,
- IDENTIFIER_PORT,
- })
- @interface DisplayIdentifierType {}
-
private final WindowManagerService mService;
- private final HashMap<String, Entry> mEntries = new HashMap<>();
- private final SettingPersister mStorage;
-
- /**
- * The preferred type of a display identifier to use when storing and retrieving entries.
- * {@link #getIdentifier(DisplayInfo)} must be used to get current preferred identifier for each
- * display. It will fall back to using {@link #IDENTIFIER_UNIQUE_ID} if the currently selected
- * one is not applicable to a particular display.
- */
- @DisplayIdentifierType
- private int mIdentifier = IDENTIFIER_UNIQUE_ID;
-
- /** Interface for persisting the display window settings. */
- interface SettingPersister {
- InputStream openRead() throws IOException;
- OutputStream startWrite() throws IOException;
- void finishWrite(OutputStream os, boolean success);
- }
-
- private static class Entry {
- private final String mName;
- private int mWindowingMode = WindowConfiguration.WINDOWING_MODE_UNDEFINED;
- private int mUserRotationMode = WindowManagerPolicy.USER_ROTATION_FREE;
- private int mUserRotation = Surface.ROTATION_0;
- private int mForcedWidth;
- private int mForcedHeight;
- private int mForcedDensity;
- private int mForcedScalingMode = FORCE_SCALING_MODE_AUTO;
- private int mRemoveContentMode = REMOVE_CONTENT_MODE_UNDEFINED;
- private boolean mShouldShowWithInsecureKeyguard = false;
- private boolean mShouldShowSystemDecors = false;
- private boolean mShouldShowIme = false;
- private int mFixedToUserRotation = IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT;
- private boolean mIgnoreOrientationRequest = false;
-
- private Entry(String name) {
- mName = name;
- }
-
- private Entry(String name, Entry copyFrom) {
- this(name);
- mWindowingMode = copyFrom.mWindowingMode;
- mUserRotationMode = copyFrom.mUserRotationMode;
- mUserRotation = copyFrom.mUserRotation;
- mForcedWidth = copyFrom.mForcedWidth;
- mForcedHeight = copyFrom.mForcedHeight;
- mForcedDensity = copyFrom.mForcedDensity;
- mForcedScalingMode = copyFrom.mForcedScalingMode;
- mRemoveContentMode = copyFrom.mRemoveContentMode;
- mShouldShowWithInsecureKeyguard = copyFrom.mShouldShowWithInsecureKeyguard;
- mShouldShowSystemDecors = copyFrom.mShouldShowSystemDecors;
- mShouldShowIme = copyFrom.mShouldShowIme;
- mFixedToUserRotation = copyFrom.mFixedToUserRotation;
- mIgnoreOrientationRequest = copyFrom.mIgnoreOrientationRequest;
- }
-
- /** @return {@code true} if all values are default. */
- private boolean isEmpty() {
- return mWindowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED
- && mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
- && mUserRotation == Surface.ROTATION_0
- && mForcedWidth == 0 && mForcedHeight == 0 && mForcedDensity == 0
- && mForcedScalingMode == FORCE_SCALING_MODE_AUTO
- && mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED
- && !mShouldShowWithInsecureKeyguard
- && !mShouldShowSystemDecors
- && !mShouldShowIme
- && mFixedToUserRotation == IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT
- && !mIgnoreOrientationRequest;
- }
- }
-
- DisplayWindowSettings(WindowManagerService service) {
- this(service, new AtomicFileStorage());
- }
+ private final SettingsProvider mSettingsProvider;
- @VisibleForTesting
- DisplayWindowSettings(WindowManagerService service, SettingPersister storageImpl) {
+ DisplayWindowSettings(WindowManagerService service, SettingsProvider settingsProvider) {
mService = service;
- mStorage = storageImpl;
- readSettings();
- }
-
- private @Nullable Entry getEntry(DisplayInfo displayInfo) {
- final String identifier = getIdentifier(displayInfo);
- Entry entry;
- // Try to get corresponding entry using preferred identifier for the current config.
- if ((entry = mEntries.get(identifier)) != null) {
- return entry;
- }
- // Else, fall back to the display name.
- if ((entry = mEntries.get(displayInfo.name)) != null) {
- // Found an entry stored with old identifier - upgrade to the new type now.
- return updateIdentifierForEntry(entry, displayInfo);
- }
- return null;
- }
-
- private Entry getOrCreateEntry(DisplayInfo displayInfo) {
- final Entry entry = getEntry(displayInfo);
- return entry != null ? entry : new Entry(getIdentifier(displayInfo));
- }
-
- /**
- * Upgrades the identifier of a legacy entry. Does it by copying the data from the old record
- * and clearing the old key in memory. The entry will be written to storage next time when a
- * setting changes.
- */
- private Entry updateIdentifierForEntry(Entry entry, DisplayInfo displayInfo) {
- final Entry newEntry = new Entry(getIdentifier(displayInfo), entry);
- removeEntry(displayInfo);
- mEntries.put(newEntry.mName, newEntry);
- return newEntry;
+ mSettingsProvider = settingsProvider;
}
void setUserRotation(DisplayContent displayContent, int rotationMode, int rotation) {
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- final Entry entry = getOrCreateEntry(displayInfo);
- entry.mUserRotationMode = rotationMode;
- entry.mUserRotation = rotation;
- writeSettingsIfNeeded(entry, displayInfo);
+ final SettingsProvider.SettingsEntry overrideSettings =
+ mSettingsProvider.getOverrideSettings(displayInfo);
+ overrideSettings.mUserRotationMode = rotationMode;
+ overrideSettings.mUserRotation = rotation;
+ mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
}
void setForcedSize(DisplayContent displayContent, int width, int height) {
@@ -207,14 +64,14 @@ class DisplayWindowSettings {
final String sizeString = (width == 0 || height == 0) ? "" : (width + "," + height);
Settings.Global.putString(mService.mContext.getContentResolver(),
Settings.Global.DISPLAY_SIZE_FORCED, sizeString);
- return;
}
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- final Entry entry = getOrCreateEntry(displayInfo);
- entry.mForcedWidth = width;
- entry.mForcedHeight = height;
- writeSettingsIfNeeded(entry, displayInfo);
+ final SettingsProvider.SettingsEntry overrideSettings =
+ mSettingsProvider.getOverrideSettings(displayInfo);
+ overrideSettings.mForcedWidth = width;
+ overrideSettings.mForcedHeight = height;
+ mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
}
void setForcedDensity(DisplayContent displayContent, int density, int userId) {
@@ -222,47 +79,47 @@ class DisplayWindowSettings {
final String densityString = density == 0 ? "" : Integer.toString(density);
Settings.Secure.putStringForUser(mService.mContext.getContentResolver(),
Settings.Secure.DISPLAY_DENSITY_FORCED, densityString, userId);
- return;
}
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- final Entry entry = getOrCreateEntry(displayInfo);
- entry.mForcedDensity = density;
- writeSettingsIfNeeded(entry, displayInfo);
+ final SettingsProvider.SettingsEntry overrideSettings =
+ mSettingsProvider.getOverrideSettings(displayInfo);
+ overrideSettings.mForcedDensity = density;
+ mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
}
void setForcedScalingMode(DisplayContent displayContent, @ForceScalingMode int mode) {
if (displayContent.isDefaultDisplay) {
Settings.Global.putInt(mService.mContext.getContentResolver(),
Settings.Global.DISPLAY_SCALING_FORCE, mode);
- return;
}
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- final Entry entry = getOrCreateEntry(displayInfo);
- entry.mForcedScalingMode = mode;
- writeSettingsIfNeeded(entry, displayInfo);
+ final SettingsProvider.SettingsEntry overrideSettings =
+ mSettingsProvider.getOverrideSettings(displayInfo);
+ overrideSettings.mForcedScalingMode = mode;
+ mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
}
void setFixedToUserRotation(DisplayContent displayContent, int fixedToUserRotation) {
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- final Entry entry = getOrCreateEntry(displayInfo);
- entry.mFixedToUserRotation = fixedToUserRotation;
- writeSettingsIfNeeded(entry, displayInfo);
+ final SettingsProvider.SettingsEntry overrideSettings =
+ mSettingsProvider.getOverrideSettings(displayInfo);
+ overrideSettings.mFixedToUserRotation = fixedToUserRotation;
+ mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
}
void setIgnoreOrientationRequest(
DisplayContent displayContent, boolean ignoreOrientationRequest) {
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
- final Entry entry = getOrCreateEntry(displayInfo);
- if (entry.mIgnoreOrientationRequest == ignoreOrientationRequest) return;
- entry.mIgnoreOrientationRequest = ignoreOrientationRequest;
- writeSettingsIfNeeded(entry, displayInfo);
+ final SettingsProvider.SettingsEntry overrideSettings =
+ mSettingsProvider.getOverrideSettings(displayInfo);
+ overrideSettings.mIgnoreOrientationRequest = ignoreOrientationRequest;
+ mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
}
- private int getWindowingModeLocked(Entry entry, DisplayContent dc) {
- int windowingMode = entry != null ? entry.mWindowingMode
- : WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+ private int getWindowingModeLocked(SettingsProvider.SettingsEntry settings, DisplayContent dc) {
+ int windowingMode = settings.mWindowingMode;
// This display used to be in freeform, but we don't support freeform anymore, so fall
// back to fullscreen.
if (windowingMode == WindowConfiguration.WINDOWING_MODE_FREEFORM
@@ -281,22 +138,23 @@ class DisplayWindowSettings {
int getWindowingModeLocked(DisplayContent dc) {
final DisplayInfo displayInfo = dc.getDisplayInfo();
- final Entry entry = getEntry(displayInfo);
- return getWindowingModeLocked(entry, dc);
+ final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo);
+ return getWindowingModeLocked(settings, dc);
}
void setWindowingModeLocked(DisplayContent dc, int mode) {
final DisplayInfo displayInfo = dc.getDisplayInfo();
- final Entry entry = getOrCreateEntry(displayInfo);
- entry.mWindowingMode = mode;
+ final SettingsProvider.SettingsEntry overrideSettings =
+ mSettingsProvider.getOverrideSettings(displayInfo);
+ overrideSettings.mWindowingMode = mode;
dc.setWindowingMode(mode);
- writeSettingsIfNeeded(entry, displayInfo);
+ mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
}
int getRemoveContentModeLocked(DisplayContent dc) {
final DisplayInfo displayInfo = dc.getDisplayInfo();
- final Entry entry = getEntry(displayInfo);
- if (entry == null || entry.mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED) {
+ final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo);
+ if (settings.mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED) {
if (dc.isPrivate()) {
// For private displays by default content is destroyed on removal.
return REMOVE_CONTENT_MODE_DESTROY;
@@ -304,111 +162,110 @@ class DisplayWindowSettings {
// For other displays by default content is moved to primary on removal.
return REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY;
}
- return entry.mRemoveContentMode;
+ return settings.mRemoveContentMode;
}
void setRemoveContentModeLocked(DisplayContent dc, int mode) {
final DisplayInfo displayInfo = dc.getDisplayInfo();
- final Entry entry = getOrCreateEntry(displayInfo);
- entry.mRemoveContentMode = mode;
- writeSettingsIfNeeded(entry, displayInfo);
+ final SettingsProvider.SettingsEntry overrideSettings =
+ mSettingsProvider.getOverrideSettings(displayInfo);
+ overrideSettings.mRemoveContentMode = mode;
+ mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
}
boolean shouldShowWithInsecureKeyguardLocked(DisplayContent dc) {
final DisplayInfo displayInfo = dc.getDisplayInfo();
- final Entry entry = getEntry(displayInfo);
- if (entry == null) {
- return false;
- }
- return entry.mShouldShowWithInsecureKeyguard;
+ final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo);
+ return settings.mShouldShowWithInsecureKeyguard != null
+ ? settings.mShouldShowWithInsecureKeyguard : false;
}
void setShouldShowWithInsecureKeyguardLocked(DisplayContent dc, boolean shouldShow) {
if (!dc.isPrivate() && shouldShow) {
- Slog.e(TAG, "Public display can't be allowed to show content when locked");
- return;
+ throw new IllegalArgumentException("Public display can't be allowed to show content"
+ + " when locked");
}
final DisplayInfo displayInfo = dc.getDisplayInfo();
- final Entry entry = getOrCreateEntry(displayInfo);
- entry.mShouldShowWithInsecureKeyguard = shouldShow;
- writeSettingsIfNeeded(entry, displayInfo);
+ final SettingsProvider.SettingsEntry overrideSettings =
+ mSettingsProvider.getOverrideSettings(displayInfo);
+ overrideSettings.mShouldShowWithInsecureKeyguard = shouldShow;
+ mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
}
boolean shouldShowSystemDecorsLocked(DisplayContent dc) {
if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) {
- // For default display should show system decors.
+ // Default display should show system decors.
return true;
}
final DisplayInfo displayInfo = dc.getDisplayInfo();
- final Entry entry = getEntry(displayInfo);
- if (entry == null) {
- return false;
- }
- return entry.mShouldShowSystemDecors;
+ final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo);
+ return settings.mShouldShowSystemDecors != null ? settings.mShouldShowSystemDecors : false;
}
void setShouldShowSystemDecorsLocked(DisplayContent dc, boolean shouldShow) {
- if (dc.getDisplayId() == Display.DEFAULT_DISPLAY && !shouldShow) {
- Slog.e(TAG, "Default display should show system decors");
- return;
- }
-
final DisplayInfo displayInfo = dc.getDisplayInfo();
- final Entry entry = getOrCreateEntry(displayInfo);
- entry.mShouldShowSystemDecors = shouldShow;
- writeSettingsIfNeeded(entry, displayInfo);
+ final SettingsProvider.SettingsEntry overrideSettings =
+ mSettingsProvider.getOverrideSettings(displayInfo);
+ overrideSettings.mShouldShowSystemDecors = shouldShow;
+ mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
}
boolean shouldShowImeLocked(DisplayContent dc) {
if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) {
- // For default display should shows IME.
+ // Default display should show IME.
return true;
}
final DisplayInfo displayInfo = dc.getDisplayInfo();
- final Entry entry = getEntry(displayInfo);
- if (entry == null) {
- return false;
- }
- return entry.mShouldShowIme;
+ final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo);
+ return settings.mShouldShowIme != null ? settings.mShouldShowIme : false;
}
void setShouldShowImeLocked(DisplayContent dc, boolean shouldShow) {
- if (dc.getDisplayId() == Display.DEFAULT_DISPLAY && !shouldShow) {
- Slog.e(TAG, "Default display should show IME");
- return;
- }
-
final DisplayInfo displayInfo = dc.getDisplayInfo();
- final Entry entry = getOrCreateEntry(displayInfo);
- entry.mShouldShowIme = shouldShow;
- writeSettingsIfNeeded(entry, displayInfo);
+ final SettingsProvider.SettingsEntry overrideSettings =
+ mSettingsProvider.getOverrideSettings(displayInfo);
+ overrideSettings.mShouldShowIme = shouldShow;
+ mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
}
void applySettingsToDisplayLocked(DisplayContent dc) {
final DisplayInfo displayInfo = dc.getDisplayInfo();
- final Entry entry = getOrCreateEntry(displayInfo);
+ final SettingsProvider.SettingsEntry settings = mSettingsProvider.getSettings(displayInfo);
// Setting windowing mode first, because it may override overscan values later.
- dc.setWindowingMode(getWindowingModeLocked(entry, dc));
-
- dc.getDisplayRotation().restoreSettings(entry.mUserRotationMode,
- entry.mUserRotation, entry.mFixedToUserRotation);
-
- final boolean hasDensityOverride = entry.mForcedDensity != 0;
- final boolean hasSizeOverride = entry.mForcedWidth != 0 && entry.mForcedHeight != 0;
+ final int windowingMode = getWindowingModeLocked(settings, dc);
+ dc.setWindowingMode(windowingMode);
+
+ final int userRotationMode = settings.mUserRotationMode != null
+ ? settings.mUserRotationMode : WindowManagerPolicy.USER_ROTATION_FREE;
+ final int userRotation = settings.mUserRotation != null
+ ? settings.mUserRotation : Surface.ROTATION_0;
+ final int mFixedToUserRotation = settings.mFixedToUserRotation != null
+ ? settings.mFixedToUserRotation : IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT;
+ dc.getDisplayRotation().restoreSettings(userRotationMode, userRotation,
+ mFixedToUserRotation);
+
+ final boolean hasDensityOverride = settings.mForcedDensity != 0;
+ final boolean hasSizeOverride = settings.mForcedWidth != 0 && settings.mForcedHeight != 0;
dc.mIsDensityForced = hasDensityOverride;
dc.mIsSizeForced = hasSizeOverride;
- dc.setIgnoreOrientationRequest(entry.mIgnoreOrientationRequest);
- final int width = hasSizeOverride ? entry.mForcedWidth : dc.mBaseDisplayWidth;
- final int height = hasSizeOverride ? entry.mForcedHeight : dc.mBaseDisplayHeight;
- final int density = hasDensityOverride ? entry.mForcedDensity : dc.mBaseDisplayDensity;
+ final boolean ignoreOrientationRequest = settings.mIgnoreOrientationRequest != null
+ ? settings.mIgnoreOrientationRequest : false;
+ dc.setIgnoreOrientationRequest(ignoreOrientationRequest);
+
+ final int width = hasSizeOverride ? settings.mForcedWidth : dc.mInitialDisplayWidth;
+ final int height = hasSizeOverride ? settings.mForcedHeight : dc.mInitialDisplayHeight;
+ final int density = hasDensityOverride ? settings.mForcedDensity
+ : dc.mInitialDisplayDensity;
dc.updateBaseDisplayMetrics(width, height, density);
- dc.mDisplayScalingDisabled = entry.mForcedScalingMode == FORCE_SCALING_MODE_DISABLED;
+ final int forcedScalingMode = settings.mForcedScalingMode != null
+ ? settings.mForcedScalingMode : FORCE_SCALING_MODE_AUTO;
+ dc.mDisplayScalingDisabled = forcedScalingMode == FORCE_SCALING_MODE_DISABLED;
}
/**
@@ -429,291 +286,281 @@ class DisplayWindowSettings {
return false;
}
- private void readSettings() {
- InputStream stream;
- try {
- stream = mStorage.openRead();
- } catch (IOException e) {
- Slog.i(TAG, "No existing display settings, starting empty");
- return;
- }
- boolean success = false;
- try {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(stream, StandardCharsets.UTF_8.name());
- int type;
- while ((type = parser.next()) != XmlPullParser.START_TAG
- && type != XmlPullParser.END_DOCUMENT) {
- // Do nothing.
- }
-
- if (type != XmlPullParser.START_TAG) {
- throw new IllegalStateException("no start tag found");
+ /**
+ * Provides the functionality to lookup the {@link SettingsEntry settings} for a given
+ * {@link DisplayInfo}.
+ * <p>
+ * NOTE: All interactions with implementations of this provider <b>must</b> be thread-safe
+ * externally.
+ */
+ interface SettingsProvider {
+ /**
+ * Returns the {@link SettingsEntry} for a given {@link DisplayInfo}. The values for the
+ * returned settings are guaranteed to match those previously set with
+ * {@link #updateOverrideSettings(DisplayInfo, SettingsEntry)} with all other values left
+ * to the implementation to determine.
+ */
+ @NonNull
+ SettingsEntry getSettings(@NonNull DisplayInfo info);
+
+ /**
+ * Returns the existing override settings for the given {@link DisplayInfo}. All calls to
+ * {@link #getSettings(DisplayInfo)} for the provided {@code info} are required to have
+ * their values overridden with all set values from the returned {@link SettingsEntry}.
+ *
+ * @see #getSettings(DisplayInfo)
+ * @see #updateOverrideSettings(DisplayInfo, SettingsEntry)
+ */
+ @NonNull
+ SettingsEntry getOverrideSettings(@NonNull DisplayInfo info);
+
+ /**
+ * Updates the override settings for a given {@link DisplayInfo}. All subsequent calls to
+ * {@link #getSettings(DisplayInfo)} for the provided {@link DisplayInfo} are required to
+ * have their values match all set values in {@code overrides}.
+ *
+ * @see #getSettings(DisplayInfo)
+ */
+ void updateOverrideSettings(@NonNull DisplayInfo info, @NonNull SettingsEntry overrides);
+
+ /**
+ * Settings for a display.
+ */
+ class SettingsEntry {
+ int mWindowingMode = WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+ @Nullable
+ Integer mUserRotationMode;
+ @Nullable
+ Integer mUserRotation;
+ int mForcedWidth;
+ int mForcedHeight;
+ int mForcedDensity;
+ @Nullable
+ Integer mForcedScalingMode;
+ int mRemoveContentMode = REMOVE_CONTENT_MODE_UNDEFINED;
+ @Nullable
+ Boolean mShouldShowWithInsecureKeyguard;
+ @Nullable
+ Boolean mShouldShowSystemDecors;
+ @Nullable
+ Boolean mShouldShowIme;
+ @Nullable
+ Integer mFixedToUserRotation;
+ @Nullable
+ Boolean mIgnoreOrientationRequest;
+
+ SettingsEntry() {}
+
+ SettingsEntry(SettingsEntry copyFrom) {
+ setTo(copyFrom);
}
- int outerDepth = parser.getDepth();
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
+ /**
+ * Copies all fields from {@code delta} into this {@link SettingsEntry} object, keeping
+ * track of whether a change has occurred.
+ *
+ * @return {@code true} if this settings have changed as a result of the copy,
+ * {@code false} otherwise.
+ *
+ * @see #updateFrom(SettingsEntry)
+ */
+ boolean setTo(@NonNull SettingsEntry other) {
+ boolean changed = false;
+ if (other.mWindowingMode != mWindowingMode) {
+ mWindowingMode = other.mWindowingMode;
+ changed = true;
}
-
- String tagName = parser.getName();
- if (tagName.equals("display")) {
- readDisplay(parser);
- } else if (tagName.equals("config")) {
- readConfig(parser);
- } else {
- Slog.w(TAG, "Unknown element under <display-settings>: "
- + parser.getName());
- XmlUtils.skipCurrentTag(parser);
+ if (!Objects.equals(other.mUserRotationMode, mUserRotationMode)) {
+ mUserRotationMode = other.mUserRotationMode;
+ changed = true;
}
+ if (!Objects.equals(other.mUserRotation, mUserRotation)) {
+ mUserRotation = other.mUserRotation;
+ changed = true;
+ }
+ if (other.mForcedWidth != mForcedWidth) {
+ mForcedWidth = other.mForcedWidth;
+ changed = true;
+ }
+ if (other.mForcedHeight != mForcedHeight) {
+ mForcedHeight = other.mForcedHeight;
+ changed = true;
+ }
+ if (other.mForcedDensity != mForcedDensity) {
+ mForcedDensity = other.mForcedDensity;
+ changed = true;
+ }
+ if (!Objects.equals(other.mForcedScalingMode, mForcedScalingMode)) {
+ mForcedScalingMode = other.mForcedScalingMode;
+ changed = true;
+ }
+ if (other.mRemoveContentMode != mRemoveContentMode) {
+ mRemoveContentMode = other.mRemoveContentMode;
+ changed = true;
+ }
+ if (other.mShouldShowWithInsecureKeyguard != mShouldShowWithInsecureKeyguard) {
+ mShouldShowWithInsecureKeyguard = other.mShouldShowWithInsecureKeyguard;
+ changed = true;
+ }
+ if (other.mShouldShowSystemDecors != mShouldShowSystemDecors) {
+ mShouldShowSystemDecors = other.mShouldShowSystemDecors;
+ changed = true;
+ }
+ if (other.mShouldShowIme != mShouldShowIme) {
+ mShouldShowIme = other.mShouldShowIme;
+ changed = true;
+ }
+ if (!Objects.equals(other.mFixedToUserRotation, mFixedToUserRotation)) {
+ mFixedToUserRotation = other.mFixedToUserRotation;
+ changed = true;
+ }
+ if (other.mIgnoreOrientationRequest != mIgnoreOrientationRequest) {
+ mIgnoreOrientationRequest = other.mIgnoreOrientationRequest;
+ changed = true;
+ }
+ return changed;
}
- success = true;
- } catch (IllegalStateException e) {
- Slog.w(TAG, "Failed parsing " + e);
- } catch (NullPointerException e) {
- Slog.w(TAG, "Failed parsing " + e);
- } catch (NumberFormatException e) {
- Slog.w(TAG, "Failed parsing " + e);
- } catch (XmlPullParserException e) {
- Slog.w(TAG, "Failed parsing " + e);
- } catch (IOException e) {
- Slog.w(TAG, "Failed parsing " + e);
- } catch (IndexOutOfBoundsException e) {
- Slog.w(TAG, "Failed parsing " + e);
- } finally {
- if (!success) {
- mEntries.clear();
- }
- try {
- stream.close();
- } catch (IOException e) {
- }
- }
- }
-
- private int getIntAttribute(XmlPullParser parser, String name) {
- return getIntAttribute(parser, name, 0 /* defaultValue */);
- }
-
- private int getIntAttribute(XmlPullParser parser, String name, int defaultValue) {
- try {
- final String str = parser.getAttributeValue(null, name);
- return str != null ? Integer.parseInt(str) : defaultValue;
- } catch (NumberFormatException e) {
- return defaultValue;
- }
- }
-
- private boolean getBooleanAttribute(XmlPullParser parser, String name) {
- return getBooleanAttribute(parser, name, false /* defaultValue */);
- }
-
- private boolean getBooleanAttribute(XmlPullParser parser, String name, boolean defaultValue) {
- try {
- final String str = parser.getAttributeValue(null, name);
- return str != null ? Boolean.parseBoolean(str) : defaultValue;
- } catch (NumberFormatException e) {
- return defaultValue;
- }
- }
-
- private void readDisplay(XmlPullParser parser) throws NumberFormatException,
- XmlPullParserException, IOException {
- String name = parser.getAttributeValue(null, "name");
- if (name != null) {
- Entry entry = new Entry(name);
- entry.mWindowingMode = getIntAttribute(parser, "windowingMode",
- WindowConfiguration.WINDOWING_MODE_UNDEFINED);
- entry.mUserRotationMode = getIntAttribute(parser, "userRotationMode",
- WindowManagerPolicy.USER_ROTATION_FREE);
- entry.mUserRotation = getIntAttribute(parser, "userRotation",
- Surface.ROTATION_0);
- entry.mForcedWidth = getIntAttribute(parser, "forcedWidth");
- entry.mForcedHeight = getIntAttribute(parser, "forcedHeight");
- entry.mForcedDensity = getIntAttribute(parser, "forcedDensity");
- entry.mForcedScalingMode = getIntAttribute(parser, "forcedScalingMode",
- FORCE_SCALING_MODE_AUTO);
- entry.mRemoveContentMode = getIntAttribute(parser, "removeContentMode",
- REMOVE_CONTENT_MODE_UNDEFINED);
- entry.mShouldShowWithInsecureKeyguard = getBooleanAttribute(parser,
- "shouldShowWithInsecureKeyguard");
- entry.mShouldShowSystemDecors = getBooleanAttribute(parser, "shouldShowSystemDecors");
- entry.mShouldShowIme = getBooleanAttribute(parser, "shouldShowIme");
- entry.mFixedToUserRotation = getIntAttribute(parser, "fixedToUserRotation");
- entry.mIgnoreOrientationRequest
- = getBooleanAttribute(parser, "ignoreOrientationRequest");
- mEntries.put(name, entry);
- }
- XmlUtils.skipCurrentTag(parser);
- }
-
- private void readConfig(XmlPullParser parser) throws NumberFormatException,
- XmlPullParserException, IOException {
- mIdentifier = getIntAttribute(parser, "identifier");
- XmlUtils.skipCurrentTag(parser);
- }
-
- private void writeSettingsIfNeeded(Entry changedEntry, DisplayInfo displayInfo) {
- if (changedEntry.isEmpty() && !removeEntry(displayInfo)) {
- // The entry didn't exist so nothing is changed and no need to update the file.
- return;
- }
-
- mEntries.put(getIdentifier(displayInfo), changedEntry);
- writeSettings();
- }
-
- private void writeSettings() {
- OutputStream stream;
- try {
- stream = mStorage.startWrite();
- } catch (IOException e) {
- Slog.w(TAG, "Failed to write display settings: " + e);
- return;
- }
-
- try {
- XmlSerializer out = new FastXmlSerializer();
- out.setOutput(stream, StandardCharsets.UTF_8.name());
- out.startDocument(null, true);
- out.startTag(null, "display-settings");
-
- out.startTag(null, "config");
- out.attribute(null, "identifier", Integer.toString(mIdentifier));
- out.endTag(null, "config");
-
- for (Entry entry : mEntries.values()) {
- out.startTag(null, "display");
- out.attribute(null, "name", entry.mName);
- if (entry.mWindowingMode != WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
- out.attribute(null, "windowingMode", Integer.toString(entry.mWindowingMode));
+ /**
+ * Copies the fields from {@code delta} into this {@link SettingsEntry} object, keeping
+ * track of whether a change has occurred. Any undefined fields in {@code delta} are
+ * ignored and not copied into the current {@link SettingsEntry}.
+ *
+ * @return {@code true} if this settings have changed as a result of the copy,
+ * {@code false} otherwise.
+ *
+ * @see #setTo(SettingsEntry)
+ */
+ boolean updateFrom(@NonNull SettingsEntry delta) {
+ boolean changed = false;
+ if (delta.mWindowingMode != WindowConfiguration.WINDOWING_MODE_UNDEFINED
+ && delta.mWindowingMode != mWindowingMode) {
+ mWindowingMode = delta.mWindowingMode;
+ changed = true;
+ }
+ if (delta.mUserRotationMode != null
+ && !Objects.equals(delta.mUserRotationMode, mUserRotationMode)) {
+ mUserRotationMode = delta.mUserRotationMode;
+ changed = true;
}
- if (entry.mUserRotationMode != WindowManagerPolicy.USER_ROTATION_FREE) {
- out.attribute(null, "userRotationMode",
- Integer.toString(entry.mUserRotationMode));
+ if (delta.mUserRotation != null
+ && !Objects.equals(delta.mUserRotation, mUserRotation)) {
+ mUserRotation = delta.mUserRotation;
+ changed = true;
}
- if (entry.mUserRotation != Surface.ROTATION_0) {
- out.attribute(null, "userRotation", Integer.toString(entry.mUserRotation));
+ if (delta.mForcedWidth != 0 && delta.mForcedWidth != mForcedWidth) {
+ mForcedWidth = delta.mForcedWidth;
+ changed = true;
}
- if (entry.mForcedWidth != 0 && entry.mForcedHeight != 0) {
- out.attribute(null, "forcedWidth", Integer.toString(entry.mForcedWidth));
- out.attribute(null, "forcedHeight", Integer.toString(entry.mForcedHeight));
+ if (delta.mForcedHeight != 0 && delta.mForcedHeight != mForcedHeight) {
+ mForcedHeight = delta.mForcedHeight;
+ changed = true;
}
- if (entry.mForcedDensity != 0) {
- out.attribute(null, "forcedDensity", Integer.toString(entry.mForcedDensity));
+ if (delta.mForcedDensity != 0 && delta.mForcedDensity != mForcedDensity) {
+ mForcedDensity = delta.mForcedDensity;
+ changed = true;
}
- if (entry.mForcedScalingMode != FORCE_SCALING_MODE_AUTO) {
- out.attribute(null, "forcedScalingMode",
- Integer.toString(entry.mForcedScalingMode));
+ if (delta.mForcedScalingMode != null
+ && !Objects.equals(delta.mForcedScalingMode, mForcedScalingMode)) {
+ mForcedScalingMode = delta.mForcedScalingMode;
+ changed = true;
}
- if (entry.mRemoveContentMode != REMOVE_CONTENT_MODE_UNDEFINED) {
- out.attribute(null, "removeContentMode",
- Integer.toString(entry.mRemoveContentMode));
+ if (delta.mRemoveContentMode != REMOVE_CONTENT_MODE_UNDEFINED
+ && delta.mRemoveContentMode != mRemoveContentMode) {
+ mRemoveContentMode = delta.mRemoveContentMode;
+ changed = true;
}
- if (entry.mShouldShowWithInsecureKeyguard) {
- out.attribute(null, "shouldShowWithInsecureKeyguard",
- Boolean.toString(entry.mShouldShowWithInsecureKeyguard));
+ if (delta.mShouldShowWithInsecureKeyguard != null
+ && delta.mShouldShowWithInsecureKeyguard
+ != mShouldShowWithInsecureKeyguard) {
+ mShouldShowWithInsecureKeyguard = delta.mShouldShowWithInsecureKeyguard;
+ changed = true;
}
- if (entry.mShouldShowSystemDecors) {
- out.attribute(null, "shouldShowSystemDecors",
- Boolean.toString(entry.mShouldShowSystemDecors));
+ if (delta.mShouldShowSystemDecors != null
+ && delta.mShouldShowSystemDecors != mShouldShowSystemDecors) {
+ mShouldShowSystemDecors = delta.mShouldShowSystemDecors;
+ changed = true;
}
- if (entry.mShouldShowIme) {
- out.attribute(null, "shouldShowIme", Boolean.toString(entry.mShouldShowIme));
+ if (delta.mShouldShowIme != null
+ && delta.mShouldShowIme != mShouldShowIme) {
+ mShouldShowIme = delta.mShouldShowIme;
+ changed = true;
}
- if (entry.mFixedToUserRotation != IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT) {
- out.attribute(null, "fixedToUserRotation",
- Integer.toString(entry.mFixedToUserRotation));
+ if (delta.mFixedToUserRotation != null
+ && !Objects.equals(delta.mFixedToUserRotation, mFixedToUserRotation)) {
+ mFixedToUserRotation = delta.mFixedToUserRotation;
+ changed = true;
}
- if (entry.mIgnoreOrientationRequest) {
- out.attribute(null, "ignoreOrientationRequest",
- Boolean.toString(entry.mIgnoreOrientationRequest));
+ if (delta.mIgnoreOrientationRequest != null
+ && delta.mIgnoreOrientationRequest != mIgnoreOrientationRequest) {
+ mIgnoreOrientationRequest = delta.mIgnoreOrientationRequest;
+ changed = true;
}
- out.endTag(null, "display");
+ return changed;
}
- out.endTag(null, "display-settings");
- out.endDocument();
- mStorage.finishWrite(stream, true /* success */);
- } catch (IOException e) {
- Slog.w(TAG, "Failed to write display window settings.", e);
- mStorage.finishWrite(stream, false /* success */);
- }
- }
-
- /**
- * Removes an entry from {@link #mEntries} cache. Looks up by new and previously used
- * identifiers.
- */
- private boolean removeEntry(DisplayInfo displayInfo) {
- // Remove entry based on primary identifier.
- boolean removed = mEntries.remove(getIdentifier(displayInfo)) != null;
- // Ensure that legacy entries are cleared as well.
- removed |= mEntries.remove(displayInfo.uniqueId) != null;
- removed |= mEntries.remove(displayInfo.name) != null;
- return removed;
- }
-
- /** Gets the identifier of choice for the current config. */
- private String getIdentifier(DisplayInfo displayInfo) {
- if (mIdentifier == IDENTIFIER_PORT && displayInfo.address != null) {
- // Config suggests using port as identifier for physical displays.
- if (displayInfo.address instanceof DisplayAddress.Physical) {
- return "port:" + ((DisplayAddress.Physical) displayInfo.address).getPort();
+ /** @return {@code true} if all values are unset. */
+ boolean isEmpty() {
+ return mWindowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED
+ && mUserRotationMode == null
+ && mUserRotation == null
+ && mForcedWidth == 0 && mForcedHeight == 0 && mForcedDensity == 0
+ && mForcedScalingMode == null
+ && mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED
+ && mShouldShowWithInsecureKeyguard == null
+ && mShouldShowSystemDecors == null
+ && mShouldShowIme == null
+ && mFixedToUserRotation == null
+ && mIgnoreOrientationRequest == null;
}
- }
- return displayInfo.uniqueId;
- }
- private static class AtomicFileStorage implements SettingPersister {
- private final AtomicFile mAtomicFile;
-
- AtomicFileStorage() {
- final File folder = new File(Environment.getDataDirectory(), SYSTEM_DIRECTORY);
- final File settingsFile = new File(folder, DISPLAY_SETTINGS_FILE_NAME);
- // If display_settings.xml doesn't exist, try to copy the vendor's one instead
- // in order to provide the vendor specific initialization.
- if (!settingsFile.exists()) {
- copyVendorSettings(settingsFile);
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SettingsEntry that = (SettingsEntry) o;
+ return mWindowingMode == that.mWindowingMode
+ && mForcedWidth == that.mForcedWidth
+ && mForcedHeight == that.mForcedHeight
+ && mForcedDensity == that.mForcedDensity
+ && mRemoveContentMode == that.mRemoveContentMode
+ && Objects.equals(mUserRotationMode, that.mUserRotationMode)
+ && Objects.equals(mUserRotation, that.mUserRotation)
+ && Objects.equals(mForcedScalingMode, that.mForcedScalingMode)
+ && Objects.equals(mShouldShowWithInsecureKeyguard,
+ that.mShouldShowWithInsecureKeyguard)
+ && Objects.equals(mShouldShowSystemDecors, that.mShouldShowSystemDecors)
+ && Objects.equals(mShouldShowIme, that.mShouldShowIme)
+ && Objects.equals(mFixedToUserRotation, that.mFixedToUserRotation)
+ && Objects.equals(mIgnoreOrientationRequest,
+ that.mIgnoreOrientationRequest);
}
- mAtomicFile = new AtomicFile(settingsFile, WM_DISPLAY_COMMIT_TAG);
- }
- private static void copyVendorSettings(File target) {
- final File vendorFile = new File(Environment.getVendorDirectory(),
- VENDOR_DISPLAY_SETTINGS_PATH);
- if (vendorFile.canRead()) {
- try {
- FileUtils.copy(vendorFile, target);
- } catch (IOException e) {
- Slog.e(TAG, "Failed to copy vendor display_settings.xml");
- }
+ @Override
+ public int hashCode() {
+ return Objects.hash(mWindowingMode, mUserRotationMode, mUserRotation, mForcedWidth,
+ mForcedHeight, mForcedDensity, mForcedScalingMode, mRemoveContentMode,
+ mShouldShowWithInsecureKeyguard, mShouldShowSystemDecors, mShouldShowIme,
+ mFixedToUserRotation, mIgnoreOrientationRequest);
}
- }
-
- @Override
- public InputStream openRead() throws FileNotFoundException {
- return mAtomicFile.openRead();
- }
- @Override
- public OutputStream startWrite() throws IOException {
- return mAtomicFile.startWrite();
- }
-
- @Override
- public void finishWrite(OutputStream os, boolean success) {
- if (!(os instanceof FileOutputStream)) {
- throw new IllegalArgumentException("Unexpected OutputStream as argument: " + os);
- }
- FileOutputStream fos = (FileOutputStream) os;
- if (success) {
- mAtomicFile.finishWrite(fos);
- } else {
- mAtomicFile.failWrite(fos);
+ @Override
+ public String toString() {
+ return "SettingsEntry{"
+ + "mWindowingMode=" + mWindowingMode
+ + ", mUserRotationMode=" + mUserRotationMode
+ + ", mUserRotation=" + mUserRotation
+ + ", mForcedWidth=" + mForcedWidth
+ + ", mForcedHeight=" + mForcedHeight
+ + ", mForcedDensity=" + mForcedDensity
+ + ", mForcedScalingMode=" + mForcedScalingMode
+ + ", mRemoveContentMode=" + mRemoveContentMode
+ + ", mShouldShowWithInsecureKeyguard=" + mShouldShowWithInsecureKeyguard
+ + ", mShouldShowSystemDecors=" + mShouldShowSystemDecors
+ + ", mShouldShowIme=" + mShouldShowIme
+ + ", mFixedToUserRotation=" + mFixedToUserRotation
+ + ", mIgnoreOrientationRequest=" + mIgnoreOrientationRequest
+ + '}';
}
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java
new file mode 100644
index 000000000000..a7f7c480f78f
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettingsProvider.java
@@ -0,0 +1,549 @@
+/*
+ * 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.wm;
+
+import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
+
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.WindowConfiguration;
+import android.os.Environment;
+import android.util.AtomicFile;
+import android.util.Slog;
+import android.util.Xml;
+import android.view.DisplayAddress;
+import android.view.DisplayInfo;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FastXmlSerializer;
+import com.android.internal.util.XmlUtils;
+import com.android.server.wm.DisplayWindowSettings.SettingsProvider;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Implementation of {@link SettingsProvider} that reads the base settings provided in a display
+ * settings file stored in /vendor/etc and then overlays those values with the settings provided in
+ * /data/system.
+ *
+ * @see DisplayWindowSettings
+ */
+class DisplayWindowSettingsProvider implements SettingsProvider {
+ private static final String TAG = TAG_WITH_CLASS_NAME
+ ? "DisplayWindowSettingsProvider" : TAG_WM;
+
+ private static final String DATA_DISPLAY_SETTINGS_FILE_PATH = "system/display_settings.xml";
+ private static final String VENDOR_DISPLAY_SETTINGS_PATH = "etc/display_settings.xml";
+ private static final String WM_DISPLAY_COMMIT_TAG = "wm-displays";
+
+ private static final int IDENTIFIER_UNIQUE_ID = 0;
+ private static final int IDENTIFIER_PORT = 1;
+ @IntDef(prefix = { "IDENTIFIER_" }, value = {
+ IDENTIFIER_UNIQUE_ID,
+ IDENTIFIER_PORT,
+ })
+ @interface DisplayIdentifierType {}
+
+ /** Interface that allows reading the display window settings. */
+ interface ReadableSettingsStorage {
+ InputStream openRead() throws IOException;
+ }
+
+ /** Interface that allows reading and writing the display window settings. */
+ interface WritableSettingsStorage extends ReadableSettingsStorage {
+ OutputStream startWrite() throws IOException;
+ void finishWrite(OutputStream os, boolean success);
+ }
+
+ private final ReadableSettingsStorage mVendorSettingsStorage;
+ /**
+ * The preferred type of a display identifier to use when storing and retrieving entries from
+ * the base (vendor) settings file.
+ *
+ * @see #getIdentifier(DisplayInfo, int)
+ */
+ @DisplayIdentifierType
+ private int mVendorIdentifierType;
+ private final Map<String, SettingsEntry> mVendorSettings = new HashMap<>();
+
+ private final WritableSettingsStorage mOverrideSettingsStorage;
+ /**
+ * The preferred type of a display identifier to use when storing and retrieving entries from
+ * the data (override) settings file.
+ *
+ * @see #getIdentifier(DisplayInfo, int)
+ */
+ @DisplayIdentifierType
+ private int mOverrideIdentifierType;
+ private final Map<String, SettingsEntry> mOverrideSettings = new HashMap<>();
+
+ /**
+ * Enables or disables settings provided from the vendor settings storage.
+ *
+ * @see #setVendorSettingsIgnored(boolean)
+ */
+ private boolean mIgnoreVendorSettings = true;
+
+ DisplayWindowSettingsProvider() {
+ this(new AtomicFileStorage(getVendorSettingsFile()),
+ new AtomicFileStorage(getOverrideSettingsFile()));
+ }
+
+ @VisibleForTesting
+ DisplayWindowSettingsProvider(@NonNull ReadableSettingsStorage vendorSettingsStorage,
+ @NonNull WritableSettingsStorage overrideSettingsStorage) {
+ mVendorSettingsStorage = vendorSettingsStorage;
+ mOverrideSettingsStorage = overrideSettingsStorage;
+ readSettings();
+ }
+
+ /**
+ * Enables or disables settings provided from the vendor settings storage. If {@code true}, the
+ * vendor settings will be ignored and only the override settings will be returned from
+ * {@link #getSettings(DisplayInfo)}. If {@code false}, settings returned from
+ * {@link #getSettings(DisplayInfo)} will be a merged result of the vendor settings and the
+ * override settings.
+ */
+ void setVendorSettingsIgnored(boolean ignored) {
+ mIgnoreVendorSettings = ignored;
+ }
+
+ /**
+ * Returns whether or not the vendor settings are being ignored.
+ *
+ * @see #setVendorSettingsIgnored(boolean)
+ */
+ @VisibleForTesting
+ boolean getVendorSettingsIgnored() {
+ return mIgnoreVendorSettings;
+ }
+
+ @Override
+ @NonNull
+ public SettingsEntry getSettings(@NonNull DisplayInfo info) {
+ SettingsEntry vendorSettings = getVendorSettingsEntry(info);
+ SettingsEntry overrideSettings = getOrCreateOverrideSettingsEntry(info);
+ if (vendorSettings == null) {
+ return new SettingsEntry(overrideSettings);
+ } else {
+ SettingsEntry mergedSettings = new SettingsEntry(vendorSettings);
+ mergedSettings.updateFrom(overrideSettings);
+ return mergedSettings;
+ }
+ }
+
+ @Override
+ @NonNull
+ public SettingsEntry getOverrideSettings(@NonNull DisplayInfo info) {
+ return new SettingsEntry(getOrCreateOverrideSettingsEntry(info));
+ }
+
+ @Override
+ public void updateOverrideSettings(@NonNull DisplayInfo info,
+ @NonNull SettingsEntry overrides) {
+ final SettingsEntry overrideSettings = getOrCreateOverrideSettingsEntry(info);
+ boolean changed = overrideSettings.setTo(overrides);
+ if (changed) {
+ writeOverrideSettings();
+ }
+ }
+
+ @Nullable
+ private SettingsEntry getVendorSettingsEntry(DisplayInfo info) {
+ if (mIgnoreVendorSettings) {
+ return null;
+ }
+
+ final String identifier = getIdentifier(info, mVendorIdentifierType);
+ SettingsEntry settings;
+ // Try to get corresponding settings using preferred identifier for the current config.
+ if ((settings = mVendorSettings.get(identifier)) != null) {
+ return settings;
+ }
+ // Else, fall back to the display name.
+ if ((settings = mVendorSettings.get(info.name)) != null) {
+ // Found an entry stored with old identifier.
+ mVendorSettings.remove(info.name);
+ mVendorSettings.put(identifier, settings);
+ return settings;
+ }
+ return null;
+ }
+
+ @NonNull
+ private SettingsEntry getOrCreateOverrideSettingsEntry(DisplayInfo info) {
+ final String identifier = getIdentifier(info, mOverrideIdentifierType);
+ SettingsEntry settings;
+ // Try to get corresponding settings using preferred identifier for the current config.
+ if ((settings = mOverrideSettings.get(identifier)) != null) {
+ return settings;
+ }
+ // Else, fall back to the display name.
+ if ((settings = mOverrideSettings.get(info.name)) != null) {
+ // Found an entry stored with old identifier.
+ mOverrideSettings.remove(info.name);
+ mOverrideSettings.put(identifier, settings);
+ writeOverrideSettings();
+ return settings;
+ }
+
+ settings = new SettingsEntry();
+ mOverrideSettings.put(identifier, settings);
+ return settings;
+ }
+
+ private void readSettings() {
+ FileData vendorFileData = readSettings(mVendorSettingsStorage);
+ if (vendorFileData != null) {
+ mVendorIdentifierType = vendorFileData.mIdentifierType;
+ mVendorSettings.putAll(vendorFileData.mSettings);
+ }
+
+ FileData overrideFileData = readSettings(mOverrideSettingsStorage);
+ if (overrideFileData != null) {
+ mOverrideIdentifierType = overrideFileData.mIdentifierType;
+ mOverrideSettings.putAll(overrideFileData.mSettings);
+ }
+ }
+
+ private void writeOverrideSettings() {
+ FileData fileData = new FileData();
+ fileData.mIdentifierType = mOverrideIdentifierType;
+ fileData.mSettings.putAll(mOverrideSettings);
+ writeSettings(mOverrideSettingsStorage, fileData);
+ }
+
+ /** Gets the identifier of choice for the current config. */
+ private static String getIdentifier(DisplayInfo displayInfo, @DisplayIdentifierType int type) {
+ if (type == IDENTIFIER_PORT && displayInfo.address != null) {
+ // Config suggests using port as identifier for physical displays.
+ if (displayInfo.address instanceof DisplayAddress.Physical) {
+ return "port:" + ((DisplayAddress.Physical) displayInfo.address).getPort();
+ }
+ }
+ return displayInfo.uniqueId;
+ }
+
+ @NonNull
+ private static AtomicFile getVendorSettingsFile() {
+ final File vendorFile = new File(Environment.getVendorDirectory(),
+ VENDOR_DISPLAY_SETTINGS_PATH);
+ return new AtomicFile(vendorFile, WM_DISPLAY_COMMIT_TAG);
+ }
+
+ @NonNull
+ private static AtomicFile getOverrideSettingsFile() {
+ final File overrideSettingsFile = new File(Environment.getDataDirectory(),
+ DATA_DISPLAY_SETTINGS_FILE_PATH);
+ return new AtomicFile(overrideSettingsFile, WM_DISPLAY_COMMIT_TAG);
+ }
+
+ @Nullable
+ private static FileData readSettings(ReadableSettingsStorage storage) {
+ InputStream stream;
+ try {
+ stream = storage.openRead();
+ } catch (IOException e) {
+ Slog.i(TAG, "No existing display settings, starting empty");
+ return null;
+ }
+ FileData fileData = new FileData();
+ boolean success = false;
+ try {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(stream, StandardCharsets.UTF_8.name());
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // Do nothing.
+ }
+
+ if (type != XmlPullParser.START_TAG) {
+ throw new IllegalStateException("no start tag found");
+ }
+
+ int outerDepth = parser.getDepth();
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ String tagName = parser.getName();
+ if (tagName.equals("display")) {
+ readDisplay(parser, fileData);
+ } else if (tagName.equals("config")) {
+ readConfig(parser, fileData);
+ } else {
+ Slog.w(TAG, "Unknown element under <display-settings>: "
+ + parser.getName());
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+ success = true;
+ } catch (IllegalStateException e) {
+ Slog.w(TAG, "Failed parsing " + e);
+ } catch (NullPointerException e) {
+ Slog.w(TAG, "Failed parsing " + e);
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "Failed parsing " + e);
+ } catch (XmlPullParserException e) {
+ Slog.w(TAG, "Failed parsing " + e);
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed parsing " + e);
+ } catch (IndexOutOfBoundsException e) {
+ Slog.w(TAG, "Failed parsing " + e);
+ } finally {
+ try {
+ stream.close();
+ } catch (IOException ignored) {
+ }
+ }
+ if (!success) {
+ fileData.mSettings.clear();
+ }
+ return fileData;
+ }
+
+ private static int getIntAttribute(XmlPullParser parser, String name, int defaultValue) {
+ try {
+ final String str = parser.getAttributeValue(null, name);
+ return str != null ? Integer.parseInt(str) : defaultValue;
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "Failed to parse display window settings attribute: " + name, e);
+ return defaultValue;
+ }
+ }
+
+ @Nullable
+ private static Integer getIntegerAttribute(XmlPullParser parser, String name,
+ @Nullable Integer defaultValue) {
+ try {
+ final String str = parser.getAttributeValue(null, name);
+ return str != null ? Integer.valueOf(str) : defaultValue;
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "Failed to parse display window settings attribute: " + name, e);
+ return defaultValue;
+ }
+ }
+
+ @Nullable
+ private static Boolean getBooleanAttribute(XmlPullParser parser, String name,
+ @Nullable Boolean defaultValue) {
+ final String str = parser.getAttributeValue(null, name);
+ return str != null ? Boolean.valueOf(str) : defaultValue;
+ }
+
+ private static void readDisplay(XmlPullParser parser, FileData fileData)
+ throws NumberFormatException, XmlPullParserException, IOException {
+ String name = parser.getAttributeValue(null, "name");
+ if (name != null) {
+ SettingsEntry settingsEntry = new SettingsEntry();
+ settingsEntry.mWindowingMode = getIntAttribute(parser, "windowingMode",
+ WindowConfiguration.WINDOWING_MODE_UNDEFINED /* defaultValue */);
+ settingsEntry.mUserRotationMode = getIntegerAttribute(parser, "userRotationMode",
+ null /* defaultValue */);
+ settingsEntry.mUserRotation = getIntegerAttribute(parser, "userRotation",
+ null /* defaultValue */);
+ settingsEntry.mForcedWidth = getIntAttribute(parser, "forcedWidth",
+ 0 /* defaultValue */);
+ settingsEntry.mForcedHeight = getIntAttribute(parser, "forcedHeight",
+ 0 /* defaultValue */);
+ settingsEntry.mForcedDensity = getIntAttribute(parser, "forcedDensity",
+ 0 /* defaultValue */);
+ settingsEntry.mForcedScalingMode = getIntegerAttribute(parser, "forcedScalingMode",
+ null /* defaultValue */);
+ settingsEntry.mRemoveContentMode = getIntAttribute(parser, "removeContentMode",
+ REMOVE_CONTENT_MODE_UNDEFINED /* defaultValue */);
+ settingsEntry.mShouldShowWithInsecureKeyguard = getBooleanAttribute(parser,
+ "shouldShowWithInsecureKeyguard", null /* defaultValue */);
+ settingsEntry.mShouldShowSystemDecors = getBooleanAttribute(parser,
+ "shouldShowSystemDecors", null /* defaultValue */);
+ settingsEntry.mShouldShowIme = getBooleanAttribute(parser, "shouldShowIme",
+ null /* defaultValue */);
+ settingsEntry.mFixedToUserRotation = getIntegerAttribute(parser, "fixedToUserRotation",
+ null /* defaultValue */);
+ settingsEntry.mIgnoreOrientationRequest = getBooleanAttribute(parser,
+ "ignoreOrientationRequest", null /* defaultValue */);
+ fileData.mSettings.put(name, settingsEntry);
+ }
+ XmlUtils.skipCurrentTag(parser);
+ }
+
+ private static void readConfig(XmlPullParser parser, FileData fileData)
+ throws NumberFormatException,
+ XmlPullParserException, IOException {
+ fileData.mIdentifierType = getIntAttribute(parser, "identifier",
+ IDENTIFIER_UNIQUE_ID);
+ XmlUtils.skipCurrentTag(parser);
+ }
+
+ private static void writeSettings(WritableSettingsStorage storage, FileData data) {
+ OutputStream stream;
+ try {
+ stream = storage.startWrite();
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to write display settings: " + e);
+ return;
+ }
+
+ boolean success = false;
+ try {
+ XmlSerializer out = new FastXmlSerializer();
+ out.setOutput(stream, StandardCharsets.UTF_8.name());
+ out.startDocument(null, true);
+
+ out.startTag(null, "display-settings");
+
+ out.startTag(null, "config");
+ out.attribute(null, "identifier",
+ Integer.toString(data.mIdentifierType));
+ out.endTag(null, "config");
+
+ for (Map.Entry<String, SettingsEntry> entry
+ : data.mSettings.entrySet()) {
+ String displayIdentifier = entry.getKey();
+ SettingsEntry settingsEntry = entry.getValue();
+ if (settingsEntry.isEmpty()) {
+ continue;
+ }
+
+ out.startTag(null, "display");
+ out.attribute(null, "name", displayIdentifier);
+ if (settingsEntry.mWindowingMode != WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
+ out.attribute(null, "windowingMode",
+ Integer.toString(settingsEntry.mWindowingMode));
+ }
+ if (settingsEntry.mUserRotationMode != null) {
+ out.attribute(null, "userRotationMode",
+ settingsEntry.mUserRotationMode.toString());
+ }
+ if (settingsEntry.mUserRotation != null) {
+ out.attribute(null, "userRotation",
+ settingsEntry.mUserRotation.toString());
+ }
+ if (settingsEntry.mForcedWidth != 0 && settingsEntry.mForcedHeight != 0) {
+ out.attribute(null, "forcedWidth",
+ Integer.toString(settingsEntry.mForcedWidth));
+ out.attribute(null, "forcedHeight",
+ Integer.toString(settingsEntry.mForcedHeight));
+ }
+ if (settingsEntry.mForcedDensity != 0) {
+ out.attribute(null, "forcedDensity",
+ Integer.toString(settingsEntry.mForcedDensity));
+ }
+ if (settingsEntry.mForcedScalingMode != null) {
+ out.attribute(null, "forcedScalingMode",
+ settingsEntry.mForcedScalingMode.toString());
+ }
+ if (settingsEntry.mRemoveContentMode != REMOVE_CONTENT_MODE_UNDEFINED) {
+ out.attribute(null, "removeContentMode",
+ Integer.toString(settingsEntry.mRemoveContentMode));
+ }
+ if (settingsEntry.mShouldShowWithInsecureKeyguard != null) {
+ out.attribute(null, "shouldShowWithInsecureKeyguard",
+ settingsEntry.mShouldShowWithInsecureKeyguard.toString());
+ }
+ if (settingsEntry.mShouldShowSystemDecors != null) {
+ out.attribute(null, "shouldShowSystemDecors",
+ settingsEntry.mShouldShowSystemDecors.toString());
+ }
+ if (settingsEntry.mShouldShowIme != null) {
+ out.attribute(null, "shouldShowIme",
+ settingsEntry.mShouldShowIme.toString());
+ }
+ if (settingsEntry.mFixedToUserRotation != null) {
+ out.attribute(null, "fixedToUserRotation",
+ settingsEntry.mFixedToUserRotation.toString());
+ }
+ if (settingsEntry.mIgnoreOrientationRequest != null) {
+ out.attribute(null, "ignoreOrientationRequest",
+ settingsEntry.mIgnoreOrientationRequest.toString());
+ }
+ out.endTag(null, "display");
+ }
+
+ out.endTag(null, "display-settings");
+ out.endDocument();
+ success = true;
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to write display window settings.", e);
+ } finally {
+ storage.finishWrite(stream, success);
+ }
+ }
+
+ private static final class FileData {
+ int mIdentifierType;
+ final Map<String, SettingsEntry> mSettings = new HashMap<>();
+
+ @Override
+ public String toString() {
+ return "FileData{"
+ + "mIdentifierType=" + mIdentifierType
+ + ", mSettings=" + mSettings
+ + '}';
+ }
+ }
+
+ private static final class AtomicFileStorage implements WritableSettingsStorage {
+ private final AtomicFile mAtomicFile;
+
+ AtomicFileStorage(@NonNull AtomicFile atomicFile) {
+ mAtomicFile = atomicFile;
+ }
+
+ @Override
+ public InputStream openRead() throws FileNotFoundException {
+ return mAtomicFile.openRead();
+ }
+
+ @Override
+ public OutputStream startWrite() throws IOException {
+ return mAtomicFile.startWrite();
+ }
+
+ @Override
+ public void finishWrite(OutputStream os, boolean success) {
+ if (!(os instanceof FileOutputStream)) {
+ throw new IllegalArgumentException("Unexpected OutputStream as argument: " + os);
+ }
+ FileOutputStream fos = (FileOutputStream) os;
+ if (success) {
+ mAtomicFile.finishWrite(fos);
+ } else {
+ mAtomicFile.failWrite(fos);
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
index 0813b4f9efe0..818d96ceb5a6 100644
--- a/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/ImeInsetsSourceProvider.java
@@ -16,11 +16,14 @@
package com.android.server.wm;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
import static com.android.server.wm.ImeInsetsSourceProviderProto.IME_TARGET_FROM_IME;
import static com.android.server.wm.ImeInsetsSourceProviderProto.INSETS_SOURCE_PROVIDER;
import static com.android.server.wm.ImeInsetsSourceProviderProto.IS_IME_LAYOUT_DRAWN;
+import android.os.Trace;
import android.util.proto.ProtoOutputStream;
import android.view.InsetsSource;
import android.view.WindowInsets;
@@ -79,6 +82,7 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider {
ProtoLog.i(WM_DEBUG_IME, "call showInsets(ime) on %s",
target.getWindow() != null ? target.getWindow().getName() : "");
target.showInsets(WindowInsets.Type.ime(), true /* fromIme */);
+ Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "WMS.showImePostLayout", 0);
if (target != mImeTargetFromIme && mImeTargetFromIme != null) {
ProtoLog.w(WM_DEBUG_IME,
"showInsets(ime) was requested by different window: %s ",
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index e7f140f989cc..773bf542e212 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -18,6 +18,7 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
@@ -35,6 +36,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration.WindowingMode;
+import android.os.Trace;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.SparseArray;
@@ -281,6 +283,7 @@ class InsetsStateController {
* Called when a layout pass has occurred.
*/
void onPostLayout() {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "ISC.onPostLayout");
for (int i = mProviders.size() - 1; i >= 0; i--) {
mProviders.valueAt(i).onPostLayout();
}
@@ -297,6 +300,7 @@ class InsetsStateController {
}
}
winInsetsChanged.clear();
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
void onInsetsModified(InsetsControlTarget caller) {
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index b33c2f2823a5..5b7b5a122b42 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -24,6 +24,8 @@ import static android.content.Context.DEVICE_POLICY_SERVICE;
import static android.content.Context.STATUS_BAR_SERVICE;
import static android.content.Intent.ACTION_CALL_EMERGENCY;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
+import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
+import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_CURRENT;
@@ -33,11 +35,6 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LOCKTASK;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
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.Task.LOCK_TASK_AUTH_ALLOWLISTED;
-import static com.android.server.wm.Task.LOCK_TASK_AUTH_DONT_LOCK;
-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_PINNABLE;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -129,6 +126,18 @@ public class LockTaskController {
/** Tag used for disabling of keyguard */
private static final String LOCK_TASK_TAG = "Lock-to-App";
+ /** Can't be put in lockTask mode. */
+ static final int LOCK_TASK_AUTH_DONT_LOCK = 0;
+ /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
+ static final int LOCK_TASK_AUTH_PINNABLE = 1;
+ /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
+ static final int LOCK_TASK_AUTH_LAUNCHABLE = 2;
+ /** Can enter lockTask without user approval. Can start over existing lockTask task. */
+ static final int LOCK_TASK_AUTH_ALLOWLISTED = 3;
+ /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
+ * lockTask task. */
+ static final int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
+
private final IBinder mToken = new LockTaskToken();
private final ActivityStackSupervisor mSupervisor;
private final Context mContext;
@@ -265,11 +274,10 @@ public class LockTaskController {
}
/**
- * @return whether the requested task is allowed to be locked (either allowlisted, or declares
- * lockTaskMode="always" in the manifest).
+ * @return whether the requested task auth is allowed to be locked.
*/
- boolean isTaskAllowlisted(Task task) {
- switch(task.mLockTaskAuth) {
+ static boolean isTaskAuthAllowlisted(int lockTaskAuth) {
+ switch(lockTaskAuth) {
case LOCK_TASK_AUTH_ALLOWLISTED:
case LOCK_TASK_AUTH_LAUNCHABLE:
case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
@@ -293,7 +301,30 @@ public class LockTaskController {
* @return whether the requested task is disallowed to be launched.
*/
boolean isLockTaskModeViolation(Task task, boolean isNewClearTask) {
- if (isLockTaskModeViolationInternal(task, isNewClearTask)) {
+ // TODO: Double check what's going on here. If the task is already in lock task mode, it's
+ // likely allowlisted, so will return false below.
+ if (isTaskLocked(task) && !isNewClearTask) {
+ // If the task is already at the top and won't be cleared, then allow the operation
+ } else if (isLockTaskModeViolationInternal(task, task.mUserId, task.intent,
+ task.mLockTaskAuth)) {
+ showLockTaskToast();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @param activity an activity that is going to be started in a new task as the root activity.
+ * @return whether the given activity is allowed to be launched.
+ */
+ boolean isNewTaskLockTaskModeViolation(ActivityRecord activity) {
+ // Use the belong task (if any) to perform the lock task checks
+ if (activity.getTask() != null) {
+ return isLockTaskModeViolation(activity.getTask());
+ }
+
+ int auth = getLockTaskAuth(activity, null /* task */);
+ if (isLockTaskModeViolationInternal(activity, activity.mUserId, activity.intent, auth)) {
showLockTaskToast();
return true;
}
@@ -310,25 +341,19 @@ public class LockTaskController {
return mLockTaskModeTasks.get(0);
}
- private boolean isLockTaskModeViolationInternal(Task task, boolean isNewClearTask) {
- // TODO: Double check what's going on here. If the task is already in lock task mode, it's
- // likely allowlisted, so will return false below.
- if (isTaskLocked(task) && !isNewClearTask) {
- // If the task is already at the top and won't be cleared, then allow the operation
- return false;
- }
-
+ private boolean isLockTaskModeViolationInternal(WindowContainer wc, int userId,
+ Intent intent, int taskAuth) {
// Allow recents activity if enabled by policy
- if (task.isActivityTypeRecents() && isRecentsAllowed(task.mUserId)) {
+ if (wc.isActivityTypeRecents() && isRecentsAllowed(userId)) {
return false;
}
// Allow emergency calling when the device is protected by a locked keyguard
- if (isKeyguardAllowed(task.mUserId) && isEmergencyCallTask(task)) {
+ if (isKeyguardAllowed(userId) && isEmergencyCallIntent(intent)) {
return false;
}
- return !(isTaskAllowlisted(task) || mLockTaskModeTasks.isEmpty());
+ return !(isTaskAuthAllowlisted(taskAuth) || mLockTaskModeTasks.isEmpty());
}
private boolean isRecentsAllowed(int userId) {
@@ -360,8 +385,7 @@ public class LockTaskController {
return isPackageAllowlisted(userId, packageName);
}
- private boolean isEmergencyCallTask(Task task) {
- final Intent intent = task.intent;
+ private boolean isEmergencyCallIntent(Intent intent) {
if (intent == null) {
return false;
}
@@ -697,6 +721,40 @@ public class LockTaskController {
}
}
+ int getLockTaskAuth(@Nullable ActivityRecord rootActivity, @Nullable Task task) {
+ if (rootActivity == null && task == null) {
+ return LOCK_TASK_AUTH_DONT_LOCK;
+ }
+ if (rootActivity == null) {
+ return LOCK_TASK_AUTH_PINNABLE;
+ }
+
+ final String pkg = (task == null || task.realActivity == null) ? null
+ : task.realActivity.getPackageName();
+ final int userId = task != null ? task.mUserId : rootActivity.mUserId;
+ int lockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
+ switch (rootActivity.lockTaskLaunchMode) {
+ case LOCK_TASK_LAUNCH_MODE_DEFAULT:
+ lockTaskAuth = isPackageAllowlisted(userId, pkg)
+ ? LOCK_TASK_AUTH_ALLOWLISTED : LOCK_TASK_AUTH_PINNABLE;
+ break;
+
+ case LOCK_TASK_LAUNCH_MODE_NEVER:
+ lockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
+ break;
+
+ case LOCK_TASK_LAUNCH_MODE_ALWAYS:
+ lockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
+ break;
+
+ case LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED:
+ lockTaskAuth = isPackageAllowlisted(userId, pkg)
+ ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
+ break;
+ }
+ return lockTaskAuth;
+ }
+
boolean isPackageAllowlisted(int userId, String pkg) {
if (pkg == null) {
return false;
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 0503c0de5195..45cd35977168 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -658,8 +658,8 @@ class RecentTasks {
}
for (int i = mTasks.size() - 1; i >= 0; --i) {
final Task task = mTasks.get(i);
- if (task.mUserId == userId
- && !mService.getLockTaskController().isTaskAllowlisted(task)) {
+ if (task.mUserId == userId && !mService.getLockTaskController().isTaskAuthAllowlisted(
+ task.mLockTaskAuth)) {
remove(task);
}
}
@@ -1874,11 +1874,23 @@ class RecentTasks {
* Creates a new RecentTaskInfo from a Task.
*/
ActivityManager.RecentTaskInfo createRecentTaskInfo(Task tr, boolean stripExtras) {
- ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
+ final ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
tr.fillTaskInfo(rti, stripExtras);
- // Fill in some deprecated values
+ // Fill in some deprecated values.
rti.id = rti.isRunning ? rti.taskId : INVALID_TASK_ID;
rti.persistentId = rti.taskId;
+
+ // Fill in organized child task info for the task created by organizer.
+ if (tr.mCreatedByOrganizer) {
+ for (int i = tr.getChildCount() - 1; i >= 0; i--) {
+ final Task childTask = tr.getChildAt(i).asTask();
+ if (childTask != null && childTask.isOrganized()) {
+ final ActivityManager.RecentTaskInfo cti = new ActivityManager.RecentTaskInfo();
+ childTask.fillTaskInfo(cti);
+ rti.childrenTaskInfos.add(cti);
+ }
+ }
+ }
return rti;
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 04b303053d8f..757c57f94a36 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2728,8 +2728,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}, true /* traverseTopToBottom */);
for (int i = mTmpTaskLayerChangedProcs.size() - 1; i >= 0; i--) {
- mTmpTaskLayerChangedProcs.valueAt(i).invalidateOomScoreReferenceState(
- true /* computeNow */);
+ mTmpTaskLayerChangedProcs.valueAt(i).computeProcessActivityState();
}
mTmpTaskLayerChangedProcs.clear();
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index c51e63f5f8c0..54a66cce9b25 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -43,10 +43,6 @@ import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
@@ -120,12 +116,16 @@ import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
+import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_ALLOWLISTED;
+import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_DONT_LOCK;
+import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE;
+import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
+import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_PINNABLE;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.Task.ActivityState.PAUSED;
import static com.android.server.wm.Task.ActivityState.PAUSING;
import static com.android.server.wm.Task.ActivityState.RESUMED;
import static com.android.server.wm.Task.ActivityState.STARTED;
-import static com.android.server.wm.Task.ActivityState.STOPPED;
import static com.android.server.wm.Task.ActivityState.STOPPING;
import static com.android.server.wm.TaskProto.ACTIVITY_TYPE;
import static com.android.server.wm.TaskProto.BOUNDS;
@@ -408,17 +408,6 @@ class Task extends WindowContainer<WindowContainer> {
boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
// was changed.
- /** Can't be put in lockTask mode. */
- final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
- /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
- final static int LOCK_TASK_AUTH_PINNABLE = 1;
- /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
- final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
- /** Can enter lockTask without user approval. Can start over existing lockTask task. */
- final static int LOCK_TASK_AUTH_ALLOWLISTED = 3;
- /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
- * lockTask task. */
- final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
int mLockTaskUid = -1; // The uid of the application that called startLockTask().
@@ -1942,32 +1931,7 @@ class Task extends WindowContainer<WindowContainer> {
}
private void setLockTaskAuth(@Nullable ActivityRecord r) {
- if (r == null) {
- mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
- return;
- }
-
- final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
- final LockTaskController lockTaskController = mAtmService.getLockTaskController();
- switch (r.lockTaskLaunchMode) {
- case LOCK_TASK_LAUNCH_MODE_DEFAULT:
- mLockTaskAuth = lockTaskController.isPackageAllowlisted(mUserId, pkg)
- ? LOCK_TASK_AUTH_ALLOWLISTED : LOCK_TASK_AUTH_PINNABLE;
- break;
-
- case LOCK_TASK_LAUNCH_MODE_NEVER:
- mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
- break;
-
- case LOCK_TASK_LAUNCH_MODE_ALWAYS:
- mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
- break;
-
- case LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED:
- mLockTaskAuth = lockTaskController.isPackageAllowlisted(mUserId, pkg)
- ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
- break;
- }
+ mLockTaskAuth = mAtmService.getLockTaskController().getLockTaskAuth(r, this);
ProtoLog.d(WM_DEBUG_LOCKTASK, "setLockTaskAuth: task=%s mLockTaskAuth=%s", this,
lockTaskAuthToString());
}
@@ -4127,6 +4091,10 @@ class Task extends WindowContainer<WindowContainer> {
forAllActivities(r -> {
info.addLaunchCookie(r.mLaunchCookie);
});
+ final Task rootTask = getRootTask();
+ info.parentTaskId = rootTask == getParent() && rootTask.mCreatedByOrganizer
+ ? rootTask.mTaskId
+ : INVALID_TASK_ID;
}
@Nullable PictureInPictureParams getPictureInPictureParams() {
@@ -4843,6 +4811,17 @@ class Task extends WindowContainer<WindowContainer> {
return mTaskOrganizer != null;
}
+ private boolean canBeOrganized() {
+ // All root tasks can be organized
+ if (isRootTask()) {
+ return true;
+ }
+
+ // Task could be organized if it's the direct child of the root created by organizer.
+ final Task rootTask = getRootTask();
+ return rootTask == getParent() && rootTask.mCreatedByOrganizer;
+ }
+
@Override
boolean showSurfaceOnCreation() {
// Organized tasks handle their own surface visibility
@@ -4991,7 +4970,7 @@ class Task extends WindowContainer<WindowContainer> {
// is created.
return false;
}
- if (!isRootTask()) {
+ if (!canBeOrganized()) {
return setTaskOrganizer(null);
}
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 2c39c2b4a98e..a1c5670ec9af 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -160,18 +160,20 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
return;
}
ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task info changed taskId=%d", task.mTaskId);
- if (!task.isOrganized()) {
- // This is safe to ignore if the task is no longer organized
- return;
- }
- try {
- // Purposely notify of task info change immediately instead of deferring (like
- // appear and vanish) to allow info changes (such as new PIP params) to flow
- // without waiting.
- mTaskOrganizer.onTaskInfoChanged(taskInfo);
- } catch (RemoteException e) {
- Slog.e(TAG, "Exception sending onTaskInfoChanged callback", e);
- }
+ mDeferTaskOrgCallbacksConsumer.accept(() -> {
+ if (!task.isOrganized()) {
+ // This is safe to ignore if the task is no longer organized
+ return;
+ }
+ try {
+ // Purposely notify of task info change immediately instead of deferring (like
+ // appear and vanish) to allow info changes (such as new PIP params) to flow
+ // without waiting.
+ mTaskOrganizer.onTaskInfoChanged(taskInfo);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Exception sending onTaskInfoChanged callback", e);
+ }
+ });
}
void onBackPressedOnTaskRoot(Task task) {
@@ -181,15 +183,17 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
// Skip if the task has not yet received taskAppeared().
return;
}
- if (!task.isOrganized()) {
- // This is safe to ignore if the task is no longer organized
- return;
- }
- try {
- mTaskOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo());
- } catch (Exception e) {
- Slog.e(TAG, "Exception sending onBackPressedOnTaskRoot callback", e);
- }
+ mDeferTaskOrgCallbacksConsumer.accept(() -> {
+ if (!task.isOrganized()) {
+ // This is safe to ignore if the task is no longer organized
+ return;
+ }
+ try {
+ mTaskOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo());
+ } catch (Exception e) {
+ Slog.e(TAG, "Exception sending onBackPressedOnTaskRoot callback", e);
+ }
+ });
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 084b7667b5a5..b8bf94c33ef1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -44,6 +44,7 @@ import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDO
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
+import static android.provider.Settings.Global.DEVELOPMENT_IGNORE_VENDOR_DISPLAY_SETTINGS;
import static android.provider.Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -197,7 +198,6 @@ import android.os.SystemService;
import android.os.Trace;
import android.os.UserHandle;
import android.os.WorkSource;
-import android.provider.DeviceConfig;
import android.provider.Settings;
import android.service.vr.IVrManager;
import android.service.vr.IVrStateCallbacks;
@@ -576,6 +576,7 @@ public class WindowManagerService extends IWindowManager.Stub
final PackageManagerInternal mPmInternal;
private final TestUtilityService mTestUtilityService;
+ final DisplayWindowSettingsProvider mDisplayWindowSettingsProvider;
final DisplayWindowSettings mDisplayWindowSettings;
/** If the system should display notifications for apps displaying an alert window. */
@@ -799,6 +800,8 @@ public class WindowManagerService extends IWindowManager.Stub
DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM);
private final Uri mRenderShadowsInCompositorUri = Settings.Global.getUriFor(
DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR);
+ private final Uri mIgnoreVendorDisplaySettingsUri = Settings.Global.getUriFor(
+ DEVELOPMENT_IGNORE_VENDOR_DISPLAY_SETTINGS);
public SettingsObserver() {
super(new Handler());
@@ -823,6 +826,8 @@ public class WindowManagerService extends IWindowManager.Stub
UserHandle.USER_ALL);
resolver.registerContentObserver(mRenderShadowsInCompositorUri, false, this,
UserHandle.USER_ALL);
+ resolver.registerContentObserver(mIgnoreVendorDisplaySettingsUri, false, this,
+ UserHandle.USER_ALL);
}
@Override
@@ -866,6 +871,11 @@ public class WindowManagerService extends IWindowManager.Stub
return;
}
+ if (mIgnoreVendorDisplaySettingsUri.equals(uri)) {
+ updateIgnoreVendorDisplaySettings();
+ return;
+ }
+
@UpdateAnimationScaleMode
final int mode;
if (mWindowAnimationScaleUri.equals(uri)) {
@@ -955,6 +965,19 @@ public class WindowManagerService extends IWindowManager.Stub
mAtmService.mSizeCompatFreeform = sizeCompatFreeform;
}
+
+ void updateIgnoreVendorDisplaySettings() {
+ final ContentResolver resolver = mContext.getContentResolver();
+ final boolean ignoreVendorSettings = Settings.Global.getInt(resolver,
+ DEVELOPMENT_IGNORE_VENDOR_DISPLAY_SETTINGS, 0) != 0;
+ synchronized (mGlobalLock) {
+ mDisplayWindowSettingsProvider.setVendorSettingsIgnored(ignoreVendorSettings);
+ mRoot.forAllDisplays(display -> {
+ mDisplayWindowSettings.applySettingsToDisplayLocked(display);
+ display.reconfigureDisplayLocked();
+ });
+ }
+ }
}
private void setShadowRenderer() {
@@ -1213,14 +1236,13 @@ public class WindowManagerService extends IWindowManager.Stub
mSurfaceFactory = surfaceFactory;
mTransaction = mTransactionFactory.get();
- mDisplayWindowSettings = new DisplayWindowSettings(this);
mPolicy = policy;
mAnimator = new WindowAnimator(this);
mRoot = new RootWindowContainer(this);
- mUseBLAST = DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT,
- WM_USE_BLAST_ADAPTER_FLAG, false);
+ final ContentResolver resolver = context.getContentResolver();
+ mUseBLAST = Settings.Global.getInt(resolver,
+ Settings.Global.DEVELOPMENT_USE_BLAST_ADAPTER_VR, 1) == 1;
mSyncEngine = new BLASTSyncEngine(this);
@@ -1298,7 +1320,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
}, UserHandle.ALL, suspendPackagesFilter, null, null);
- final ContentResolver resolver = context.getContentResolver();
// Get persisted window scale setting
mWindowAnimationScaleSetting = Settings.Global.getFloat(resolver,
Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
@@ -1313,6 +1334,12 @@ public class WindowManagerService extends IWindowManager.Stub
mForceDesktopModeOnExternalDisplays = Settings.Global.getInt(resolver,
DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS, 0) != 0;
+ final boolean ignoreVendorDisplaySettings = Settings.Global.getInt(resolver,
+ DEVELOPMENT_IGNORE_VENDOR_DISPLAY_SETTINGS, 0) != 0;
+ mDisplayWindowSettingsProvider = new DisplayWindowSettingsProvider();
+ mDisplayWindowSettingsProvider.setVendorSettingsIgnored(ignoreVendorDisplaySettings);
+ mDisplayWindowSettings = new DisplayWindowSettings(this, mDisplayWindowSettingsProvider);
+
IntentFilter filter = new IntentFilter();
// Track changes to DevicePolicyManager state so we can enable/disable keyguard.
filter.addAction(ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
@@ -7670,6 +7697,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (imeTarget == null) {
return;
}
+ Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "WMS.showImePostLayout", 0);
final InsetsControlTarget controlTarget = imeTarget.getImeControlTarget();
imeTarget = controlTarget.getWindow();
// If InsetsControlTarget doesn't have a window, its using remoteControlTarget which
@@ -7683,6 +7711,7 @@ public class WindowManagerService extends IWindowManager.Stub
@Override
public void hideIme(IBinder imeTargetWindowToken, int displayId) {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WMS.hideIme");
synchronized (mGlobalLock) {
WindowState imeTarget = mWindowMap.get(imeTargetWindowToken);
ProtoLog.d(WM_DEBUG_IME, "hideIme target: %s ", imeTarget);
@@ -7703,6 +7732,7 @@ public class WindowManagerService extends IWindowManager.Stub
WindowInsets.Type.ime(), true /* fromIme */);
}
}
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@Override
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 2e7905c64049..5bfa662ea4cb 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -225,8 +225,19 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
@Nullable
private final BackgroundActivityStartCallback mBackgroundActivityStartCallback;
- /** The state for oom-adjustment calculation. */
- private final OomScoreReferenceState mOomRefState;
+ // The bits used for mActivityStateFlags.
+ private static final int ACTIVITY_STATE_FLAG_IS_VISIBLE = 0x10000000;
+ private static final int ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED = 0x20000000;
+ private static final int ACTIVITY_STATE_FLAG_IS_STOPPING = 0x40000000;
+ private static final int ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING = 0x80000000;
+ private static final int ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER = 0x0000ffff;
+
+ /**
+ * The state for oom-adjustment calculation. The higher 16 bits are the activity states, and the
+ * lower 16 bits are the task layer rank (see {@link Task#mLayerRank}). This field is written by
+ * window manager and read by activity manager.
+ */
+ private volatile int mActivityStateFlags = ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
public WindowProcessController(@NonNull ActivityTaskManagerService atm, ApplicationInfo info,
String name, int uid, int userId, Object owner,
@@ -240,7 +251,6 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
mAtm = atm;
mDisplayId = INVALID_DISPLAY;
mBackgroundActivityStartCallback = mAtm.getBackgroundActivityStartCallback();
- mOomRefState = new OomScoreReferenceState(this);
boolean isSysUiPackage = info.packageName.equals(
mAtm.getSysUiServiceComponentLocked().getPackageName());
@@ -707,7 +717,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
@HotPath(caller = HotPath.OOM_ADJUSTMENT)
public boolean hasVisibleActivities() {
- return (mOomRefState.mActivityStateFlags & OomScoreReferenceState.FLAG_IS_VISIBLE) != 0;
+ return (mActivityStateFlags & ACTIVITY_STATE_FLAG_IS_VISIBLE) != 0;
}
@HotPath(caller = HotPath.LRU_UPDATE)
@@ -1000,34 +1010,6 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
mHostActivities.remove(r);
}
- private static class OomScoreReferenceState extends RootWindowContainer.LockedScheduler {
- private static final int FLAG_IS_VISIBLE = 0x10000000;
- private static final int FLAG_IS_PAUSING = 0x20000000;
- private static final int FLAG_IS_STOPPING = 0x40000000;
- private static final int FLAG_IS_STOPPING_FINISHING = 0x80000000;
- /** @see Task#mLayerRank */
- private static final int MASK_MIN_TASK_LAYER = 0x0000ffff;
-
- private final WindowProcessController mOwner;
- boolean mChanged;
-
- /**
- * The higher 16 bits are the activity states, and the lower 16 bits are the task layer
- * rank. This field is written by window manager and read by activity manager.
- */
- volatile int mActivityStateFlags = MASK_MIN_TASK_LAYER;
-
- OomScoreReferenceState(WindowProcessController owner) {
- super(owner.mAtm);
- mOwner = owner;
- }
-
- @Override
- public void execute() {
- mOwner.computeOomScoreReferenceStateIfNeeded();
- }
- }
-
public interface ComputeOomAdjCallback {
void onVisibleActivity();
void onPausedActivity();
@@ -1041,26 +1023,21 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
*/
@HotPath(caller = HotPath.OOM_ADJUSTMENT)
public int computeOomAdjFromActivities(ComputeOomAdjCallback callback) {
- final int flags = mOomRefState.mActivityStateFlags;
- if ((flags & OomScoreReferenceState.FLAG_IS_VISIBLE) != 0) {
+ final int flags = mActivityStateFlags;
+ if ((flags & ACTIVITY_STATE_FLAG_IS_VISIBLE) != 0) {
callback.onVisibleActivity();
- } else if ((flags & OomScoreReferenceState.FLAG_IS_PAUSING) != 0) {
+ } else if ((flags & ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED) != 0) {
callback.onPausedActivity();
- } else if ((flags & OomScoreReferenceState.FLAG_IS_STOPPING) != 0) {
+ } else if ((flags & ACTIVITY_STATE_FLAG_IS_STOPPING) != 0) {
callback.onStoppingActivity(
- (flags & OomScoreReferenceState.FLAG_IS_STOPPING_FINISHING) != 0);
+ (flags & ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING) != 0);
} else {
callback.onOtherActivity();
}
- return flags & OomScoreReferenceState.MASK_MIN_TASK_LAYER;
+ return flags & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
}
- void computeOomScoreReferenceStateIfNeeded() {
- if (!mOomRefState.mChanged) {
- return;
- }
- mOomRefState.mChanged = false;
-
+ void computeProcessActivityState() {
// Since there could be more than one activities in a process record, we don't need to
// compute the OomAdj with each of them, just need to find out the activity with the
// "best" state, the order would be visible, pausing, stopping...
@@ -1101,36 +1078,25 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
finishing &= r.finishing;
}
}
-
- int stateFlags = minTaskLayer & OomScoreReferenceState.MASK_MIN_TASK_LAYER;
- if (visible) {
- stateFlags |= OomScoreReferenceState.FLAG_IS_VISIBLE;
- } else if (best == PAUSING) {
- stateFlags |= OomScoreReferenceState.FLAG_IS_PAUSING;
- } else if (best == STOPPING) {
- stateFlags |= OomScoreReferenceState.FLAG_IS_STOPPING;
- if (finishing) {
- stateFlags |= OomScoreReferenceState.FLAG_IS_STOPPING_FINISHING;
- }
- }
- mOomRefState.mActivityStateFlags = stateFlags;
}
- }
- void invalidateOomScoreReferenceState(boolean computeNow) {
- mOomRefState.mChanged = true;
- if (computeNow) {
- computeOomScoreReferenceStateIfNeeded();
- return;
+ int stateFlags = minTaskLayer & ACTIVITY_STATE_FLAG_MASK_MIN_TASK_LAYER;
+ if (visible) {
+ stateFlags |= ACTIVITY_STATE_FLAG_IS_VISIBLE;
+ } else if (best == PAUSING) {
+ stateFlags |= ACTIVITY_STATE_FLAG_IS_PAUSING_OR_PAUSED;
+ } else if (best == STOPPING) {
+ stateFlags |= ACTIVITY_STATE_FLAG_IS_STOPPING;
+ if (finishing) {
+ stateFlags |= ACTIVITY_STATE_FLAG_IS_STOPPING_FINISHING;
+ }
}
- mOomRefState.scheduleIfNeeded();
+ mActivityStateFlags = stateFlags;
}
/** Called when the process has some oom related changes and it is going to update oom-adj. */
private void prepareOomAdjustment() {
mAtm.mRootWindowContainer.rankTaskLayersIfNeeded();
- // The task layer may not change but the activity state in the same task may change.
- computeOomScoreReferenceStateIfNeeded();
}
public int computeRelaunchReason() {
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 21cb9a74c74e..db93c8932898 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -17,7 +17,7 @@
package com.android.server.wm;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
-import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW;
+import static android.view.SurfaceControl.METADATA_OWNER_PID;
import static android.view.SurfaceControl.METADATA_OWNER_UID;
import static android.view.SurfaceControl.METADATA_WINDOW_TYPE;
@@ -105,6 +105,7 @@ class WindowSurfaceController {
.setFlags(flags)
.setMetadata(METADATA_WINDOW_TYPE, windowType)
.setMetadata(METADATA_OWNER_UID, ownerUid)
+ .setMetadata(METADATA_OWNER_PID, mWindowSession.mPid)
.setCallsite("WindowSurfaceController");
final boolean useBLAST = mService.mUseBLAST && ((win.getAttrs().privateFlags &
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 4d553e2f92aa..3bfcb6def252 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4255,18 +4255,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
mInjector.getPackageManager().getPackagesForUid(
mInjector.binderGetCallingUid()))
.write();
- final int callingUserId = mInjector.userHandleGetCallingUserId();
+ final CallerIdentity caller = getCallerIdentity();
- if (parent) {
- enforceProfileOwnerOrSystemUser();
- }
- enforceUserUnlocked(callingUserId);
+ Preconditions.checkCallAuthorization(!parent || (isDeviceOwner(caller)
+ || isProfileOwner(caller) || isSystemUid(caller)),
+ "Only profile owner, device owner and system may call this method.");
+ enforceUserUnlocked(caller.getUserId());
mContext.enforceCallingOrSelfPermission(
REQUEST_PASSWORD_COMPLEXITY,
"Must have " + REQUEST_PASSWORD_COMPLEXITY + " permission.");
synchronized (getLockObject()) {
- final int credentialOwner = getCredentialOwner(callingUserId, parent);
+ final int credentialOwner = getCredentialOwner(caller.getUserId(), parent);
PasswordMetrics metrics = mLockSettingsInternal.getUserPasswordMetrics(credentialOwner);
return metrics == null ? PASSWORD_COMPLEXITY_NONE : metrics.determineComplexity();
}
@@ -7299,7 +7299,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public boolean hasDeviceOwner() {
- enforceDeviceOwnerOrManageUsers();
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller));
return mOwners.hasDeviceOwner();
}
@@ -8355,32 +8356,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
|| hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS);
}
- private void enforceDeviceOwnerOrManageUsers() {
- final CallerIdentity caller = getCallerIdentity();
- if (isDeviceOwner(caller)) {
- return;
- }
- Preconditions.checkCallAuthorization(canManageUsers(caller));
- }
-
- private void enforceProfileOwnerOrSystemUser() {
- final CallerIdentity caller = getCallerIdentity();
- if (isDeviceOwner(caller) || isProfileOwner(caller)) {
- return;
- }
- Preconditions.checkState(isSystemUid(caller),
- "Only profile owner, device owner and system may call this method.");
- }
-
- private void enforceProfileOwnerOrFullCrossUsersPermission(CallerIdentity caller,
- int userId) {
- if ((userId == caller.getUserId()) && (isProfileOwner(caller) || isDeviceOwner(caller))) {
- // Device Owner/Profile Owner may access the user it runs on.
- return;
- }
- Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userId));
- }
-
private boolean canUserUseLockTaskLocked(int userId) {
if (isUserAffiliatedWithDeviceLocked(userId)) {
return true;
@@ -12458,7 +12433,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (!mHasFeature) {
return null;
}
- enforceDeviceOwnerOrManageUsers();
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller));
synchronized (getLockObject()) {
final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked();
return deviceOwnerAdmin == null ? null : deviceOwnerAdmin.organizationName;
@@ -13605,19 +13581,22 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public long getLastSecurityLogRetrievalTime() {
- enforceDeviceOwnerOrManageUsers();
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller));
return getUserData(UserHandle.USER_SYSTEM).mLastSecurityLogRetrievalTime;
}
@Override
public long getLastBugReportRequestTime() {
- enforceDeviceOwnerOrManageUsers();
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller));
return getUserData(UserHandle.USER_SYSTEM).mLastBugReportRequestTime;
}
@Override
public long getLastNetworkLogRetrievalTime() {
- enforceDeviceOwnerOrManageUsers();
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller));
return getUserData(UserHandle.USER_SYSTEM).mLastNetworkLogsRetrievalTime;
}
@@ -13721,15 +13700,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public boolean isCurrentInputMethodSetByOwner() {
- enforceProfileOwnerOrSystemUser();
- return getUserData(mInjector.userHandleGetCallingUserId()).mCurrentInputMethodSet;
+ final CallerIdentity caller = getCallerIdentity();
+ Preconditions.checkCallAuthorization(isDeviceOwner(caller)
+ || isProfileOwner(caller) || isSystemUid(caller),
+ "Only profile owner, device owner and system may call this method.");
+ return getUserData(caller.getUserId()).mCurrentInputMethodSet;
}
@Override
public StringParceledListSlice getOwnerInstalledCaCerts(@NonNull UserHandle user) {
final int userId = user.getIdentifier();
final CallerIdentity caller = getCallerIdentity();
- enforceProfileOwnerOrFullCrossUsersPermission(caller, userId);
+ Preconditions.checkCallAuthorization((userId == caller.getUserId())
+ || isProfileOwner(caller) || isDeviceOwner(caller)
+ || hasFullCrossUsersPermission(caller, userId));
+
synchronized (getLockObject()) {
return new StringParceledListSlice(
new ArrayList<>(getUserData(userId).mOwnerInstalledCaCerts));
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 03edc585b46a..dfa726f1bfc8 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1266,6 +1266,12 @@ public final class SystemServer implements Dumpable {
inputManager = new InputManagerService(context);
t.traceEnd();
+ if (!disableCameraService) {
+ t.traceBegin("StartCameraServiceProxy");
+ mSystemServiceManager.startService(CameraServiceProxy.class);
+ t.traceEnd();
+ }
+
t.traceBegin("StartWindowManagerService");
// WMS needs sensor service ready
ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
@@ -1339,7 +1345,7 @@ public final class SystemServer implements Dumpable {
mSystemServiceManager.startService(IorapForwardingService.class);
t.traceEnd();
- if (Build.IS_DEBUGGABLE) {
+ if (Build.IS_DEBUGGABLE && ProfcollectForwardingService.enabled()) {
t.traceBegin("ProfcollectForwardingService");
mSystemServiceManager.startService(ProfcollectForwardingService.class);
t.traceEnd();
@@ -2200,12 +2206,6 @@ public final class SystemServer implements Dumpable {
t.traceEnd();
}
- if (!disableCameraService) {
- t.traceBegin("StartCameraServiceProxy");
- mSystemServiceManager.startService(CameraServiceProxy.class);
- t.traceEnd();
- }
-
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_EMBEDDED)) {
t.traceBegin("StartIoTSystemService");
mSystemServiceManager.startService(IOT_SERVICE_CLASS);
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index d14ed5a15cf9..19449654f2ec 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -31,6 +31,7 @@ import android.os.ServiceManager;
import android.os.SystemProperties;
import android.os.UpdateEngine;
import android.os.UpdateEngineCallback;
+import android.provider.DeviceConfig;
import android.util.Log;
import com.android.server.IoThread;
@@ -68,6 +69,14 @@ public final class ProfcollectForwardingService extends SystemService {
sSelfService = this;
}
+ /**
+ * Check whether profcollect is enabled through device config.
+ */
+ public static boolean enabled() {
+ return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PROFCOLLECT_NATIVE_BOOT, "enabled",
+ false);
+ }
+
@Override
public void onStart() {
if (DEBUG) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
index 736a7be5e39e..2c92ae44d63a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/RescuePartyTest.java
@@ -27,9 +27,11 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.RescueParty.LEVEL_FACTORY_RESET;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import android.content.ContentResolver;
@@ -79,8 +81,11 @@ public class RescuePartyTest {
private static final String CALLING_PACKAGE2 = "com.package.name2";
private static final String NAMESPACE1 = "namespace1";
private static final String NAMESPACE2 = "namespace2";
+ private static final String NAMESPACE3 = "namespace3";
private static final String PROP_DEVICE_CONFIG_DISABLE_FLAG =
"persist.device_config.configuration.disable_rescue_party";
+ private static final String PROP_DISABLE_FACTORY_RESET_FLAG =
+ "persist.device_config.configuration.disable_rescue_party_factory_reset";
private MockitoSession mSession;
private HashMap<String, String> mSystemSettingsMap;
@@ -183,27 +188,38 @@ public class RescuePartyTest {
@Test
public void testBootLoopDetectionWithExecutionForAllRescueLevels() {
+ RescueParty.onSettingsProviderPublished(mMockContext);
+ verify(() -> Settings.Config.registerMonitorCallback(eq(mMockContentResolver),
+ mMonitorCallbackCaptor.capture()));
+
noteBoot();
verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, /*resetNamespaces=*/ null);
assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_DEFAULTS,
SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
+ // Record DeviceConfig accesses
+ RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext);
+ RemoteCallback monitorCallback = mMonitorCallbackCaptor.getValue();
+ monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE1, NAMESPACE1));
+ monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE1, NAMESPACE2));
+
+ final String[] expectedAllResetNamespaces = new String[]{NAMESPACE1, NAMESPACE2};
+
noteBoot();
- verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_CHANGES, /*resetNamespaces=*/ null);
+ verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_CHANGES, expectedAllResetNamespaces);
assertEquals(RescueParty.LEVEL_RESET_SETTINGS_UNTRUSTED_CHANGES,
SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
noteBoot();
- verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS, /*resetNamespaces=*/ null);
+ verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS, expectedAllResetNamespaces);
assertEquals(RescueParty.LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS,
SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
noteBoot();
- verify(() -> RecoverySystem.rebootPromptAndWipeUserData(mMockContext, RescueParty.TAG));
assertEquals(LEVEL_FACTORY_RESET,
SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
}
@@ -230,7 +246,6 @@ public class RescuePartyTest {
notePersistentAppCrash();
- verify(() -> RecoverySystem.rebootPromptAndWipeUserData(mMockContext, RescueParty.TAG));
assertEquals(LEVEL_FACTORY_RESET,
SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
}
@@ -247,6 +262,7 @@ public class RescuePartyTest {
monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE1, NAMESPACE1));
monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE1, NAMESPACE2));
monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE2, NAMESPACE2));
+ monitorCallback.sendResult(getConfigAccessBundle(CALLING_PACKAGE2, NAMESPACE3));
// Fake DeviceConfig value changes
monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE1));
verify(mMockPackageWatchdog).startObservingHealth(observer,
@@ -255,10 +271,15 @@ public class RescuePartyTest {
verify(mMockPackageWatchdog, times(2)).startObservingHealth(eq(observer),
mPackageListCaptor.capture(),
eq(RescueParty.DEFAULT_OBSERVING_DURATION_MS));
+ monitorCallback.sendResult(getConfigNamespaceUpdateBundle(NAMESPACE3));
+ verify(mMockPackageWatchdog).startObservingHealth(observer,
+ Arrays.asList(CALLING_PACKAGE2), RescueParty.DEFAULT_OBSERVING_DURATION_MS);
assertTrue(mPackageListCaptor.getValue().containsAll(
Arrays.asList(CALLING_PACKAGE1, CALLING_PACKAGE2)));
// Perform and verify scoped resets
final String[] expectedResetNamespaces = new String[]{NAMESPACE1, NAMESPACE2};
+ final String[] expectedAllResetNamespaces =
+ new String[]{NAMESPACE1, NAMESPACE2, NAMESPACE3};
observer.execute(new VersionedPackage(
CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_CRASH);
verifySettingsResets(Settings.RESET_MODE_UNTRUSTED_DEFAULTS, expectedResetNamespaces);
@@ -273,13 +294,12 @@ public class RescuePartyTest {
observer.execute(new VersionedPackage(
CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING);
- verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS, /*resetNamespaces=*/null);
+ verifySettingsResets(Settings.RESET_MODE_TRUSTED_DEFAULTS, expectedAllResetNamespaces);
assertEquals(RescueParty.LEVEL_RESET_SETTINGS_TRUSTED_DEFAULTS,
SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
observer.execute(new VersionedPackage(
CALLING_PACKAGE1, 1), PackageWatchdog.FAILURE_REASON_APP_CRASH);
- verify(() -> RecoverySystem.rebootPromptAndWipeUserData(mMockContext, RescueParty.TAG));
assertTrue(RescueParty.isAttemptingFactoryReset());
}
@@ -288,7 +308,6 @@ public class RescuePartyTest {
for (int i = 0; i < LEVEL_FACTORY_RESET; i++) {
noteBoot();
}
- verify(() -> RecoverySystem.rebootPromptAndWipeUserData(mMockContext, RescueParty.TAG));
assertTrue(RescueParty.isAttemptingFactoryReset());
}
@@ -337,12 +356,25 @@ public class RescuePartyTest {
assertEquals(RescuePartyObserver.getInstance(mMockContext).execute(sFailingPackage,
PackageWatchdog.FAILURE_REASON_APP_NOT_RESPONDING), false);
- // Restore the property value initalized in SetUp()
+ // Restore the property value initialized in SetUp()
SystemProperties.set(RescueParty.PROP_ENABLE_RESCUE, Boolean.toString(true));
SystemProperties.set(PROP_DEVICE_CONFIG_DISABLE_FLAG, Boolean.toString(false));
}
@Test
+ public void testDisablingFactoryResetByDeviceConfigFlag() {
+ SystemProperties.set(PROP_DISABLE_FACTORY_RESET_FLAG, Boolean.toString(true));
+
+ for (int i = 0; i < LEVEL_FACTORY_RESET; i++) {
+ noteBoot();
+ }
+ assertFalse(RescueParty.isAttemptingFactoryReset());
+
+ // Restore the property value initialized in SetUp()
+ SystemProperties.set(PROP_DISABLE_FACTORY_RESET_FLAG, "");
+ }
+
+ @Test
public void testHealthCheckLevels() {
RescuePartyObserver observer = RescuePartyObserver.getInstance(mMockContext);
@@ -437,7 +469,7 @@ public class RescuePartyTest {
eq(resetMode), anyInt()));
// Verify DeviceConfig resets
if (resetNamespaces == null) {
- verify(() -> DeviceConfig.resetToDefaults(resetMode, /*namespace=*/ null));
+ verify(() -> DeviceConfig.resetToDefaults(anyInt(), anyString()), never());
} else {
for (String namespace : resetNamespaces) {
verify(() -> DeviceConfig.resetToDefaults(resetMode, namespace));
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index db4aba519a6a..8e4942e1ad5c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -47,6 +47,7 @@ import static com.android.server.alarm.AlarmManagerService.AlarmHandler.REMOVE_F
import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_LONG_TIME;
import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_SHORT_TIME;
import static com.android.server.alarm.AlarmManagerService.Constants.KEY_ALLOW_WHILE_IDLE_WHITELIST_DURATION;
+import static com.android.server.alarm.AlarmManagerService.Constants.KEY_LAZY_BATCHING;
import static com.android.server.alarm.AlarmManagerService.Constants.KEY_LISTENER_TIMEOUT;
import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MAX_INTERVAL;
import static com.android.server.alarm.AlarmManagerService.Constants.KEY_MIN_FUTURITY;
@@ -62,6 +63,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.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
@@ -365,7 +367,7 @@ public class AlarmManagerServiceTest {
}
private void setIdleUntilAlarm(int type, long triggerTime, PendingIntent pi) {
- setTestAlarm(type, triggerTime, pi, 0, FLAG_IDLE_UNTIL, TEST_CALLING_UID);
+ setTestAlarm(type, triggerTime, pi, 0, FLAG_IDLE_UNTIL | FLAG_STANDALONE, TEST_CALLING_UID);
}
private void setWakeFromIdle(int type, long triggerTime, PendingIntent pi) {
@@ -410,6 +412,12 @@ public class AlarmManagerServiceTest {
mService.mConstants.onPropertiesChanged(mDeviceConfigProperties);
}
+ private void setDeviceConfigBoolean(String key, boolean val) {
+ mDeviceConfigKeys.add(key);
+ doReturn(val).when(mDeviceConfigProperties).getBoolean(eq(key), anyBoolean());
+ mService.mConstants.onPropertiesChanged(mDeviceConfigProperties);
+ }
+
/**
* Lowers quotas to make testing feasible. Careful while calling as this will replace any
* existing settings for the calling test.
@@ -1382,6 +1390,35 @@ public class AlarmManagerServiceTest {
}
}
+ @Test
+ public void alarmStoreMigration() {
+ setDeviceConfigBoolean(KEY_LAZY_BATCHING, false);
+ final int numAlarms = 10;
+ final PendingIntent[] pis = new PendingIntent[numAlarms];
+ for (int i = 0; i < numAlarms; i++) {
+ pis[i] = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 1, pis[i]);
+ }
+
+ final ArrayList<Alarm> alarmsBefore = mService.mAlarmStore.asList();
+ assertEquals(numAlarms, alarmsBefore.size());
+ for (int i = 0; i < numAlarms; i++) {
+ final PendingIntent pi = pis[i];
+ assertTrue(i + "th PendingIntent missing: ",
+ alarmsBefore.removeIf(a -> a.matches(pi, null)));
+ }
+
+ setDeviceConfigBoolean(KEY_LAZY_BATCHING, true);
+
+ final ArrayList<Alarm> alarmsAfter = mService.mAlarmStore.asList();
+ assertEquals(numAlarms, alarmsAfter.size());
+ for (int i = 0; i < numAlarms; i++) {
+ final PendingIntent pi = pis[i];
+ assertTrue(i + "th PendingIntent missing: ",
+ alarmsAfter.removeIf(a -> a.matches(pi, null)));
+ }
+ }
+
@After
public void tearDown() {
if (mMockingSession != null) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java
index c4fc61a5aa6e..42fa3d480046 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmStoreTest.java
@@ -16,6 +16,9 @@
package com.android.server.alarm;
+import static android.app.AlarmManager.ELAPSED_REALTIME;
+import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
+
import static com.android.server.alarm.Constants.TEST_CALLING_PACKAGE;
import static com.android.server.alarm.Constants.TEST_CALLING_UID;
@@ -23,35 +26,50 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.platform.test.annotations.Presubmit;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
import java.util.ArrayList;
@Presubmit
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
public class AlarmStoreTest {
- private AlarmStore mAlarmStore;
- @Before
- public void setUp() {
- mAlarmStore = new BatchingAlarmStore(null);
+ @Parameter
+ public AlarmStore mAlarmStore;
+
+ @Parameters
+ public static Object[] stores() {
+ return new AlarmStore[]{
+ new LazyAlarmStore(),
+ new BatchingAlarmStore(),
+ };
}
private static Alarm createAlarm(long whenElapsed, long windowLength) {
- return createAlarm(AlarmManager.ELAPSED_REALTIME, whenElapsed, windowLength, 0);
+ return createAlarm(ELAPSED_REALTIME, whenElapsed, windowLength, 0);
}
private static Alarm createWakeupAlarm(long whenElapsed, long windowLength, int flags) {
- return createAlarm(AlarmManager.ELAPSED_REALTIME_WAKEUP, whenElapsed, windowLength, flags);
+ return createAlarm(ELAPSED_REALTIME_WAKEUP, whenElapsed, windowLength, flags);
+ }
+
+ private static Alarm createAlarmClock(long whenElapsed) {
+ final AlarmManager.AlarmClockInfo info = new AlarmManager.AlarmClockInfo(whenElapsed,
+ mock(PendingIntent.class));
+ return new Alarm(ELAPSED_REALTIME_WAKEUP, whenElapsed, whenElapsed, 0, 0,
+ mock(PendingIntent.class), null, null, null, 0, info, TEST_CALLING_UID,
+ TEST_CALLING_PACKAGE);
}
private static Alarm createAlarm(int type, long whenElapsed, long windowLength, int flags) {
@@ -206,4 +224,21 @@ public class AlarmStoreTest {
});
assertEquals(7, mAlarmStore.getNextDeliveryTime());
}
+
+ @Test
+ public void alarmClockRemovalListener() {
+ final Runnable onRemoved = mock(Runnable.class);
+ mAlarmStore.setAlarmClockRemovalListener(onRemoved);
+
+ final Alarm simpleAlarm = createAlarm(5, 0);
+ final Alarm alarmClock = createAlarmClock(10);
+
+ addAlarmsToStore(simpleAlarm, alarmClock);
+
+ mAlarmStore.remove(simpleAlarm::equals);
+ verifyZeroInteractions(onRemoved);
+
+ mAlarmStore.remove(alarmClock::equals);
+ verify(onRemoved).run();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
index 081bfb5b2724..0d0ac6d2794d 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/AppSearchImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.appsearch.external.localbackend;
+package com.android.server.appsearch.external.localstorage;
import static com.google.common.truth.Truth.assertThat;
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverterTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java
index a95290d89b59..85d4f01f8d41 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/GenericDocumentToProtoConverterTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/GenericDocumentToProtoConverterTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.appsearch.external.localbackend.converter;
+package com.android.server.appsearch.external.localstorage.converter;
import static com.google.common.truth.Truth.assertThat;
@@ -53,13 +53,13 @@ public class GenericDocumentToProtoConverterTest {
.setScore(1)
.setTtlMillis(1L)
.setNamespace("namespace")
- .setProperty("longKey1", 1L)
- .setProperty("doubleKey1", 1.0)
- .setProperty("booleanKey1", true)
- .setProperty("stringKey1", "test-value1")
- .setProperty("byteKey1", BYTE_ARRAY_1, BYTE_ARRAY_2)
- .setProperty("documentKey1", DOCUMENT_PROPERTIES_1)
- .setProperty(GenericDocument.PROPERTIES_FIELD, DOCUMENT_PROPERTIES_2)
+ .setPropertyLong("longKey1", 1L)
+ .setPropertyDouble("doubleKey1", 1.0)
+ .setPropertyBoolean("booleanKey1", true)
+ .setPropertyString("stringKey1", "test-value1")
+ .setPropertyBytes("byteKey1", BYTE_ARRAY_1, BYTE_ARRAY_2)
+ .setPropertyDocument("documentKey1", DOCUMENT_PROPERTIES_1)
+ .setPropertyDocument("documentKey2", DOCUMENT_PROPERTIES_2)
.build();
// Create the Document proto. Need to sort the property order by key.
@@ -87,8 +87,8 @@ public class GenericDocumentToProtoConverterTest {
PropertyProto.newBuilder().setName("documentKey1")
.addDocumentValues(
GenericDocumentToProtoConverter.convert(DOCUMENT_PROPERTIES_1)));
- propertyProtoMap.put(GenericDocument.PROPERTIES_FIELD,
- PropertyProto.newBuilder().setName(GenericDocument.PROPERTIES_FIELD)
+ propertyProtoMap.put("documentKey2",
+ PropertyProto.newBuilder().setName("documentKey2")
.addDocumentValues(
GenericDocumentToProtoConverter.convert(DOCUMENT_PROPERTIES_2)));
List<String> sortedKey = new ArrayList<>(propertyProtoMap.keySet());
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverterTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
index 8b2fd1ce9fef..7336c3c36417 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SchemaToProtoConverterTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SchemaToProtoConverterTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.appsearch.external.localbackend.converter;
+package com.android.server.appsearch.external.localstorage.converter;
import static com.google.common.truth.Truth.assertThat;
@@ -50,7 +50,6 @@ public class SchemaToProtoConverterTest {
.addProperties(PropertyConfigProto.newBuilder()
.setPropertyName("subject")
.setDataType(PropertyConfigProto.DataType.Code.STRING)
- .setSchemaType("")
.setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
.setIndexingConfig(
com.android.server.appsearch.proto.IndexingConfig.newBuilder()
@@ -60,7 +59,6 @@ public class SchemaToProtoConverterTest {
).addProperties(PropertyConfigProto.newBuilder()
.setPropertyName("body")
.setDataType(PropertyConfigProto.DataType.Code.STRING)
- .setSchemaType("")
.setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
.setIndexingConfig(
com.android.server.appsearch.proto.IndexingConfig.newBuilder()
@@ -94,7 +92,6 @@ public class SchemaToProtoConverterTest {
.addProperties(PropertyConfigProto.newBuilder()
.setPropertyName("artist")
.setDataType(PropertyConfigProto.DataType.Code.STRING)
- .setSchemaType("")
.setCardinality(PropertyConfigProto.Cardinality.Code.REPEATED)
.setIndexingConfig(
com.android.server.appsearch.proto.IndexingConfig.newBuilder()
@@ -104,7 +101,6 @@ public class SchemaToProtoConverterTest {
).addProperties(PropertyConfigProto.newBuilder()
.setPropertyName("pubDate")
.setDataType(PropertyConfigProto.DataType.Code.INT64)
- .setSchemaType("")
.setCardinality(PropertyConfigProto.Cardinality.Code.OPTIONAL)
.setIndexingConfig(
com.android.server.appsearch.proto.IndexingConfig.newBuilder()
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SnippetTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
index e9357aa60632..d5762a1317b5 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localbackend/converter/SnippetTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/converter/SnippetTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server.appsearch.external.localbackend.converter;
+package com.android.server.appsearch.external.localstorage.converter;
import static com.google.common.truth.Truth.assertThat;
@@ -123,7 +123,7 @@ public class SnippetTest {
for (SearchResultProto.ResultProto proto : searchResultProto.getResultsList()) {
SearchResult result = SearchResultToProtoConverter.convertSearchResult(proto);
- assertThat(result.getMatches()).isEqualTo(null);
+ assertThat(result.getMatches()).isEmpty();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/Face10Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/Face10Test.java
index 7a0d8946d179..b73a783af299 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/Face10Test.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/Face10Test.java
@@ -46,6 +46,10 @@ public class Face10Test {
private Face10 mFace10;
private IBinder mBinder;
+ private static void waitForIdle() {
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ }
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -59,11 +63,8 @@ public class Face10Test {
@Test
public void scheduleRevokeChallenge_doesNotCrash() {
- mFace10.scheduleRevokeChallenge(mBinder, TAG);
+ mFace10.scheduleRevokeChallenge(0 /* sensorId */, 0 /* userId */, mBinder, TAG,
+ 0 /* challenge */);
waitForIdle();
}
-
- private static void waitForIdle() {
- InstrumentationRegistry.getInstrumentation().waitForIdleSync();
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyConstantsTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyConstantsTest.java
index be05245deea1..9660d6ba2f74 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyConstantsTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyConstantsTest.java
@@ -15,33 +15,33 @@
*/
package com.android.server.devicepolicy;
-import android.test.AndroidTestCase;
+import static com.google.common.truth.Truth.assertThat;
+
import android.test.suitebuilder.annotation.SmallTest;
+import org.junit.Test;
+
/**
* Test for {@link DevicePolicyConstants}.
*
- m FrameworksServicesTests &&
- adb install \
- -r ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
- adb shell am instrument -e class com.android.server.devicepolicy.DevicePolicyConstantsTest \
- -w com.android.frameworks.servicestests
-
-
- -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
+ * <p>Run this test with:
+ *
+ * {@code atest FrameworksServicesTests:com.android.server.devicepolicy.DevicePolicyConstantsTest}
*/
@SmallTest
-public class DevicePolicyConstantsTest extends AndroidTestCase {
+public class DevicePolicyConstantsTest {
private static final String TAG = "DevicePolicyConstantsTest";
+ @Test
public void testDefaultValues() throws Exception {
final DevicePolicyConstants constants = DevicePolicyConstants.loadFromString("");
- assertEquals(1 * 60 * 60, constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_SEC);
- assertEquals(24 * 60 * 60, constants.DAS_DIED_SERVICE_RECONNECT_MAX_BACKOFF_SEC);
- assertEquals(2.0, constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_INCREASE);
+ assertThat(constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_SEC).isEqualTo(1 * 60 * 60);
+ assertThat(constants.DAS_DIED_SERVICE_RECONNECT_MAX_BACKOFF_SEC).isEqualTo(24 * 60 * 60);
+ assertThat(constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_INCREASE).isWithin(1.0e-10).of(2.0);
}
+ @Test
public void testCustomValues() throws Exception {
final DevicePolicyConstants constants = DevicePolicyConstants.loadFromString(
"das_died_service_reconnect_backoff_sec=10,"
@@ -49,11 +49,13 @@ public class DevicePolicyConstantsTest extends AndroidTestCase {
+ "das_died_service_reconnect_max_backoff_sec=15"
);
- assertEquals(10, constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_SEC);
- assertEquals(15, constants.DAS_DIED_SERVICE_RECONNECT_MAX_BACKOFF_SEC);
- assertEquals(1.25, constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_INCREASE);
+ assertThat(constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_SEC).isEqualTo(10);
+ assertThat(constants.DAS_DIED_SERVICE_RECONNECT_MAX_BACKOFF_SEC).isEqualTo(15);
+ assertThat(constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_INCREASE).isWithin(1.0e-10)
+ .of(1.25);
}
+ @Test
public void testMinMax() throws Exception {
final DevicePolicyConstants constants = DevicePolicyConstants.loadFromString(
"das_died_service_reconnect_backoff_sec=3,"
@@ -61,8 +63,8 @@ public class DevicePolicyConstantsTest extends AndroidTestCase {
+ "das_died_service_reconnect_max_backoff_sec=1"
);
- assertEquals(5, constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_SEC);
- assertEquals(5, constants.DAS_DIED_SERVICE_RECONNECT_MAX_BACKOFF_SEC);
- assertEquals(1.0, constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_INCREASE);
+ assertThat(constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_SEC).isEqualTo(5);
+ assertThat(constants.DAS_DIED_SERVICE_RECONNECT_MAX_BACKOFF_SEC).isEqualTo(5);
+ assertThat(constants.DAS_DIED_SERVICE_RECONNECT_BACKOFF_INCREASE).isWithin(1.0e-10).of(1.0);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyEventLoggerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyEventLoggerTest.java
index b24bca8fc050..350b390a2130 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyEventLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyEventLoggerTest.java
@@ -46,8 +46,8 @@ public class DevicePolicyEventLoggerTest {
.setTimePeriod(1234L);
assertThat(eventLogger.getEventId()).isEqualTo(5);
assertThat(eventLogger.getBoolean()).isTrue();
- assertThat(eventLogger.getStringArray())
- .isEqualTo(new String[] {"string1", "string2", "string3"});
+ assertThat(eventLogger.getStringArray()).asList()
+ .containsExactly("string1", "string2", "string3");
assertThat(eventLogger.getAdminPackageName()).isEqualTo("com.test.package");
assertThat(eventLogger.getInt()).isEqualTo(4321);
assertThat(eventLogger.getTimePeriod()).isEqualTo(1234L);
@@ -57,23 +57,22 @@ public class DevicePolicyEventLoggerTest {
public void testStrings() {
assertThat(DevicePolicyEventLogger
.createEvent(0)
- .setStrings("string1", "string2", "string3").getStringArray())
- .isEqualTo(new String[] {"string1", "string2", "string3"});
+ .setStrings("string1", "string2", "string3").getStringArray()).asList()
+ .containsExactly("string1", "string2", "string3").inOrder();
assertThat(DevicePolicyEventLogger
.createEvent(0)
.setStrings("string1", new String[] {"string2", "string3"}).getStringArray())
- .isEqualTo(new String[] {"string1", "string2", "string3"});
+ .asList().containsExactly("string1", "string2", "string3").inOrder();
assertThat(DevicePolicyEventLogger
.createEvent(0)
.setStrings("string1", "string2", new String[] {"string3"}).getStringArray())
- .isEqualTo(new String[] {"string1", "string2", "string3"});
-
+ .asList().containsExactly("string1", "string2", "string3").inOrder();
assertThat(DevicePolicyEventLogger
.createEvent(0)
- .setStrings((String) null).getStringArray())
- .isEqualTo(new String[] {null});
+ .setStrings((String) null).getStringArray()).asList()
+ .containsExactly((String) null);
assertThat(DevicePolicyEventLogger
.createEvent(0)
@@ -106,8 +105,8 @@ public class DevicePolicyEventLoggerTest {
.createEvent(0);
assertThat(eventLogger.getEventId()).isEqualTo(0);
assertThat(eventLogger.getBoolean()).isFalse();
- assertThat(eventLogger.getStringArray()).isEqualTo(null);
- assertThat(eventLogger.getAdminPackageName()).isEqualTo(null);
+ assertThat(eventLogger.getStringArray()).isNull();
+ assertThat(eventLogger.getAdminPackageName()).isNull();
assertThat(eventLogger.getInt()).isEqualTo(0);
assertThat(eventLogger.getTimePeriod()).isEqualTo(0L);
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
index 3167820f0a48..fa3f45c08202 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
@@ -20,7 +20,9 @@ import static android.os.UserHandle.USER_SYSTEM;
import static com.android.server.devicepolicy.DpmTestUtils.writeInputStreamToFile;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
-import static org.junit.Assert.assertArrayEquals;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
@@ -43,17 +45,23 @@ import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
import com.android.frameworks.servicestests.R;
import com.android.server.LocalServices;
import com.android.server.SystemService;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@Presubmit
+@RunWith(AndroidJUnit4.class)
public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
private static final String USER_TYPE_EMPTY = "";
@@ -63,9 +71,8 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
private DpmMockContext mContext;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
mContext = getContext();
@@ -77,6 +84,7 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
.thenReturn(true);
}
+ @Test
public void testMigration() throws Exception {
final File user10dir = getServices().addUser(10, 0, USER_TYPE_EMPTY);
final File user11dir = getServices().addUser(11, 0,
@@ -160,19 +168,19 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
mContext.binder.restoreCallingIdentity(ident);
}
- assertTrue(dpms.mOwners.hasDeviceOwner());
- assertFalse(dpms.mOwners.hasProfileOwner(USER_SYSTEM));
- assertTrue(dpms.mOwners.hasProfileOwner(10));
- assertTrue(dpms.mOwners.hasProfileOwner(11));
- assertFalse(dpms.mOwners.hasProfileOwner(12));
+ assertThat(dpms.mOwners.hasDeviceOwner()).isTrue();
+ assertThat(dpms.mOwners.hasProfileOwner(USER_SYSTEM)).isFalse();
+ assertThat(dpms.mOwners.hasProfileOwner(10)).isTrue();
+ assertThat(dpms.mOwners.hasProfileOwner(11)).isTrue();
+ assertThat(dpms.mOwners.hasProfileOwner(12)).isFalse();
// Now all information should be migrated.
- assertFalse(dpms.mOwners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(
- USER_SYSTEM));
- assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(10));
- assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(11));
- assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(12));
+ assertThat(dpms.mOwners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+ assertThat(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(USER_SYSTEM))
+ .isFalse();
+ assertThat(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+ assertThat(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+ assertThat(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(12)).isFalse();
// Check the new base restrictions.
DpmTestUtils.assertRestrictions(
@@ -221,6 +229,7 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
dpms.getProfileOwnerAdminLocked(11).ensureUserRestrictions());
}
+ @Test
public void testMigration2_profileOwnerOnUser0() throws Exception {
setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_SYSTEM_USER_UID);
@@ -271,13 +280,13 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
} finally {
mContext.binder.restoreCallingIdentity(ident);
}
- assertFalse(dpms.mOwners.hasDeviceOwner());
- assertTrue(dpms.mOwners.hasProfileOwner(USER_SYSTEM));
+ assertThat(dpms.mOwners.hasDeviceOwner()).isFalse();
+ assertThat(dpms.mOwners.hasProfileOwner(USER_SYSTEM)).isTrue();
// Now all information should be migrated.
- assertFalse(dpms.mOwners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertFalse(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(
- USER_SYSTEM));
+ assertThat(dpms.mOwners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+ assertThat(dpms.mOwners.getProfileOwnerUserRestrictionsNeedsMigration(USER_SYSTEM))
+ .isFalse();
// Check the new base restrictions.
DpmTestUtils.assertRestrictions(
@@ -297,6 +306,7 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
}
// Test setting default restrictions for managed profile.
+ @Test
public void testMigration3_managedProfileOwner() throws Exception {
// Create a managed profile user.
final File user10dir = getServices().addUser(10, 0,
@@ -339,8 +349,8 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
mContext.binder.restoreCallingIdentity(ident);
}
- assertFalse(dpms.mOwners.hasDeviceOwner());
- assertTrue(dpms.mOwners.hasProfileOwner(10));
+ assertThat(dpms.mOwners.hasDeviceOwner()).isFalse();
+ assertThat(dpms.mOwners.hasProfileOwner(10)).isTrue();
// Check that default restrictions were applied.
DpmTestUtils.assertRestrictions(
@@ -352,11 +362,12 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
final Set<String> alreadySet =
dpms.getProfileOwnerAdminLocked(10).defaultEnabledRestrictionsAlreadySet;
- assertEquals(alreadySet.size(), 1);
- assertTrue(alreadySet.contains(UserManager.DISALLOW_BLUETOOTH_SHARING));
+ assertThat(alreadySet).hasSize(1);
+ assertThat(alreadySet.contains(UserManager.DISALLOW_BLUETOOTH_SHARING)).isTrue();
}
@SmallTest
+ @Test
public void testCompMigrationUnAffiliated_skipped() throws Exception {
prepareAdmin1AsDo();
prepareAdminAnotherPackageAsPo(COPE_PROFILE_USER_ID);
@@ -364,10 +375,11 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
final DevicePolicyManagerServiceTestable dpms = bootDpmsUp();
// DO should still be DO since no migration should happen.
- assertTrue(dpms.mOwners.hasDeviceOwner());
+ assertThat(dpms.mOwners.hasDeviceOwner()).isTrue();
}
@SmallTest
+ @Test
public void testCompMigrationAffiliated() throws Exception {
prepareAdmin1AsDo();
prepareAdmin1AsPo(COPE_PROFILE_USER_ID, Build.VERSION_CODES.R);
@@ -378,48 +390,54 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
final DevicePolicyManagerServiceTestable dpms = bootDpmsUp();
// DO should cease to be DO.
- assertFalse(dpms.mOwners.hasDeviceOwner());
+ assertThat(dpms.mOwners.hasDeviceOwner()).isFalse();
final DpmMockContext poContext = new DpmMockContext(getServices(), mRealTestContext);
poContext.binder.callingUid = UserHandle.getUid(COPE_PROFILE_USER_ID, COPE_ADMIN1_APP_ID);
runAsCaller(poContext, dpms, dpm -> {
- assertEquals("Password history policy wasn't migrated to PO parent instance",
- 33, dpm.getParentProfileInstance(admin1).getPasswordHistoryLength(admin1));
- assertEquals("Password history policy was put into non-parent PO instance",
- 0, dpm.getPasswordHistoryLength(admin1));
- assertTrue("Screen capture restriction wasn't migrated to PO parent instance",
- dpm.getParentProfileInstance(admin1).getScreenCaptureDisabled(admin1));
-
- assertArrayEquals("Accounts with management disabled weren't migrated to PO parent",
- new String[] {"com.google-primary"},
- dpm.getParentProfileInstance(admin1).getAccountTypesWithManagementDisabled());
- assertArrayEquals("Accounts with management disabled for profile were lost",
- new String[] {"com.google-profile"},
- dpm.getAccountTypesWithManagementDisabled());
-
- assertTrue("User restriction wasn't migrated to PO parent instance",
- dpm.getParentProfileInstance(admin1).getUserRestrictions(admin1)
- .containsKey(UserManager.DISALLOW_BLUETOOTH));
- assertFalse("User restriction was put into non-parent PO instance",
- dpm.getUserRestrictions(admin1).containsKey(UserManager.DISALLOW_BLUETOOTH));
-
- assertTrue("User restriction wasn't migrated to PO parent instance",
- dpms.getProfileOwnerAdminLocked(COPE_PROFILE_USER_ID)
- .getParentActiveAdmin()
- .getEffectiveRestrictions()
- .containsKey(UserManager.DISALLOW_CONFIG_DATE_TIME));
- assertFalse("User restriction was put into non-parent PO instance",
- dpms.getProfileOwnerAdminLocked(COPE_PROFILE_USER_ID)
- .getEffectiveRestrictions()
- .containsKey(UserManager.DISALLOW_CONFIG_DATE_TIME));
- assertEquals("Personal apps suspension wasn't migrated",
- DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED,
- dpm.getPersonalAppsSuspendedReasons(admin1));
+ assertWithMessage("Password history policy wasn't migrated to PO parent instance")
+ .that(dpm.getParentProfileInstance(admin1).getPasswordHistoryLength(admin1))
+ .isEqualTo(33);
+ assertWithMessage("Password history policy was put into non-parent PO instance")
+ .that(dpm.getPasswordHistoryLength(admin1)).isEqualTo(0);
+ assertWithMessage("Screen capture restriction wasn't migrated to PO parent instance")
+ .that(dpm.getParentProfileInstance(admin1).getScreenCaptureDisabled(admin1))
+ .isTrue();
+
+ assertWithMessage("Accounts with management disabled weren't migrated to PO parent")
+ .that(dpm.getParentProfileInstance(admin1)
+ .getAccountTypesWithManagementDisabled()).asList()
+ .containsExactly("com.google-primary");
+
+ assertWithMessage("Accounts with management disabled for profile were lost")
+ .that(dpm.getAccountTypesWithManagementDisabled()).asList()
+ .containsExactly("com.google-profile");
+
+ assertWithMessage("User restriction wasn't migrated to PO parent instance")
+ .that(dpm.getParentProfileInstance(admin1).getUserRestrictions(admin1).keySet())
+ .contains(UserManager.DISALLOW_BLUETOOTH);
+
+ assertWithMessage("User restriction was put into non-parent PO instance").that(
+ dpm.getUserRestrictions(admin1).keySet())
+ .doesNotContain(UserManager.DISALLOW_BLUETOOTH);
+
+ assertWithMessage("User restriction wasn't migrated to PO parent instance")
+ .that(dpms.getProfileOwnerAdminLocked(COPE_PROFILE_USER_ID)
+ .getParentActiveAdmin().getEffectiveRestrictions().keySet())
+ .contains(UserManager.DISALLOW_CONFIG_DATE_TIME);
+ assertWithMessage("User restriction was put into non-parent PO instance")
+ .that(dpms.getProfileOwnerAdminLocked(COPE_PROFILE_USER_ID)
+ .getEffectiveRestrictions().keySet())
+ .doesNotContain(UserManager.DISALLOW_CONFIG_DATE_TIME);
+ assertWithMessage("Personal apps suspension wasn't migrated")
+ .that(dpm.getPersonalAppsSuspendedReasons(admin1))
+ .isEqualTo(DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED);
});
}
@SmallTest
+ @Test
public void testCompMigration_keepSuspendedAppsWhenDpcIsRPlus() throws Exception {
prepareAdmin1AsDo();
prepareAdmin1AsPo(COPE_PROFILE_USER_ID, Build.VERSION_CODES.R);
@@ -445,13 +463,14 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
poContext.binder.callingUid = UserHandle.getUid(COPE_PROFILE_USER_ID, COPE_ADMIN1_APP_ID);
runAsCaller(poContext, dpms, dpm -> {
- assertEquals("Personal apps suspension wasn't migrated",
- DevicePolicyManager.PERSONAL_APPS_SUSPENDED_EXPLICITLY,
- dpm.getPersonalAppsSuspendedReasons(admin1));
+ assertWithMessage("Personal apps suspension wasn't migrated")
+ .that(dpm.getPersonalAppsSuspendedReasons(admin1))
+ .isEqualTo(DevicePolicyManager.PERSONAL_APPS_SUSPENDED_EXPLICITLY);
});
}
@SmallTest
+ @Test
public void testCompMigration_unsuspendAppsWhenDpcNotRPlus() throws Exception {
prepareAdmin1AsDo();
prepareAdmin1AsPo(COPE_PROFILE_USER_ID, Build.VERSION_CODES.Q);
@@ -470,9 +489,9 @@ public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
poContext.binder.callingUid = UserHandle.getUid(COPE_PROFILE_USER_ID, COPE_ADMIN1_APP_ID);
runAsCaller(poContext, dpms, dpm -> {
- assertEquals("Personal apps weren't unsuspended",
- DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED,
- dpm.getPersonalAppsSuspendedReasons(admin1));
+ assertWithMessage("Personal apps weren't unsuspended")
+ .that(dpm.getPersonalAppsSuspendedReasons(admin1))
+ .isEqualTo(DevicePolicyManager.PERSONAL_APPS_NOT_SUSPENDED);
});
}
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 c4f7b9547277..8d7bc16fcf56 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -39,7 +39,9 @@ import static com.android.server.devicepolicy.DpmMockContext.CALLER_USER_HANDLE;
import static com.android.server.testutils.TestUtils.assertExpectException;
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.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
@@ -89,13 +91,14 @@ import android.os.Bundle;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
+import android.platform.test.annotations.FlakyTest;
import android.platform.test.annotations.Presubmit;
import android.provider.Settings;
import android.security.KeyChain;
import android.security.keystore.AttestationUtils;
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
-import android.test.MoreAsserts;
+import android.test.MoreAsserts; // TODO(b/171932723): replace by Truth
import android.util.ArraySet;
import android.util.Pair;
@@ -111,6 +114,9 @@ import com.android.server.devicepolicy.DevicePolicyManagerService.RestrictionsLi
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.internal.util.collections.Sets;
import org.mockito.stubbing.Answer;
@@ -127,17 +133,11 @@ import java.util.concurrent.TimeUnit;
/**
* Tests for DevicePolicyManager( and DevicePolicyManagerService).
- * You can run them via:
- m FrameworksServicesTests &&
- adb install \
- -r ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
- adb shell am instrument -e class com.android.server.devicepolicy.DevicePolicyManagerTest \
- -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
-
- (mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
*
- * , or:
- * runtest -c com.android.server.devicepolicy.DevicePolicyManagerTest frameworks-services
+ * <p>Run this test with:
+ *
+ * {@code atest FrameworksServicesTests:com.android.server.devicepolicy.DevicePolicyManagerTest}
+ *
*/
@SmallTest
@Presubmit
@@ -205,9 +205,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
private static final String PROFILE_OFF_SUSPENSION_TEXT = "suspension_text";
private static final String PROFILE_OFF_SUSPENSION_SOON_TEXT = "suspension_tomorrow_text";
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
mContext = getContext();
mServiceContext = mContext;
@@ -251,11 +250,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
return dpms.mTransferOwnershipMetadataManager;
}
- @Override
- protected void tearDown() throws Exception {
+ @After
+ public void tearDown() throws Exception {
flushTasks(dpms);
getMockTransferMetadataManager().deleteMetadataFile();
- super.tearDown();
}
private void initializeDpms() {
@@ -336,14 +334,15 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// PO needs to be a DA.
dpm.setActiveAdmin(admin, /*replace=*/ false);
// Fire!
- assertTrue(dpm.setProfileOwner(admin, "owner-name", CALLER_USER_HANDLE));
+ assertThat(dpm.setProfileOwner(admin, "owner-name", CALLER_USER_HANDLE)).isTrue();
// Check
- assertEquals(admin, dpm.getProfileOwnerAsUser(CALLER_USER_HANDLE));
+ assertThat(dpm.getProfileOwnerAsUser(CALLER_USER_HANDLE)).isEqualTo(admin);
});
mServiceContext.binder.restoreCallingIdentity(ident);
}
+ @Test
public void testHasNoFeature() throws Exception {
when(getServices().packageManager.hasSystemFeature(eq(PackageManager.FEATURE_DEVICE_ADMIN)))
.thenReturn(false);
@@ -352,9 +351,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
new DevicePolicyManagerServiceTestable(getServices(), mContext);
// If the device has no DPMS feature, it shouldn't register the local service.
- assertNull(LocalServices.getService(DevicePolicyManagerInternal.class));
+ assertThat(LocalServices.getService(DevicePolicyManagerInternal.class)).isNull();
}
+ @Test
public void testLoadAdminData() throws Exception {
// Device owner in SYSTEM_USER
setDeviceOwner();
@@ -365,7 +365,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
final int ANOTHER_UID = UserHandle.getUid(CALLER_USER_HANDLE, 1306);
setUpPackageManagerForFakeAdmin(adminAnotherPackage, ANOTHER_UID, admin2);
dpm.setActiveAdmin(adminAnotherPackage, /* replace =*/ false, CALLER_USER_HANDLE);
- assertTrue(dpm.isAdminActiveAsUser(adminAnotherPackage, CALLER_USER_HANDLE));
+ assertThat(dpm.isAdminActiveAsUser(adminAnotherPackage, CALLER_USER_HANDLE)).isTrue();
initializeDpms();
@@ -381,6 +381,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().networkPolicyManagerInternal).onAdminDataAvailable();
}
+ @Test
public void testLoadAdminData_noAdmins() throws Exception {
final int ANOTHER_USER_ID = 15;
getServices().addUser(ANOTHER_USER_ID, 0, "");
@@ -399,6 +400,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
/**
* Caller doesn't have proper permissions.
*/
+ @Test
public void testSetActiveAdmin_SecurityException() {
// 1. Failure cases.
@@ -422,6 +424,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
* {@link DevicePolicyManager#getActiveAdmins}
* {@link DevicePolicyManager#getActiveAdminsAsUser}
*/
+ @Test
public void testSetActiveAdmin() throws Exception {
// 1. Make sure the caller has proper permissions.
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
@@ -456,9 +459,9 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// TODO Verify other calls too.
// Make sure it's active admin1.
- assertTrue(dpm.isAdminActive(admin1));
- assertFalse(dpm.isAdminActive(admin2));
- assertFalse(dpm.isAdminActive(admin3));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
+ assertThat(dpm.isAdminActive(admin2)).isFalse();
+ assertThat(dpm.isAdminActive(admin3)).isFalse();
// But not admin1 for a different user.
@@ -466,8 +469,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// (Because we're checking a different user's status from CALLER_USER_HANDLE.)
mContext.callerPermissions.add("android.permission.INTERACT_ACROSS_USERS_FULL");
- assertFalse(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE + 1));
- assertFalse(dpm.isAdminActiveAsUser(admin2, CALLER_USER_HANDLE + 1));
+ assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE + 1)).isFalse();
+ assertThat(dpm.isAdminActiveAsUser(admin2, CALLER_USER_HANDLE + 1)).isFalse();
mContext.callerPermissions.remove("android.permission.INTERACT_ACROSS_USERS_FULL");
@@ -479,9 +482,9 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setActiveAdmin(admin2, /* replace =*/ false);
// Now we have two admins.
- assertTrue(dpm.isAdminActive(admin1));
- assertTrue(dpm.isAdminActive(admin2));
- assertFalse(dpm.isAdminActive(admin3));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
+ assertThat(dpm.isAdminActive(admin2)).isTrue();
+ assertThat(dpm.isAdminActive(admin3)).isFalse();
// Admin2 was already enabled, so setApplicationEnabledSetting() shouldn't have called
// again. (times(1) because it was previously called for admin1)
@@ -508,9 +511,9 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// 6. Test getActiveAdmins()
List<ComponentName> admins = dpm.getActiveAdmins();
- assertEquals(2, admins.size());
- assertEquals(admin1, admins.get(0));
- assertEquals(admin2, admins.get(1));
+ assertThat(admins.size()).isEqualTo(2);
+ assertThat(admins.get(0)).isEqualTo(admin1);
+ assertThat(admins.get(1)).isEqualTo(admin2);
// There shouldn't be any callback to UsageStatsManagerInternal when the admin is being
// replaced
@@ -519,12 +522,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Another user has no admins.
mContext.callerPermissions.add("android.permission.INTERACT_ACROSS_USERS_FULL");
- assertEquals(0, DpmTestUtils.getListSizeAllowingNull(
- dpm.getActiveAdminsAsUser(CALLER_USER_HANDLE + 1)));
+ assertThat(DpmTestUtils.getListSizeAllowingNull(
+ dpm.getActiveAdminsAsUser(CALLER_USER_HANDLE + 1))).isEqualTo(0);
mContext.callerPermissions.remove("android.permission.INTERACT_ACROSS_USERS_FULL");
}
+ @Test
public void testSetActiveAdmin_multiUsers() throws Exception {
final int ANOTHER_USER_ID = 100;
@@ -544,12 +548,12 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mMockContext.binder.callingUid = DpmMockContext.CALLER_UID;
- assertTrue(dpm.isAdminActive(admin1));
- assertFalse(dpm.isAdminActive(admin2));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
+ assertThat(dpm.isAdminActive(admin2)).isFalse();
mMockContext.binder.callingUid = ANOTHER_ADMIN_UID;
- assertFalse(dpm.isAdminActive(admin1));
- assertTrue(dpm.isAdminActive(admin2));
+ assertThat(dpm.isAdminActive(admin1)).isFalse();
+ assertThat(dpm.isAdminActive(admin2)).isTrue();
}
/**
@@ -557,12 +561,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
* {@link DevicePolicyManager#setActiveAdmin}
* with replace=false
*/
+ @Test
public void testSetActiveAdmin_twiceWithoutReplace() throws Exception {
// 1. Make sure the caller has proper permissions.
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
dpm.setActiveAdmin(admin1, /* replace =*/ false);
- assertTrue(dpm.isAdminActive(admin1));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
// Add the same admin1 again without replace, which should throw.
assertExpectException(IllegalArgumentException.class, /* messageRegex= */ null,
@@ -574,6 +579,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
* {@link DevicePolicyManager#setActiveAdmin} when the admin isn't protected with
* BIND_DEVICE_ADMIN.
*/
+ @Test
public void testSetActiveAdmin_permissionCheck() throws Exception {
// 1. Make sure the caller has proper permissions.
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
@@ -581,13 +587,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertExpectException(IllegalArgumentException.class,
/* messageRegex= */ permission.BIND_DEVICE_ADMIN,
() -> dpm.setActiveAdmin(adminNoPerm, /* replace =*/ false));
- assertFalse(dpm.isAdminActive(adminNoPerm));
+ assertThat(dpm.isAdminActive(adminNoPerm)).isFalse();
// Change the target API level to MNC. Now it can be set as DA.
setUpPackageManagerForAdmin(adminNoPerm, DpmMockContext.CALLER_UID, null,
VERSION_CODES.M);
dpm.setActiveAdmin(adminNoPerm, /* replace =*/ false);
- assertTrue(dpm.isAdminActive(adminNoPerm));
+ assertThat(dpm.isAdminActive(adminNoPerm)).isTrue();
// TODO Test the "load from the file" case where DA will still be loaded even without
// BIND_DEVICE_ADMIN and target API is N.
@@ -597,6 +603,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
* Test for:
* {@link DevicePolicyManager#removeActiveAdmin}
*/
+ @Test
public void testRemoveActiveAdmin_SecurityException() {
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
@@ -604,9 +611,9 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setActiveAdmin(admin1, /* replace =*/ false);
- assertTrue(dpm.isAdminActive(admin1));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
- assertFalse(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE)).isFalse();
// Directly call the DPMS method with a different userid, which should fail.
assertExpectException(SecurityException.class, /* messageRegex =*/ null,
@@ -627,6 +634,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
* {@link DevicePolicyManager#removeActiveAdmin} should fail with the user is not unlocked
* (because we can't send the remove broadcast).
*/
+ @Test
public void testRemoveActiveAdmin_userNotRunningOrLocked() {
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
@@ -636,9 +644,9 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setActiveAdmin(admin1, /* replace =*/ false);
- assertTrue(dpm.isAdminActive(admin1));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
- assertFalse(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE)).isFalse();
// 1. User not unlocked.
setUserUnlocked(CALLER_USER_HANDLE, false);
@@ -646,7 +654,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
/* messageRegex= */ "User must be running and unlocked",
() -> dpm.removeActiveAdmin(admin1));
- assertFalse(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE)).isFalse();
verify(getServices().usageStatsManagerInternal, times(0)).setActiveAdminApps(
null, CALLER_USER_HANDLE);
@@ -654,7 +662,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setUserUnlocked(CALLER_USER_HANDLE, true);
dpm.removeActiveAdmin(admin1);
- assertFalse(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse();
verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
null, CALLER_USER_HANDLE);
}
@@ -663,6 +671,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
* Test for:
* {@link DevicePolicyManager#removeActiveAdmin}
*/
+ @Test
public void testRemoveActiveAdmin_fromDifferentUserWithINTERACT_ACROSS_USERS_FULL() {
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
@@ -670,8 +679,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setActiveAdmin(admin1, /* replace =*/ false);
- assertTrue(dpm.isAdminActive(admin1));
- assertFalse(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
+ assertThat(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE)).isFalse();
// Different user, but should work, because caller has proper permissions.
mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
@@ -680,7 +689,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = 1234567;
dpms.removeActiveAdmin(admin1, CALLER_USER_HANDLE);
- assertFalse(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse();
verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
null, CALLER_USER_HANDLE);
@@ -691,6 +700,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
* Test for:
* {@link DevicePolicyManager#removeActiveAdmin}
*/
+ @Test
public void testRemoveActiveAdmin_sameUserNoMANAGE_DEVICE_ADMINS() {
// Need MANAGE_DEVICE_ADMINS for setActiveAdmin. We'll remove it later.
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
@@ -699,8 +709,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setActiveAdmin(admin1, /* replace =*/ false);
- assertTrue(dpm.isAdminActive(admin1));
- assertFalse(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
+ assertThat(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE)).isFalse();
// Broadcast from saveSettingsLocked().
verify(mContext.spiedContext, times(1)).sendBroadcastAsUser(
@@ -725,7 +735,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
isNull(String.class),
isNull(Bundle.class));
- assertFalse(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse();
verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
null, CALLER_USER_HANDLE);
@@ -738,6 +748,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// TODO Check other internal calls.
}
+ @Test
public void testRemoveActiveAdmin_multipleAdminsInUser() {
// Need MANAGE_DEVICE_ADMINS for setActiveAdmin. We'll remove it later.
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
@@ -745,14 +756,14 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Add admin1.
dpm.setActiveAdmin(admin1, /* replace =*/ false);
- assertTrue(dpm.isAdminActive(admin1));
- assertFalse(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
+ assertThat(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE)).isFalse();
// Add admin2.
dpm.setActiveAdmin(admin2, /* replace =*/ false);
- assertTrue(dpm.isAdminActive(admin2));
- assertFalse(dpm.isRemovingAdmin(admin2, CALLER_USER_HANDLE));
+ assertThat(dpm.isAdminActive(admin2)).isTrue();
+ assertThat(dpm.isRemovingAdmin(admin2, CALLER_USER_HANDLE)).isFalse();
// Broadcast from saveSettingsLocked().
verify(mContext.spiedContext, times(2)).sendBroadcastAsUser(
@@ -777,7 +788,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
isNull(String.class),
isNull(Bundle.class));
- assertFalse(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse();
verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
MockUtils.checkApps(admin2.getPackageName()),
eq(CALLER_USER_HANDLE));
@@ -793,6 +804,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
* Test for:
* {@link DevicePolicyManager#forceRemoveActiveAdmin(ComponentName, int)}
*/
+ @Test
public void testForceRemoveActiveAdmin() throws Exception {
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
@@ -802,7 +814,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
/* appId= */ 10138,
/* flags= */ ApplicationInfo.FLAG_TEST_ONLY);
dpm.setActiveAdmin(admin1, /* replace =*/ false);
- assertTrue(dpm.isAdminActive(admin1));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
// Calling from a non-shell uid should fail with a SecurityException
mContext.binder.callingUid = 123456;
@@ -815,7 +827,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.callerPermissions.add(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
// Verify
- assertFalse(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse();
verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
null, CALLER_USER_HANDLE);
}
@@ -825,6 +837,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
*
* Validates that when the password history length is set, it is persisted after rebooting
*/
+ @Test
public void testSaveAndLoadPasswordHistoryLength_persistedAfterReboot() throws Exception {
int passwordHistoryLength = 2;
@@ -842,13 +855,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Save password history length
dpm.setPasswordHistoryLength(admin1, passwordHistoryLength);
- assertEquals(dpm.getPasswordHistoryLength(admin1), passwordHistoryLength);
+ assertThat(passwordHistoryLength).isEqualTo(dpm.getPasswordHistoryLength(admin1));
initializeDpms();
reset(mContext.spiedContext);
// Password history length should persist after rebooted
- assertEquals(dpm.getPasswordHistoryLength(admin1), passwordHistoryLength);
+ assertThat(passwordHistoryLength).isEqualTo(dpm.getPasswordHistoryLength(admin1));
}
/**
@@ -858,6 +871,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
* {@link DeviceAdminReceiver#ACTION_PASSWORD_CHANGED} is sent to managed profile owners, in
* addition to ones in the original user.
*/
+ @Test
public void testSetActivePasswordState_sendToProfiles() throws Exception {
mContext.callerPermissions.add(permission.BIND_DEVICE_ADMIN);
@@ -893,6 +907,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
* intent {@link DeviceAdminReceiver#ACTION_PASSWORD_CHANGED} is only sent to the profile, not
* its parent.
*/
+ @Test
public void testSetActivePasswordState_notSentToParent() throws Exception {
mContext.callerPermissions.add(permission.BIND_DEVICE_ADMIN);
@@ -932,6 +947,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
/**
* Test for: {@link DevicePolicyManager#setDeviceOwner} DO on system user installs successfully.
*/
+ @Test
public void testSetDeviceOwner() throws Exception {
setDeviceOwner();
@@ -944,7 +960,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// DO admin can't be deactivated.
dpm.removeActiveAdmin(admin1);
- assertTrue(dpm.isAdminActive(admin1));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
// TODO Test getDeviceOwnerName() too. To do so, we need to change
// DPMS.getApplicationLabel() because Context.createPackageContextAsUser() is not mockable.
@@ -969,19 +985,19 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setActiveAdmin(admin1, /* replace =*/ false);
// Fire!
- assertTrue(dpm.setDeviceOwner(admin1, "owner-name"));
+ assertThat(dpm.setDeviceOwner(admin1, "owner-name")).isTrue();
// getDeviceOwnerComponent should return the admin1 component.
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+ assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(admin1);
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
// Check various get APIs.
checkGetDeviceOwnerInfoApi(dpm, /* hasDeviceOwner =*/ true);
// getDeviceOwnerComponent should *NOT* return the admin1 component for other users.
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
- assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+ assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(null);
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -997,7 +1013,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
MockUtils.checkIntentAction(DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED),
MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
}
private void checkGetDeviceOwnerInfoApi(DevicePolicyManager dpm, boolean hasDeviceOwner) {
@@ -1012,89 +1028,89 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// TODO Test getDeviceOwnerName() too. To do so, we need to change
// DPMS.getApplicationLabel() because Context.createPackageContextAsUser() is not mockable.
if (hasDeviceOwner) {
- assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
- assertTrue(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+ assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isTrue();
+ assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isTrue();
+ assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(admin1);
- assertTrue(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
- assertEquals(UserHandle.USER_SYSTEM, dpm.getDeviceOwnerUserId());
+ assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isTrue();
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
+ assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
} else {
- assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
- assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
- assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+ assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isFalse();
+ assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isFalse();
+ assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(null);
- assertFalse(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
- assertEquals(null, dpm.getDeviceOwnerComponentOnAnyUser());
- assertEquals(UserHandle.USER_NULL, dpm.getDeviceOwnerUserId());
+ assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isFalse();
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(null);
+ assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
}
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
if (hasDeviceOwner) {
- assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
- assertTrue(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+ assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isTrue();
+ assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isTrue();
+ assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(admin1);
- assertTrue(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
- assertEquals(UserHandle.USER_SYSTEM, dpm.getDeviceOwnerUserId());
+ assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isTrue();
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
+ assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
} else {
- assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
- assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
- assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+ assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isFalse();
+ assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isFalse();
+ assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(null);
- assertFalse(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
- assertEquals(null, dpm.getDeviceOwnerComponentOnAnyUser());
- assertEquals(UserHandle.USER_NULL, dpm.getDeviceOwnerUserId());
+ assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isFalse();
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(null);
+ assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
}
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
// Still with MANAGE_USERS.
- assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
- assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
- assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+ assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isFalse();
+ assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isFalse();
+ assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(null);
if (hasDeviceOwner) {
- assertTrue(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
- assertEquals(UserHandle.USER_SYSTEM, dpm.getDeviceOwnerUserId());
+ assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isTrue();
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
+ assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
} else {
- assertFalse(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
- assertEquals(null, dpm.getDeviceOwnerComponentOnAnyUser());
- assertEquals(UserHandle.USER_NULL, dpm.getDeviceOwnerUserId());
+ assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isFalse();
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(null);
+ assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
}
mContext.binder.callingUid = Process.SYSTEM_UID;
mContext.callerPermissions.remove(permission.MANAGE_USERS);
// System can still call "OnAnyUser" without MANAGE_USERS.
if (hasDeviceOwner) {
- assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
- assertTrue(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+ assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isTrue();
+ assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isTrue();
+ assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(admin1);
- assertTrue(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
- assertEquals(UserHandle.USER_SYSTEM, dpm.getDeviceOwnerUserId());
+ assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isTrue();
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
+ assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
} else {
- assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
- assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
- assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+ assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isFalse();
+ assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isFalse();
+ assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(null);
- assertFalse(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
- assertEquals(null, dpm.getDeviceOwnerComponentOnAnyUser());
- assertEquals(UserHandle.USER_NULL, dpm.getDeviceOwnerUserId());
+ assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isFalse();
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(null);
+ assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
}
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
// Still no MANAGE_USERS.
if (hasDeviceOwner) {
- assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
- assertTrue(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+ assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isTrue();
+ assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isTrue();
+ assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(admin1);
} else {
- assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
- assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
- assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+ assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isFalse();
+ assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isFalse();
+ assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(null);
}
assertExpectException(SecurityException.class, /* messageRegex =*/ null,
@@ -1108,9 +1124,9 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
// Still no MANAGE_USERS.
- assertFalse(dpm.isDeviceOwnerApp(admin1.getPackageName()));
- assertFalse(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
- assertEquals(null, dpm.getDeviceOwnerComponentOnCallingUser());
+ assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isFalse();
+ assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isFalse();
+ assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(null);
assertExpectException(SecurityException.class, /* messageRegex =*/ null,
() -> dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
@@ -1130,6 +1146,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
/**
* Test for: {@link DevicePolicyManager#setDeviceOwner} Package doesn't exist.
*/
+ @Test
public void testSetDeviceOwner_noSuchPackage() {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_USERS);
@@ -1144,10 +1161,12 @@ public class DevicePolicyManagerTest extends DpmTestBase {
() -> dpm.setDeviceOwner(new ComponentName("a.b.c", ".def")));
}
+ @Test
public void testSetDeviceOwner_failures() throws Exception {
// TODO Test more failure cases. Basically test all chacks in enforceCanSetDeviceOwner().
}
+ @Test
public void testClearDeviceOwner() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_USERS);
@@ -1164,20 +1183,20 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
dpm.setActiveAdmin(admin1, /* replace =*/ false);
- assertTrue(dpm.setDeviceOwner(admin1, "owner-name"));
+ assertThat(dpm.setDeviceOwner(admin1, "owner-name")).isTrue();
// Verify internal calls.
verify(getServices().iactivityManager, times(1)).updateDeviceOwner(
eq(admin1.getPackageName()));
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
dpm.addUserRestriction(admin1, UserManager.DISALLOW_ADD_USER);
when(getServices().userManager.hasUserRestriction(eq(UserManager.DISALLOW_ADD_USER),
MockUtils.checkUserHandle(UserHandle.USER_SYSTEM))).thenReturn(true);
- assertTrue(dpm.isAdminActive(admin1));
- assertFalse(dpm.isRemovingAdmin(admin1, UserHandle.USER_SYSTEM));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
+ assertThat(dpm.isRemovingAdmin(admin1, UserHandle.USER_SYSTEM)).isFalse();
// Set up other mocks.
when(getServices().userManager.getUserRestrictions()).thenReturn(new Bundle());
@@ -1196,7 +1215,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.clearDeviceOwnerApp(admin1.getPackageName());
// Now DO shouldn't be set.
- assertNull(dpm.getDeviceOwnerComponentOnAnyUser());
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isNull();
verify(getServices().userManager).setUserRestriction(eq(UserManager.DISALLOW_ADD_USER),
eq(false),
@@ -1209,7 +1228,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
null, UserHandle.USER_SYSTEM);
- assertFalse(dpm.isAdminActiveAsUser(admin1, UserHandle.USER_SYSTEM));
+ assertThat(dpm.isAdminActiveAsUser(admin1, UserHandle.USER_SYSTEM)).isFalse();
// ACTION_DEVICE_OWNER_CHANGED should be sent twice, once for setting the device owner
// and once for clearing it.
@@ -1219,6 +1238,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// TODO Check other calls.
}
+ @Test
public void testDeviceOwnerBackupActivateDeactivate() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -1227,7 +1247,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
dpm.setActiveAdmin(admin1, /* replace =*/ false);
- assertTrue(dpm.setDeviceOwner(admin1, "owner-name"));
+ assertThat(dpm.setDeviceOwner(admin1, "owner-name")).isTrue();
verify(getServices().ibackupManager, times(1)).setBackupServiceActive(
eq(UserHandle.USER_SYSTEM), eq(false));
@@ -1238,6 +1258,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
eq(UserHandle.USER_SYSTEM), eq(true));
}
+ @Test
public void testProfileOwnerBackupActivateDeactivate() throws Exception {
setAsProfileOwner(admin1);
@@ -1250,6 +1271,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
eq(CALLER_USER_HANDLE), eq(true));
}
+ @Test
public void testClearDeviceOwner_fromDifferentUser() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_USERS);
@@ -1266,13 +1288,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
dpm.setActiveAdmin(admin1, /* replace =*/ false);
- assertTrue(dpm.setDeviceOwner(admin1, "owner-name"));
+ assertThat(dpm.setDeviceOwner(admin1, "owner-name")).isTrue();
// Verify internal calls.
verify(getServices().iactivityManager, times(1)).updateDeviceOwner(
eq(admin1.getPackageName()));
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
// Now call clear from the secondary user, which should throw.
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
@@ -1286,7 +1308,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
() -> dpm.clearDeviceOwnerApp(admin1.getPackageName()));
// DO shouldn't be removed.
- assertTrue(dpm.isDeviceManaged());
+ assertThat(dpm.isDeviceManaged()).isTrue();
}
/**
@@ -1294,6 +1316,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
*
* Validates that when the device owner is removed, the reset password token is cleared
*/
+ @Test
public void testClearDeviceOwner_clearResetPasswordToken() throws Exception {
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -1312,13 +1335,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
when(getServices().lockPatternUtils.addEscrowToken(eq(token), eq(UserHandle.USER_SYSTEM),
nullable(EscrowTokenStateChangeCallback.class)))
.thenReturn(handle);
- assertTrue(dpm.setResetPasswordToken(admin1, token));
+ assertThat(dpm.setResetPasswordToken(admin1, token)).isTrue();
// Assert reset password token is active
when(getServices().lockPatternUtils.isEscrowTokenActive(eq(handle),
eq(UserHandle.USER_SYSTEM)))
.thenReturn(true);
- assertTrue(dpm.isResetPasswordTokenActive(admin1));
+ assertThat(dpm.isResetPasswordTokenActive(admin1)).isTrue();
// Remove the device owner
dpm.clearDeviceOwnerApp(admin1.getPackageName());
@@ -1328,12 +1351,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
eq(UserHandle.USER_SYSTEM));
}
+ @Test
public void testSetProfileOwner() throws Exception {
setAsProfileOwner(admin1);
// PO admin can't be deactivated.
dpm.removeActiveAdmin(admin1);
- assertTrue(dpm.isAdminActive(admin1));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
// Try setting DO on the same user, which should fail.
setUpPackageManagerForAdmin(admin2, DpmMockContext.CALLER_UID);
@@ -1347,13 +1371,14 @@ public class DevicePolicyManagerTest extends DpmTestBase {
});
}
+ @Test
public void testClearProfileOwner() throws Exception {
setAsProfileOwner(admin1);
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
- assertTrue(dpm.isProfileOwnerApp(admin1.getPackageName()));
- assertFalse(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.isProfileOwnerApp(admin1.getPackageName())).isTrue();
+ assertThat(dpm.isRemovingAdmin(admin1, CALLER_USER_HANDLE)).isFalse();
// First try when the user is locked, which should fail.
when(getServices().userManager.isUserUnlocked(anyInt()))
@@ -1367,16 +1392,18 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.clearProfileOwner(admin1);
// Check
- assertFalse(dpm.isProfileOwnerApp(admin1.getPackageName()));
- assertFalse(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.isProfileOwnerApp(admin1.getPackageName())).isFalse();
+ assertThat(dpm.isAdminActiveAsUser(admin1, CALLER_USER_HANDLE)).isFalse();
verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
null, CALLER_USER_HANDLE);
}
+ @Test
public void testSetProfileOwner_failures() throws Exception {
// TODO Test more failure cases. Basically test all chacks in enforceCanSetProfileOwner().
}
+ @Test
public void testGetDeviceOwnerAdminLocked() throws Exception {
checkDeviceOwnerWithMultipleDeviceAdmins();
}
@@ -1421,13 +1448,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Set DO on the first non-system user.
getServices().setUserRunning(CALLER_USER_HANDLE, true);
- assertTrue(dpm.setDeviceOwner(admin2, "owner-name", CALLER_USER_HANDLE));
+ assertThat(dpm.setDeviceOwner(admin2, "owner-name", CALLER_USER_HANDLE)).isTrue();
- assertEquals(admin2, dpms.getDeviceOwnerComponent(/* callingUserOnly =*/ false));
+ assertThat(dpms.getDeviceOwnerComponent(/* callingUserOnly =*/ false)).isEqualTo(admin2);
// Then check getDeviceOwnerAdminLocked().
- assertEquals(admin2, getDeviceOwner().info.getComponent());
- assertEquals(DpmMockContext.CALLER_UID, getDeviceOwner().getUid());
+ assertThat(getDeviceOwner().info.getComponent()).isEqualTo(admin2);
+ assertThat(getDeviceOwner().getUid()).isEqualTo(DpmMockContext.CALLER_UID);
}
/**
@@ -1438,6 +1465,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
* We didn't use to persist the DO component class name, but now we do, and the above method
* finds the right component from a package name upon migration.
*/
+ @Test
public void testDeviceOwnerMigration() throws Exception {
when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
checkDeviceOwnerWithMultipleDeviceAdmins();
@@ -1449,7 +1477,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpms.mOwners.writeDeviceOwner();
// Make sure the DO component name doesn't have a class name.
- assertEquals("", dpms.getDeviceOwnerComponent(/* callingUserOnly =*/ false).getClassName());
+ assertThat(dpms.getDeviceOwnerComponent(/* callingUserOnly= */ false).getClassName())
+ .isEmpty();
// Then create a new DPMS to have it load the settings from files.
when(getServices().userManager.getUserRestrictions(any(UserHandle.class)))
@@ -1459,9 +1488,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Now the DO component name is a full name.
// *BUT* because both admin1 and admin2 belong to the same package, we think admin1 is the
// DO.
- assertEquals(admin1, dpms.getDeviceOwnerComponent(/* callingUserOnly =*/ false));
+ assertThat(dpms.getDeviceOwnerComponent(/* callingUserOnly =*/ false)).isEqualTo(admin1);
}
+ @Test
public void testSetGetApplicationRestriction() {
setAsProfileOwner(admin1);
mContext.packageName = admin1.getPackageName();
@@ -1480,20 +1510,20 @@ public class DevicePolicyManagerTest extends DpmTestBase {
{
Bundle returned = dpm.getApplicationRestrictions(admin1, "pkg1");
- assertNotNull(returned);
- assertEquals(returned.size(), 1);
- assertEquals(returned.get("KEY_STRING"), "Foo1");
+ assertThat(returned).isNotNull();
+ assertThat(returned.size()).isEqualTo(1);
+ assertThat("Foo1").isEqualTo(returned.get("KEY_STRING"));
}
{
Bundle returned = dpm.getApplicationRestrictions(admin1, "pkg2");
- assertNotNull(returned);
- assertEquals(returned.size(), 1);
- assertEquals(returned.get("KEY_STRING"), "Foo2");
+ assertThat(returned).isNotNull();
+ assertThat(returned.size()).isEqualTo(1);
+ assertThat("Foo2").isEqualTo(returned.get("KEY_STRING"));
}
dpm.setApplicationRestrictions(admin1, "pkg2", new Bundle());
- assertEquals(0, dpm.getApplicationRestrictions(admin1, "pkg2").size());
+ assertThat(dpm.getApplicationRestrictions(admin1, "pkg2").size()).isEqualTo(0);
}
/**
@@ -1546,6 +1576,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
return uid;
}
+ @Test
public void testCertificateDisclosure() throws Exception {
final int userId = CALLER_USER_HANDLE;
final UserHandle user = UserHandle.of(userId);
@@ -1571,7 +1602,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.cancelAsUser(anyString(), anyInt(), eq(user));
// Given that we have four certificates installed,
- when(getServices().keyChainConnection.getService().getUserCaAliases()).thenReturn(fourCerts);
+ when(getServices().keyChainConnection.getService().getUserCaAliases())
+ .thenReturn(fourCerts);
// when two of them are approved (one of them approved twice hence no action),
dpms.approveCaCert(fourCerts.getList().get(0), userId, true);
dpms.approveCaCert(fourCerts.getList().get(1), userId, true);
@@ -1586,6 +1618,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
* Simple test for delegate set/get and general delegation. Tests verifying that delegated
* privileges can acually be exercised by a delegate are not covered here.
*/
+ @Test
public void testDelegation() throws Exception {
setAsProfileOwner(admin1);
@@ -1606,17 +1639,18 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// DPMS correctly stores and retrieves the delegates
DevicePolicyData policy = dpms.mUserData.get(userHandle);
- assertEquals(2, policy.mDelegationMap.size());
+ assertThat(policy.mDelegationMap.size()).isEqualTo(2);
MoreAsserts.assertContentsInAnyOrder(policy.mDelegationMap.get(CERT_DELEGATE),
DELEGATION_CERT_INSTALL);
MoreAsserts.assertContentsInAnyOrder(dpm.getDelegatedScopes(admin1, CERT_DELEGATE),
DELEGATION_CERT_INSTALL);
- assertEquals(CERT_DELEGATE, dpm.getCertInstallerPackage(admin1));
+ assertThat(dpm.getCertInstallerPackage(admin1)).isEqualTo(CERT_DELEGATE);
MoreAsserts.assertContentsInAnyOrder(policy.mDelegationMap.get(RESTRICTIONS_DELEGATE),
DELEGATION_APP_RESTRICTIONS);
MoreAsserts.assertContentsInAnyOrder(dpm.getDelegatedScopes(admin1, RESTRICTIONS_DELEGATE),
DELEGATION_APP_RESTRICTIONS);
- assertEquals(RESTRICTIONS_DELEGATE, dpm.getApplicationRestrictionsManagingPackage(admin1));
+ assertThat(dpm.getApplicationRestrictionsManagingPackage(admin1))
+ .isEqualTo(RESTRICTIONS_DELEGATE);
// On calling install certificate APIs from an unauthorized process
mContext.binder.callingUid = RESTRICTIONS_DELEGATE_UID;
@@ -1658,6 +1692,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
}
+ @Test
public void testApplicationRestrictionsManagingApp() throws Exception {
setAsProfileOwner(admin1);
@@ -1673,7 +1708,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// delegated that permission yet.
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
mContext.packageName = admin1.getPackageName();
- assertFalse(dpm.isCallerApplicationRestrictionsManagingPackage());
+ assertThat(dpm.isCallerApplicationRestrictionsManagingPackage()).isFalse();
final Bundle rest = new Bundle();
rest.putString("KEY_STRING", "Foo1");
assertExpectException(SecurityException.class, INVALID_CALLING_IDENTITY_MSG,
@@ -1682,7 +1717,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Check via the profile owner that no restrictions were set.
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
mContext.packageName = admin1.getPackageName();
- assertEquals(0, dpm.getApplicationRestrictions(admin1, "pkg1").size());
+ assertThat(dpm.getApplicationRestrictions(admin1, "pkg1").size()).isEqualTo(0);
// Check the API does not allow setting a non-existent package
assertExpectException(PackageManager.NameNotFoundException.class,
@@ -1692,22 +1727,22 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Let appRestrictionsManagerPackage manage app restrictions
dpm.setApplicationRestrictionsManagingPackage(admin1, appRestrictionsManagerPackage);
- assertEquals(appRestrictionsManagerPackage,
- dpm.getApplicationRestrictionsManagingPackage(admin1));
+ assertThat(dpm.getApplicationRestrictionsManagingPackage(admin1))
+ .isEqualTo(appRestrictionsManagerPackage);
// Now that package should be able to set and retrieve app restrictions.
mContext.binder.callingUid = appRestrictionsManagerUid;
mContext.packageName = appRestrictionsManagerPackage;
- assertTrue(dpm.isCallerApplicationRestrictionsManagingPackage());
+ assertThat(dpm.isCallerApplicationRestrictionsManagingPackage()).isTrue();
dpm.setApplicationRestrictions(null, "pkg1", rest);
Bundle returned = dpm.getApplicationRestrictions(null, "pkg1");
- assertEquals(1, returned.size(), 1);
- assertEquals("Foo1", returned.get("KEY_STRING"));
+ assertThat(returned.size()).isEqualTo(1);
+ assertThat(returned.get("KEY_STRING")).isEqualTo("Foo1");
// The same app running on a separate user shouldn't be able to manage app restrictions.
mContext.binder.callingUid = UserHandle.getUid(
UserHandle.USER_SYSTEM, appRestrictionsManagerAppId);
- assertFalse(dpm.isCallerApplicationRestrictionsManagingPackage());
+ assertThat(dpm.isCallerApplicationRestrictionsManagingPackage()).isFalse();
assertExpectException(SecurityException.class, nonDelegateExceptionMessageRegex,
() -> dpm.setApplicationRestrictions(null, "pkg1", rest));
@@ -1715,20 +1750,21 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// too.
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
mContext.packageName = admin1.getPackageName();
- assertEquals(returned, dpm.getApplicationRestrictions(admin1, "pkg1"));
+ assertThat(dpm.getApplicationRestrictions(admin1, "pkg1")).isEqualTo(returned);
dpm.setApplicationRestrictions(admin1, "pkg1", null);
- assertEquals(0, dpm.getApplicationRestrictions(admin1, "pkg1").size());
+ assertThat(dpm.getApplicationRestrictions(admin1, "pkg1").size()).isEqualTo(0);
// Removing the ability for the package to manage app restrictions.
dpm.setApplicationRestrictionsManagingPackage(admin1, null);
- assertNull(dpm.getApplicationRestrictionsManagingPackage(admin1));
+ assertThat(dpm.getApplicationRestrictionsManagingPackage(admin1)).isNull();
mContext.binder.callingUid = appRestrictionsManagerUid;
mContext.packageName = appRestrictionsManagerPackage;
- assertFalse(dpm.isCallerApplicationRestrictionsManagingPackage());
+ assertThat(dpm.isCallerApplicationRestrictionsManagingPackage()).isFalse();
assertExpectException(SecurityException.class, INVALID_CALLING_IDENTITY_MSG,
() -> dpm.setApplicationRestrictions(null, "pkg1", null));
}
+ @Test
public void testSetUserRestriction_asDo() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_USERS);
@@ -1745,8 +1781,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Call.
dpm.setActiveAdmin(admin1, /* replace =*/ false, UserHandle.USER_SYSTEM);
- assertTrue(dpm.setDeviceOwner(admin1, "owner-name",
- UserHandle.USER_SYSTEM));
+ assertThat(dpm.setDeviceOwner(admin1, "owner-name",
+ UserHandle.USER_SYSTEM)).isTrue();
assertNoDeviceOwnerRestrictions();
reset(getServices().userManagerInternal);
@@ -1859,6 +1895,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
return null;
}
+ @Test
public void testDaDisallowedPolicies_SecurityException() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS_FULL);
@@ -1869,25 +1906,28 @@ public class DevicePolicyManagerTest extends DpmTestBase {
boolean originalCameraDisabled = dpm.getCameraDisabled(admin1);
assertExpectException(SecurityException.class, /* messageRegex= */ null,
() -> dpm.setCameraDisabled(admin1, true));
- assertEquals(originalCameraDisabled, dpm.getCameraDisabled(admin1));
+ assertThat(dpm.getCameraDisabled(admin1)).isEqualTo(originalCameraDisabled);
int originalKeyguardDisabledFeatures = dpm.getKeyguardDisabledFeatures(admin1);
assertExpectException(SecurityException.class, /* messageRegex= */ null,
() -> dpm.setKeyguardDisabledFeatures(admin1,
DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL));
- assertEquals(originalKeyguardDisabledFeatures, dpm.getKeyguardDisabledFeatures(admin1));
+ assertThat(dpm.getKeyguardDisabledFeatures(admin1))
+ .isEqualTo(originalKeyguardDisabledFeatures);
long originalPasswordExpirationTimeout = dpm.getPasswordExpirationTimeout(admin1);
assertExpectException(SecurityException.class, /* messageRegex= */ null,
() -> dpm.setPasswordExpirationTimeout(admin1, 1234));
- assertEquals(originalPasswordExpirationTimeout, dpm.getPasswordExpirationTimeout(admin1));
+ assertThat(dpm.getPasswordExpirationTimeout(admin1))
+ .isEqualTo(originalPasswordExpirationTimeout);
int originalPasswordQuality = dpm.getPasswordQuality(admin1);
assertExpectException(SecurityException.class, /* messageRegex= */ null,
() -> dpm.setPasswordQuality(admin1, DevicePolicyManager.PASSWORD_QUALITY_NUMERIC));
- assertEquals(originalPasswordQuality, dpm.getPasswordQuality(admin1));
+ assertThat(dpm.getPasswordQuality(admin1)).isEqualTo(originalPasswordQuality);
}
+ @Test
public void testSetUserRestriction_asPo() {
setAsProfileOwner(admin1);
@@ -2023,6 +2063,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
UserManager.DISALLOW_UNMUTE_MICROPHONE
);
+ @Test
public void testSetUserRestriction_asPoOfOrgOwnedDevice() throws Exception {
final int MANAGED_PROFILE_ADMIN_UID =
UserHandle.getUid(CALLER_USER_HANDLE, DpmMockContext.SYSTEM_UID);
@@ -2097,6 +2138,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
);
}
+ @Test
public void testNoDefaultEnabledUserRestrictions() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_USERS);
@@ -2112,8 +2154,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
dpm.setActiveAdmin(admin1, /* replace =*/ false, UserHandle.USER_SYSTEM);
- assertTrue(dpm.setDeviceOwner(admin1, "owner-name",
- UserHandle.USER_SYSTEM));
+ assertThat(dpm.setDeviceOwner(admin1, "owner-name",
+ UserHandle.USER_SYSTEM)).isTrue();
assertNoDeviceOwnerRestrictions();
@@ -2132,6 +2174,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
);
}
+ @Test
public void testSetFactoryResetProtectionPolicyWithDO() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -2156,6 +2199,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
eq(android.Manifest.permission.MANAGE_FACTORY_RESET_PROTECTION));
}
+ @Test
public void testSetFactoryResetProtectionPolicyFailWithPO() throws Exception {
setupProfileOwner();
@@ -2167,6 +2211,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
() -> dpm.setFactoryResetProtectionPolicy(admin1, policy));
}
+ @Test
public void testSetFactoryResetProtectionPolicyWithPOOfOrganizationOwnedDevice()
throws Exception {
setupProfileOwner();
@@ -2204,6 +2249,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
eq(android.Manifest.permission.MANAGE_FACTORY_RESET_PROTECTION));
}
+ @Test
public void testGetFactoryResetProtectionPolicyWithFrpManagementAgent()
throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -2245,6 +2291,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertThat(actualAccounts).containsExactlyElementsIn(expectedAccounts);
}
+ @Test
public void testSetKeyguardDisabledFeaturesWithDO() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -2255,6 +2302,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA);
}
+ @Test
public void testSetKeyguardDisabledFeaturesWithPO() throws Exception {
setupProfileOwner();
@@ -2264,6 +2312,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
}
+ @Test
public void testSetKeyguardDisabledFeaturesWithPOOfOrganizationOwnedDevice()
throws Exception {
final int MANAGED_PROFILE_USER_ID = CALLER_USER_HANDLE;
@@ -2281,6 +2330,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA);
}
+ @Test
public void testSetApplicationHiddenWithDO() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -2304,6 +2354,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
UserHandle.USER_SYSTEM);
}
+ @Test
public void testSetApplicationHiddenWithPOOfOrganizationOwnedDevice() throws Exception {
final int MANAGED_PROFILE_USER_ID = CALLER_USER_HANDLE;
final int MANAGED_PROFILE_ADMIN_UID =
@@ -2334,6 +2385,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
false, UserHandle.USER_SYSTEM);
}
+ @Test
public void testGetMacAddress() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -2351,7 +2403,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// DO needs to be an DA.
dpm.setActiveAdmin(admin1, /* replace =*/ false);
- assertTrue(dpm.isAdminActive(admin1));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
// Test 2. Caller has DA, but not DO.
assertExpectException(SecurityException.class,
@@ -2359,7 +2411,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
() -> dpm.getWifiMacAddress(admin1));
// Test 3. Caller has PO, but not DO.
- assertTrue(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM));
+ assertThat(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM)).isTrue();
assertExpectException(SecurityException.class,
/* messageRegex= */ INVALID_CALLING_IDENTITY_MSG,
() -> dpm.getWifiMacAddress(admin1));
@@ -2368,30 +2420,32 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.clearProfileOwner(admin1);
dpm.setActiveAdmin(admin1, false);
// Test 4, Caller is DO now.
- assertTrue(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM));
+ assertThat(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM)).isTrue();
// 4-1. But WifiManager is not ready.
- assertNull(dpm.getWifiMacAddress(admin1));
+ assertThat(dpm.getWifiMacAddress(admin1)).isNull();
// 4-2. When WifiManager returns an empty array, dpm should also output null.
when(getServices().wifiManager.getFactoryMacAddresses()).thenReturn(new String[0]);
- assertNull(dpm.getWifiMacAddress(admin1));
+ assertThat(dpm.getWifiMacAddress(admin1)).isNull();
// 4-3. With a real MAC address.
final String[] macAddresses = new String[]{"11:22:33:44:55:66"};
when(getServices().wifiManager.getFactoryMacAddresses()).thenReturn(macAddresses);
- assertEquals("11:22:33:44:55:66", dpm.getWifiMacAddress(admin1));
+ assertThat(dpm.getWifiMacAddress(admin1)).isEqualTo("11:22:33:44:55:66");
}
+ @Test
public void testGetMacAddressByOrgOwnedPO() throws Exception {
setupProfileOwner();
configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
final String[] macAddresses = new String[]{"11:22:33:44:55:66"};
when(getServices().wifiManager.getFactoryMacAddresses()).thenReturn(macAddresses);
- assertEquals("11:22:33:44:55:66", dpm.getWifiMacAddress(admin1));
+ assertThat(dpm.getWifiMacAddress(admin1)).isEqualTo("11:22:33:44:55:66");
}
+ @Test
public void testReboot() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -2404,19 +2458,19 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Set admin1 as DA.
dpm.setActiveAdmin(admin1, false);
- assertTrue(dpm.isAdminActive(admin1));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
assertExpectException(SecurityException.class, /* messageRegex= */
INVALID_CALLING_IDENTITY_MSG, () -> dpm.reboot(admin1));
// Set admin1 as PO.
- assertTrue(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM));
+ assertThat(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM)).isTrue();
assertExpectException(SecurityException.class, /* messageRegex= */
INVALID_CALLING_IDENTITY_MSG, () -> dpm.reboot(admin1));
// Remove PO and add DO.
dpm.clearProfileOwner(admin1);
dpm.setActiveAdmin(admin1, false);
- assertTrue(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM));
+ assertThat(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM)).isTrue();
// admin1 is DO.
// Set current call state of device to ringing.
@@ -2432,10 +2486,12 @@ public class DevicePolicyManagerTest extends DpmTestBase {
() -> dpm.reboot(admin1));
// Set current call state of device to idle.
- when(getServices().telephonyManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_IDLE);
+ when(getServices().telephonyManager.getCallState())
+ .thenReturn(TelephonyManager.CALL_STATE_IDLE);
dpm.reboot(admin1);
}
+ @Test
public void testSetGetSupportText() {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
dpm.setActiveAdmin(admin1, true);
@@ -2444,11 +2500,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Null default support messages.
{
- assertNull(dpm.getLongSupportMessage(admin1));
- assertNull(dpm.getShortSupportMessage(admin1));
+ assertThat(dpm.getLongSupportMessage(admin1)).isNull();
+ assertThat(dpm.getShortSupportMessage(admin1)).isNull();
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertNull(dpm.getShortSupportMessageForUser(admin1, CALLER_USER_HANDLE));
- assertNull(dpm.getLongSupportMessageForUser(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.getShortSupportMessageForUser(admin1, CALLER_USER_HANDLE)).isNull();
+ assertThat(dpm.getLongSupportMessageForUser(admin1, CALLER_USER_HANDLE)).isNull();
mMockContext.binder.callingUid = DpmMockContext.CALLER_UID;
}
@@ -2473,46 +2529,46 @@ public class DevicePolicyManagerTest extends DpmTestBase {
{
final String supportText = "Some text to test with.";
dpm.setShortSupportMessage(admin1, supportText);
- assertEquals(supportText, dpm.getShortSupportMessage(admin1));
- assertNull(dpm.getLongSupportMessage(admin1));
- assertNull(dpm.getShortSupportMessage(admin2));
+ assertThat(dpm.getShortSupportMessage(admin1)).isEqualTo(supportText);
+ assertThat(dpm.getLongSupportMessage(admin1)).isNull();
+ assertThat(dpm.getShortSupportMessage(admin2)).isNull();
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertEquals(supportText, dpm.getShortSupportMessageForUser(admin1,
- CALLER_USER_HANDLE));
- assertNull(dpm.getShortSupportMessageForUser(admin2, CALLER_USER_HANDLE));
- assertNull(dpm.getLongSupportMessageForUser(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.getShortSupportMessageForUser(admin1,
+ CALLER_USER_HANDLE)).isEqualTo(supportText);
+ assertThat(dpm.getShortSupportMessageForUser(admin2, CALLER_USER_HANDLE)).isNull();
+ assertThat(dpm.getLongSupportMessageForUser(admin1, CALLER_USER_HANDLE)).isNull();
mMockContext.binder.callingUid = DpmMockContext.CALLER_UID;
dpm.setShortSupportMessage(admin1, null);
- assertNull(dpm.getShortSupportMessage(admin1));
+ assertThat(dpm.getShortSupportMessage(admin1)).isNull();
}
// Set/Get long returns what it sets and other admins text isn't changed.
{
final String supportText = "Some text to test with.\nWith more text.";
dpm.setLongSupportMessage(admin1, supportText);
- assertEquals(supportText, dpm.getLongSupportMessage(admin1));
- assertNull(dpm.getShortSupportMessage(admin1));
- assertNull(dpm.getLongSupportMessage(admin2));
+ assertThat(dpm.getLongSupportMessage(admin1)).isEqualTo(supportText);
+ assertThat(dpm.getShortSupportMessage(admin1)).isNull();
+ assertThat(dpm.getLongSupportMessage(admin2)).isNull();
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertEquals(supportText, dpm.getLongSupportMessageForUser(admin1,
- CALLER_USER_HANDLE));
- assertNull(dpm.getLongSupportMessageForUser(admin2, CALLER_USER_HANDLE));
- assertNull(dpm.getShortSupportMessageForUser(admin1, CALLER_USER_HANDLE));
+ assertThat(dpm.getLongSupportMessageForUser(admin1,
+ CALLER_USER_HANDLE)).isEqualTo(supportText);
+ assertThat(dpm.getLongSupportMessageForUser(admin2, CALLER_USER_HANDLE)).isNull();
+ assertThat(dpm.getShortSupportMessageForUser(admin1, CALLER_USER_HANDLE)).isNull();
mMockContext.binder.callingUid = DpmMockContext.CALLER_UID;
dpm.setLongSupportMessage(admin1, null);
- assertNull(dpm.getLongSupportMessage(admin1));
+ assertThat(dpm.getLongSupportMessage(admin1)).isNull();
}
}
+ @Test
public void testSetGetMeteredDataDisabledPackages() throws Exception {
setAsProfileOwner(admin1);
- final ArrayList<String> emptyList = new ArrayList<>();
- assertEquals(emptyList, dpm.getMeteredDataDisabledPackages(admin1));
+ assertThat(dpm.getMeteredDataDisabledPackages(admin1)).isEmpty();
// Setup
final ArrayList<String> pkgsToRestrict = new ArrayList<>();
@@ -2525,8 +2581,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
List<String> excludedPkgs = dpm.setMeteredDataDisabledPackages(admin1, pkgsToRestrict);
// Verify
- assertEquals(emptyList, excludedPkgs);
- assertEquals(pkgsToRestrict, dpm.getMeteredDataDisabledPackages(admin1));
+ assertThat(excludedPkgs).isEmpty();
+ assertThat(dpm.getMeteredDataDisabledPackages(admin1)).isEqualTo(pkgsToRestrict);
verify(getServices().networkPolicyManagerInternal).setMeteredRestrictedPackages(
MockUtils.checkApps(pkgsToRestrict.toArray(new String[0])),
eq(CALLER_USER_HANDLE));
@@ -2536,17 +2592,18 @@ public class DevicePolicyManagerTest extends DpmTestBase {
excludedPkgs = dpm.setMeteredDataDisabledPackages(admin1, pkgsToRestrict);
// Verify
- assertEquals(emptyList, excludedPkgs);
- assertEquals(pkgsToRestrict, dpm.getMeteredDataDisabledPackages(admin1));
+ assertThat(excludedPkgs).isEmpty();
+ assertThat(dpm.getMeteredDataDisabledPackages(admin1)).isEqualTo(pkgsToRestrict);
verify(getServices().networkPolicyManagerInternal).setMeteredRestrictedPackages(
MockUtils.checkApps(pkgsToRestrict.toArray(new String[0])),
eq(CALLER_USER_HANDLE));
}
+ @Test
public void testSetGetMeteredDataDisabledPackages_deviceAdmin() {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
dpm.setActiveAdmin(admin1, true);
- assertTrue(dpm.isAdminActive(admin1));
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
mContext.callerPermissions.remove(permission.MANAGE_DEVICE_ADMINS);
assertExpectException(SecurityException.class, /* messageRegex= */ NOT_PROFILE_OWNER_MSG,
@@ -2555,11 +2612,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
() -> dpm.getMeteredDataDisabledPackages(admin1));
}
+ @Test
public void testIsMeteredDataDisabledForUserPackage() throws Exception {
setAsProfileOwner(admin1);
// Setup
- final ArrayList<String> emptyList = new ArrayList<>();
final ArrayList<String> pkgsToRestrict = new ArrayList<>();
final String package1 = "com.example.one";
final String package2 = "com.example.two";
@@ -2571,16 +2628,20 @@ public class DevicePolicyManagerTest extends DpmTestBase {
List<String> excludedPkgs = dpm.setMeteredDataDisabledPackages(admin1, pkgsToRestrict);
// Verify
- assertEquals(emptyList, excludedPkgs);
+ assertThat(excludedPkgs).isEmpty();
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertTrue(package1 + "should be restricted",
- dpm.isMeteredDataDisabledPackageForUser(admin1, package1, CALLER_USER_HANDLE));
- assertTrue(package2 + "should be restricted",
- dpm.isMeteredDataDisabledPackageForUser(admin1, package2, CALLER_USER_HANDLE));
- assertFalse(package3 + "should not be restricted",
- dpm.isMeteredDataDisabledPackageForUser(admin1, package3, CALLER_USER_HANDLE));
- }
-
+ assertWithMessage("%s should be restricted", package1)
+ .that(dpm.isMeteredDataDisabledPackageForUser(admin1, package1, CALLER_USER_HANDLE))
+ .isTrue();
+ assertWithMessage("%s should be restricted", package2)
+ .that(dpm.isMeteredDataDisabledPackageForUser(admin1, package2, CALLER_USER_HANDLE))
+ .isTrue();
+ assertWithMessage("%s should not be restricted", package3)
+ .that(dpm.isMeteredDataDisabledPackageForUser(admin1, package3, CALLER_USER_HANDLE))
+ .isFalse();
+ }
+
+ @Test
public void testIsMeteredDataDisabledForUserPackage_nonSystemUidCaller() throws Exception {
setAsProfileOwner(admin1);
assertExpectException(SecurityException.class,
@@ -2597,6 +2658,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
clearDeviceOwner();
}
+ @Test
public void testCreateAdminSupportIntent() throws Exception {
// Setup device owner.
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -2604,11 +2666,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Nonexisting permission returns null
Intent intent = dpm.createAdminSupportIntent("disallow_nothing");
- assertNull(intent);
+ assertThat(intent).isNull();
// Existing permission that is not set returns null
intent = dpm.createAdminSupportIntent(UserManager.DISALLOW_ADJUST_VOLUME);
- assertNull(intent);
+ assertThat(intent).isNull();
// Existing permission that is not set by device/profile owner returns null
when(getServices().userManager.hasUserRestriction(
@@ -2616,7 +2678,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
eq(UserHandle.getUserHandleForUid(mContext.binder.callingUid))))
.thenReturn(true);
intent = dpm.createAdminSupportIntent(UserManager.DISALLOW_ADJUST_VOLUME);
- assertNull(intent);
+ assertThat(intent).isNull();
// UM.getUserRestrictionSources() will return a list of size 1 with the caller resource.
doAnswer((Answer<List<UserManager.EnforcingUser>>) invocation -> Collections.singletonList(
@@ -2626,51 +2688,53 @@ public class DevicePolicyManagerTest extends DpmTestBase {
eq(UserManager.DISALLOW_ADJUST_VOLUME),
eq(UserHandle.of(UserHandle.myUserId())));
intent = dpm.createAdminSupportIntent(UserManager.DISALLOW_ADJUST_VOLUME);
- assertNotNull(intent);
- assertEquals(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS, intent.getAction());
- assertEquals(UserHandle.getUserId(DpmMockContext.CALLER_SYSTEM_USER_UID),
- intent.getIntExtra(Intent.EXTRA_USER_ID, -1));
- assertEquals(admin1, intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN));
- assertEquals(UserManager.DISALLOW_ADJUST_VOLUME,
- intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
+ assertThat(intent).isNotNull();
+ assertThat(intent.getAction()).isEqualTo(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS);
+ assertThat(intent.getIntExtra(Intent.EXTRA_USER_ID, -1))
+ .isEqualTo(UserHandle.getUserId(DpmMockContext.CALLER_SYSTEM_USER_UID));
+ assertThat(
+ (ComponentName) intent.getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN))
+ .isEqualTo(admin1);
+ assertThat(intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION))
+ .isEqualTo(UserManager.DISALLOW_ADJUST_VOLUME);
// Try with POLICY_DISABLE_CAMERA and POLICY_DISABLE_SCREEN_CAPTURE, which are not
// user restrictions
// Camera is not disabled
intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_CAMERA);
- assertNull(intent);
+ assertThat(intent).isNull();
// Camera is disabled
dpm.setCameraDisabled(admin1, true);
intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_CAMERA);
- assertNotNull(intent);
- assertEquals(DevicePolicyManager.POLICY_DISABLE_CAMERA,
- intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
+ assertThat(intent).isNotNull();
+ assertThat(intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION))
+ .isEqualTo(DevicePolicyManager.POLICY_DISABLE_CAMERA);
// Screen capture is not disabled
intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
- assertNull(intent);
+ assertThat(intent).isNull();
// Screen capture is disabled
dpm.setScreenCaptureDisabled(admin1, true);
intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
- assertNotNull(intent);
- assertEquals(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE,
- intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
+ assertThat(intent).isNotNull();
+ assertThat(intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION))
+ .isEqualTo(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
// Same checks for different user
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
// Camera should be disabled by device owner
intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_CAMERA);
- assertNotNull(intent);
- assertEquals(DevicePolicyManager.POLICY_DISABLE_CAMERA,
- intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION));
- assertEquals(UserHandle.getUserId(DpmMockContext.CALLER_SYSTEM_USER_UID),
- intent.getIntExtra(Intent.EXTRA_USER_ID, -1));
+ assertThat(intent).isNotNull();
+ assertThat(intent.getStringExtra(DevicePolicyManager.EXTRA_RESTRICTION))
+ .isEqualTo(DevicePolicyManager.POLICY_DISABLE_CAMERA);
+ assertThat(intent.getIntExtra(Intent.EXTRA_USER_ID, -1))
+ .isEqualTo(UserHandle.getUserId(DpmMockContext.CALLER_SYSTEM_USER_UID));
// ScreenCapture should not be disabled by device owner
intent = dpm.createAdminSupportIntent(DevicePolicyManager.POLICY_DISABLE_SCREEN_CAPTURE);
- assertNull(intent);
+ assertThat(intent).isNull();
}
/**
@@ -2679,6 +2743,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
* {@link DevicePolicyManager#getAffiliationIds}
* {@link DevicePolicyManager#isAffiliatedUser}
*/
+ @Test
public void testUserAffiliation() throws Exception {
mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -2686,20 +2751,20 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Check that the system user is unaffiliated.
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
- assertFalse(dpm.isAffiliatedUser());
+ assertThat(dpm.isAffiliatedUser()).isFalse();
// Set a device owner on the system user. Check that the system user becomes affiliated.
setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
dpm.setActiveAdmin(admin1, /* replace =*/ false);
- assertTrue(dpm.setDeviceOwner(admin1, "owner-name"));
- assertTrue(dpm.isAffiliatedUser());
- assertTrue(dpm.getAffiliationIds(admin1).isEmpty());
+ assertThat(dpm.setDeviceOwner(admin1, "owner-name")).isTrue();
+ assertThat(dpm.isAffiliatedUser()).isTrue();
+ assertThat(dpm.getAffiliationIds(admin1).isEmpty()).isTrue();
// Install a profile owner. Check that the test user is unaffiliated.
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
setAsProfileOwner(admin2);
- assertFalse(dpm.isAffiliatedUser());
- assertTrue(dpm.getAffiliationIds(admin2).isEmpty());
+ assertThat(dpm.isAffiliatedUser()).isFalse();
+ assertThat(dpm.getAffiliationIds(admin2).isEmpty()).isTrue();
// Have the profile owner specify a set of affiliation ids. Check that the test user remains
// unaffiliated.
@@ -2709,7 +2774,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
userAffiliationIds.add("blue");
dpm.setAffiliationIds(admin2, userAffiliationIds);
MoreAsserts.assertContentsInAnyOrder(dpm.getAffiliationIds(admin2), "red", "green", "blue");
- assertFalse(dpm.isAffiliatedUser());
+ assertThat(dpm.isAffiliatedUser()).isFalse();
// Have the device owner specify a set of affiliation ids that do not intersect with those
// specified by the profile owner. Check that the test user remains unaffiliated.
@@ -2722,7 +2787,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
MoreAsserts.assertContentsInAnyOrder(
dpm.getAffiliationIds(admin1), "cyan", "yellow", "magenta");
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
- assertFalse(dpm.isAffiliatedUser());
+ assertThat(dpm.isAffiliatedUser()).isFalse();
// Have the profile owner specify a set of affiliation ids that intersect with those
// specified by the device owner. Check that the test user becomes affiliated.
@@ -2730,33 +2795,36 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setAffiliationIds(admin2, userAffiliationIds);
MoreAsserts.assertContentsInAnyOrder(
dpm.getAffiliationIds(admin2), "red", "green", "blue", "yellow");
- assertTrue(dpm.isAffiliatedUser());
+ assertThat(dpm.isAffiliatedUser()).isTrue();
// Clear affiliation ids for the profile owner. The user becomes unaffiliated.
dpm.setAffiliationIds(admin2, Collections.emptySet());
- assertTrue(dpm.getAffiliationIds(admin2).isEmpty());
- assertFalse(dpm.isAffiliatedUser());
+ assertThat(dpm.getAffiliationIds(admin2).isEmpty()).isTrue();
+ assertThat(dpm.isAffiliatedUser()).isFalse();
// Set affiliation ids again, then clear PO to check that the user becomes unaffiliated
dpm.setAffiliationIds(admin2, userAffiliationIds);
- assertTrue(dpm.isAffiliatedUser());
+ assertThat(dpm.isAffiliatedUser()).isTrue();
dpm.clearProfileOwner(admin2);
- assertFalse(dpm.isAffiliatedUser());
+ assertThat(dpm.isAffiliatedUser()).isFalse();
// Check that the system user remains affiliated.
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
- assertTrue(dpm.isAffiliatedUser());
+ assertThat(dpm.isAffiliatedUser()).isTrue();
// Clear the device owner - the user becomes unaffiliated.
clearDeviceOwner();
- assertFalse(dpm.isAffiliatedUser());
+ assertThat(dpm.isAffiliatedUser()).isFalse();
}
+ @Test
public void testGetUserProvisioningState_defaultResult() {
mContext.callerPermissions.add(permission.MANAGE_USERS);
- assertEquals(DevicePolicyManager.STATE_USER_UNMANAGED, dpm.getUserProvisioningState());
+ assertThat(dpm.getUserProvisioningState())
+ .isEqualTo(DevicePolicyManager.STATE_USER_UNMANAGED);
}
+ @Test
public void testSetUserProvisioningState_permission() throws Exception {
setupProfileOwner();
@@ -2764,6 +2832,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
}
+ @Test
public void testSetUserProvisioningState_unprivileged() throws Exception {
setupProfileOwner();
assertExpectException(SecurityException.class, /* messageRegex =*/ null,
@@ -2771,6 +2840,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
CALLER_USER_HANDLE));
}
+ @Test
public void testSetUserProvisioningState_noManagement() {
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
mContext.callerPermissions.add(permission.MANAGE_USERS);
@@ -2778,9 +2848,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
/* messageRegex= */ "change provisioning state unless a .* owner is set",
() -> dpm.setUserProvisioningState(DevicePolicyManager.STATE_USER_SETUP_FINALIZED,
CALLER_USER_HANDLE));
- assertEquals(DevicePolicyManager.STATE_USER_UNMANAGED, dpm.getUserProvisioningState());
+ assertThat(dpm.getUserProvisioningState())
+ .isEqualTo(DevicePolicyManager.STATE_USER_UNMANAGED);
}
+ @Test
public void testSetUserProvisioningState_deviceOwnerFromSetupWizard() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -2790,6 +2862,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
}
+ @Test
public void testSetUserProvisioningState_deviceOwnerFromSetupWizardAlternative()
throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -2800,6 +2873,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
}
+ @Test
public void testSetUserProvisioningState_deviceOwnerWithoutSetupWizard() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -2808,6 +2882,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
}
+ @Test
public void testSetUserProvisioningState_managedProfileFromSetupWizard_primaryUser()
throws Exception {
setupProfileOwner();
@@ -2817,6 +2892,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DevicePolicyManager.STATE_USER_PROFILE_FINALIZED);
}
+ @Test
public void testSetUserProvisioningState_managedProfileFromSetupWizard_managedProfile()
throws Exception {
setupProfileOwner();
@@ -2826,6 +2902,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
}
+ @Test
public void testSetUserProvisioningState_managedProfileWithoutSetupWizard() throws Exception {
setupProfileOwner();
@@ -2833,6 +2910,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DevicePolicyManager.STATE_USER_SETUP_FINALIZED);
}
+ @Test
public void testSetUserProvisioningState_illegalTransitionOutOfFinalized1() throws Exception {
setupProfileOwner();
@@ -2843,6 +2921,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DevicePolicyManager.STATE_USER_UNMANAGED));
}
+ @Test
public void testSetUserProvisioningState_illegalTransitionToAnotherInProgressState()
throws Exception {
setupProfileOwner();
@@ -2858,10 +2937,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
mContext.callerPermissions.add(permission.MANAGE_USERS);
- assertEquals(DevicePolicyManager.STATE_USER_UNMANAGED, dpm.getUserProvisioningState());
+ assertThat(dpm.getUserProvisioningState())
+ .isEqualTo(DevicePolicyManager.STATE_USER_UNMANAGED);
for (int state : states) {
dpm.setUserProvisioningState(state, userId);
- assertEquals(state, dpm.getUserProvisioningState());
+ assertThat(dpm.getUserProvisioningState()).isEqualTo(state);
}
}
@@ -2870,7 +2950,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_UID);
dpm.setActiveAdmin(admin1, false);
- assertTrue(dpm.setProfileOwner(admin1, null, CALLER_USER_HANDLE));
+ assertThat(dpm.setProfileOwner(admin1, null, CALLER_USER_HANDLE)).isTrue();
mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
}
@@ -2880,7 +2960,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setUpPackageManagerForAdmin(admin1, DpmMockContext.SYSTEM_UID);
dpm.setActiveAdmin(admin1, false);
- assertTrue(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM));
+ assertThat(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM)).isTrue();
mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
}
@@ -2890,11 +2970,12 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
dpm.setActiveAdmin(admin1, false);
- assertTrue(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM));
+ assertThat(dpm.setDeviceOwner(admin1, null, UserHandle.USER_SYSTEM)).isTrue();
mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
}
+ @Test
public void testSetMaximumTimeToLock() {
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
@@ -2956,6 +3037,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verifyStayOnWhilePluggedCleared(false);
}
+ @Test
public void testIsActiveSupervisionApp() throws Exception {
when(mServiceContext.resources
.getString(R.string.config_defaultSupervisionProfileOwnerComponent))
@@ -2968,11 +3050,12 @@ public class DevicePolicyManagerTest extends DpmTestBase {
final DevicePolicyManagerInternal dpmi =
LocalServices.getService(DevicePolicyManagerInternal.class);
- assertTrue(dpmi.isActiveSupervisionApp(PROFILE_ADMIN));
+ assertThat(dpmi.isActiveSupervisionApp(PROFILE_ADMIN)).isTrue();
}
// Test if lock timeout on managed profile is handled correctly depending on whether profile
// uses separate challenge.
+ @Test
public void testSetMaximumTimeToLockProfile() throws Exception {
final int PROFILE_USER = 15;
final int PROFILE_ADMIN = UserHandle.getUid(PROFILE_USER, 19436);
@@ -3039,6 +3122,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verifyScreenTimeoutCall(Long.MAX_VALUE, UserHandle.USER_SYSTEM);
}
+ @Test
public void testSetRequiredStrongAuthTimeout_DeviceOwner() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -3055,8 +3139,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
getServices().buildMock.isDebuggable = false;
dpm.setRequiredStrongAuthTimeout(admin1, MAX_MINUS_ONE_MINUTE);
- assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), MAX_MINUS_ONE_MINUTE);
- assertEquals(dpm.getRequiredStrongAuthTimeout(null), MAX_MINUS_ONE_MINUTE);
+ assertThat(MAX_MINUS_ONE_MINUTE).isEqualTo(dpm.getRequiredStrongAuthTimeout(admin1));
+ assertThat(MAX_MINUS_ONE_MINUTE).isEqualTo(dpm.getRequiredStrongAuthTimeout(null));
verify(getServices().systemProperties, never()).getLong(anyString(), anyLong());
@@ -3067,45 +3151,47 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setRequiredStrongAuthTimeout(admin1, 0);
// aggregation should be the default if unset by any admin
- assertEquals(dpm.getRequiredStrongAuthTimeout(null),
- DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+ assertThat(DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS)
+ .isEqualTo(dpm.getRequiredStrongAuthTimeout(null));
// admin not participating by default
- assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), 0);
+ assertThat(dpm.getRequiredStrongAuthTimeout(admin1)).isEqualTo(0);
//clamping from the top
dpm.setRequiredStrongAuthTimeout(admin1,
DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS + ONE_MINUTE);
- assertEquals(dpm.getRequiredStrongAuthTimeout(admin1),
- DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
- assertEquals(dpm.getRequiredStrongAuthTimeout(null),
- DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+ assertThat(DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS)
+ .isEqualTo(dpm.getRequiredStrongAuthTimeout(admin1));
+ assertThat(DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS)
+ .isEqualTo(dpm.getRequiredStrongAuthTimeout(null));
// 0 means the admin is not participating, so default should be returned
dpm.setRequiredStrongAuthTimeout(admin1, 0);
- assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), 0);
- assertEquals(dpm.getRequiredStrongAuthTimeout(null),
- DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+ assertThat(dpm.getRequiredStrongAuthTimeout(admin1)).isEqualTo(0);
+ assertThat(DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS)
+ .isEqualTo(dpm.getRequiredStrongAuthTimeout(null));
// clamping from the bottom
dpm.setRequiredStrongAuthTimeout(admin1, MINIMUM_STRONG_AUTH_TIMEOUT_MS - ONE_MINUTE);
- assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), MINIMUM_STRONG_AUTH_TIMEOUT_MS);
- assertEquals(dpm.getRequiredStrongAuthTimeout(null), MINIMUM_STRONG_AUTH_TIMEOUT_MS);
+ assertThat(dpm.getRequiredStrongAuthTimeout(admin1))
+ .isEqualTo(MINIMUM_STRONG_AUTH_TIMEOUT_MS);
+ assertThat(dpm.getRequiredStrongAuthTimeout(null))
+ .isEqualTo(MINIMUM_STRONG_AUTH_TIMEOUT_MS);
// values within range
dpm.setRequiredStrongAuthTimeout(admin1, MIN_PLUS_ONE_MINUTE);
- assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), MIN_PLUS_ONE_MINUTE);
- assertEquals(dpm.getRequiredStrongAuthTimeout(null), MIN_PLUS_ONE_MINUTE);
+ assertThat(dpm.getRequiredStrongAuthTimeout(admin1)).isEqualTo(MIN_PLUS_ONE_MINUTE);
+ assertThat(dpm.getRequiredStrongAuthTimeout(null)).isEqualTo(MIN_PLUS_ONE_MINUTE);
dpm.setRequiredStrongAuthTimeout(admin1, MAX_MINUS_ONE_MINUTE);
- assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), MAX_MINUS_ONE_MINUTE);
- assertEquals(dpm.getRequiredStrongAuthTimeout(null), MAX_MINUS_ONE_MINUTE);
+ assertThat(dpm.getRequiredStrongAuthTimeout(admin1)).isEqualTo(MAX_MINUS_ONE_MINUTE);
+ assertThat(dpm.getRequiredStrongAuthTimeout(null)).isEqualTo(MAX_MINUS_ONE_MINUTE);
// reset to default
dpm.setRequiredStrongAuthTimeout(admin1, 0);
- assertEquals(dpm.getRequiredStrongAuthTimeout(admin1), 0);
- assertEquals(dpm.getRequiredStrongAuthTimeout(null),
- DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS);
+ assertThat(dpm.getRequiredStrongAuthTimeout(admin1)).isEqualTo(0);
+ assertThat(DevicePolicyManager.DEFAULT_STRONG_AUTH_TIMEOUT_MS)
+ .isEqualTo(dpm.getRequiredStrongAuthTimeout(null));
// negative value
assertExpectException(IllegalArgumentException.class, /* messageRegex= */ null,
@@ -3130,8 +3216,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
private void setup_DeviceAdminFeatureOff() throws Exception {
when(getServices().packageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN))
.thenReturn(false);
- when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
- .thenReturn(false);
+ when(getServices().ipackageManager
+ .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(false);
initializeDpms();
when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(false);
when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM, true))
@@ -3141,6 +3227,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
}
+ @Test
public void testIsProvisioningAllowed_DeviceAdminFeatureOff() throws Exception {
setup_DeviceAdminFeatureOff();
mContext.packageName = admin1.getPackageName();
@@ -3153,6 +3240,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, false);
}
+ @Test
public void testCheckProvisioningPreCondition_DeviceAdminFeatureOff() throws Exception {
setup_DeviceAdminFeatureOff();
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -3170,8 +3258,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
private void setup_ManagedProfileFeatureOff() throws Exception {
- when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
- .thenReturn(false);
+ when(getServices().ipackageManager
+ .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(false);
initializeDpms();
when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(false);
when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM, true))
@@ -3181,6 +3269,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
}
+ @Test
public void testIsProvisioningAllowed_ManagedProfileFeatureOff() throws Exception {
setup_ManagedProfileFeatureOff();
mContext.packageName = admin1.getPackageName();
@@ -3202,6 +3291,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, false);
}
+ @Test
public void testCheckProvisioningPreCondition_ManagedProfileFeatureOff() throws Exception {
setup_ManagedProfileFeatureOff();
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -3233,8 +3323,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
private void setup_nonSplitUser_firstBoot_primaryUser() throws Exception {
- when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
- .thenReturn(true);
+ when(getServices().ipackageManager
+ .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(false);
when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM, true))
.thenReturn(true);
@@ -3244,6 +3334,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
}
+ @Test
public void testIsProvisioningAllowed_nonSplitUser_firstBoot_primaryUser() throws Exception {
setup_nonSplitUser_firstBoot_primaryUser();
mContext.packageName = admin1.getPackageName();
@@ -3257,6 +3348,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
false /* because of non-split user */);
}
+ @Test
public void testCheckProvisioningPreCondition_nonSplitUser_firstBoot_primaryUser()
throws Exception {
setup_nonSplitUser_firstBoot_primaryUser();
@@ -3275,8 +3367,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
private void setup_nonSplitUser_afterDeviceSetup_primaryUser() throws Exception {
- when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
- .thenReturn(true);
+ when(getServices().ipackageManager
+ .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(false);
when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM, true))
.thenReturn(true);
@@ -3302,6 +3394,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
true)).thenReturn(true);
}
+ @Test
public void testIsProvisioningAllowed_nonSplitUser_afterDeviceSetup_primaryUser()
throws Exception {
setup_nonSplitUser_afterDeviceSetup_primaryUser();
@@ -3318,6 +3411,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
false/* because of non-split user */);
}
+ @Test
public void testCheckProvisioningPreCondition_nonSplitUser_afterDeviceSetup_primaryUser()
throws Exception {
setup_nonSplitUser_afterDeviceSetup_primaryUser();
@@ -3335,6 +3429,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DevicePolicyManager.CODE_NOT_SYSTEM_USER_SPLIT);
}
+ @Test
public void testProvisioning_nonSplitUser_withDo_primaryUser() throws Exception {
setup_nonSplitUser_withDo_primaryUser();
mContext.packageName = admin1.getPackageName();
@@ -3361,6 +3456,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DpmMockContext.ANOTHER_PACKAGE_NAME, DpmMockContext.ANOTHER_UID);
}
+ @Test
public void testProvisioning_nonSplitUser_withDo_primaryUser_restrictedBySystem()
throws Exception {
setup_nonSplitUser_withDo_primaryUser();
@@ -3388,6 +3484,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DpmMockContext.ANOTHER_PACKAGE_NAME, DpmMockContext.ANOTHER_UID);
}
+ @Test
public void testCheckCannotSetProfileOwnerWithDeviceOwner() throws Exception {
setup_nonSplitUser_withDo_primaryUser();
final int managedProfileUserId = 18;
@@ -3399,10 +3496,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.callerPermissions.addAll(OWNER_SETUP_PERMISSIONS);
setUpPackageManagerForFakeAdmin(admin1, managedProfileAdminUid, admin1);
dpm.setActiveAdmin(admin1, false, userId);
- assertFalse(dpm.setProfileOwner(admin1, null, userId));
+ assertThat(dpm.setProfileOwner(admin1, null, userId)).isFalse();
mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
}
+ @Test
public void testCheckProvisioningPreCondition_nonSplitUser_attemptingComp() throws Exception {
setup_nonSplitUser_withDo_primaryUser_ManagedProfile();
mContext.packageName = admin1.getPackageName();
@@ -3420,6 +3518,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DpmMockContext.ANOTHER_PACKAGE_NAME, DpmMockContext.ANOTHER_UID);
}
+ @Test
public void testCheckProvisioningPreCondition_nonSplitUser_comp_cannot_remove_profile()
throws Exception {
setup_nonSplitUser_withDo_primaryUser_ManagedProfile();
@@ -3449,8 +3548,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
private void setup_splitUser_firstBoot_systemUser() throws Exception {
- when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
- .thenReturn(true);
+ when(getServices().ipackageManager
+ .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM, true))
.thenReturn(false);
@@ -3459,6 +3558,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
}
+ @Test
public void testIsProvisioningAllowed_splitUser_firstBoot_systemUser() throws Exception {
setup_splitUser_firstBoot_systemUser();
mContext.packageName = admin1.getPackageName();
@@ -3473,6 +3573,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
false/* because calling uid is system user */);
}
+ @Test
public void testCheckProvisioningPreCondition_splitUser_firstBoot_systemUser()
throws Exception {
setup_splitUser_firstBoot_systemUser();
@@ -3491,8 +3592,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
private void setup_splitUser_afterDeviceSetup_systemUser() throws Exception {
- when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
- .thenReturn(true);
+ when(getServices().ipackageManager
+ .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM, true))
.thenReturn(false);
@@ -3501,6 +3602,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
}
+ @Test
public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_systemUser() throws Exception {
setup_splitUser_afterDeviceSetup_systemUser();
mContext.packageName = admin1.getPackageName();
@@ -3517,6 +3619,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
false/* because calling uid is system user */);
}
+ @Test
public void testCheckProvisioningPreCondition_splitUser_afterDeviceSetup_systemUser()
throws Exception {
setup_splitUser_afterDeviceSetup_systemUser();
@@ -3535,8 +3638,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
private void setup_splitUser_firstBoot_primaryUser() throws Exception {
- when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
- .thenReturn(true);
+ when(getServices().ipackageManager
+ .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
when(getServices().userManager.canAddMoreManagedProfiles(CALLER_USER_HANDLE,
true)).thenReturn(true);
@@ -3545,6 +3648,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
}
+ @Test
public void testIsProvisioningAllowed_splitUser_firstBoot_primaryUser() throws Exception {
setup_splitUser_firstBoot_primaryUser();
mContext.packageName = admin1.getPackageName();
@@ -3557,6 +3661,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_USER, true);
}
+ @Test
public void testCheckProvisioningPreCondition_splitUser_firstBoot_primaryUser()
throws Exception {
setup_splitUser_firstBoot_primaryUser();
@@ -3575,8 +3680,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
private void setup_splitUser_afterDeviceSetup_primaryUser() throws Exception {
- when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
- .thenReturn(true);
+ when(getServices().ipackageManager
+ .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
when(getServices().userManager.canAddMoreManagedProfiles(CALLER_USER_HANDLE,
true)).thenReturn(true);
@@ -3585,6 +3690,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
}
+ @Test
public void testIsProvisioningAllowed_splitUser_afterDeviceSetup_primaryUser()
throws Exception {
setup_splitUser_afterDeviceSetup_primaryUser();
@@ -3601,6 +3707,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
false/* because user setup completed */);
}
+ @Test
public void testCheckProvisioningPreCondition_splitUser_afterDeviceSetup_primaryUser()
throws Exception {
setup_splitUser_afterDeviceSetup_primaryUser();
@@ -3621,8 +3728,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
private void setup_provisionManagedProfileWithDeviceOwner_systemUser() throws Exception {
setDeviceOwner();
- when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
- .thenReturn(true);
+ when(getServices().ipackageManager
+ .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
when(getServices().userManager.canAddMoreManagedProfiles(UserHandle.USER_SYSTEM, true))
.thenReturn(false);
@@ -3631,6 +3738,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
}
+ @Test
public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_systemUser()
throws Exception {
setup_provisionManagedProfileWithDeviceOwner_systemUser();
@@ -3640,6 +3748,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
false /* can't provision managed profile on system user */);
}
+ @Test
public void testCheckProvisioningPreCondition_provisionManagedProfileWithDeviceOwner_systemUser()
throws Exception {
setup_provisionManagedProfileWithDeviceOwner_systemUser();
@@ -3651,8 +3760,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
private void setup_provisionManagedProfileWithDeviceOwner_primaryUser() throws Exception {
setDeviceOwner();
- when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
- .thenReturn(true);
+ when(getServices().ipackageManager
+ .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(false);
when(getServices().userManager.getProfileParent(CALLER_USER_HANDLE))
.thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "user system", 0));
@@ -3663,6 +3772,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.ANOTHER_UID;
}
+ @Test
public void testIsProvisioningAllowed_provisionManagedProfileWithDeviceOwner_primaryUser()
throws Exception {
setup_provisionManagedProfileWithDeviceOwner_primaryUser();
@@ -3671,6 +3781,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
}
+ @Test
public void testCheckProvisioningPreCondition_provisionManagedProfileWithDeviceOwner_primaryUser()
throws Exception {
setup_provisionManagedProfileWithDeviceOwner_primaryUser();
@@ -3684,8 +3795,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
private void setup_provisionManagedProfileCantRemoveUser_primaryUser() throws Exception {
setDeviceOwner();
- when(getServices().ipackageManager.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0))
- .thenReturn(true);
+ when(getServices().ipackageManager
+ .hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS, 0)).thenReturn(true);
when(getServices().userManagerForMock.isSplitSystemUser()).thenReturn(true);
when(getServices().userManager.hasUserRestriction(
eq(UserManager.DISALLOW_REMOVE_MANAGED_PROFILE),
@@ -3700,6 +3811,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
}
+ @Test
public void testIsProvisioningAllowed_provisionManagedProfileCantRemoveUser_primaryUser()
throws Exception {
setup_provisionManagedProfileCantRemoveUser_primaryUser();
@@ -3708,6 +3820,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertProvisioningAllowed(DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, false);
}
+ @Test
public void testCheckProvisioningPreCondition_provisionManagedProfileCantRemoveUser_primaryUser()
throws Exception {
setup_provisionManagedProfileCantRemoveUser_primaryUser();
@@ -3716,6 +3829,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DevicePolicyManager.CODE_CANNOT_ADD_MANAGED_PROFILE);
}
+ @Test
public void testCheckProvisioningPreCondition_permission() {
// GIVEN the permission MANAGE_PROFILE_AND_DEVICE_OWNERS is not granted
assertExpectException(SecurityException.class, /* messageRegex =*/ null,
@@ -3723,12 +3837,14 @@ public class DevicePolicyManagerTest extends DpmTestBase {
DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE, "some.package"));
}
+ @Test
public void testForceUpdateUserSetupComplete_permission() {
// GIVEN the permission MANAGE_PROFILE_AND_DEVICE_OWNERS is not granted
assertExpectException(SecurityException.class, /* messageRegex =*/ null,
() -> dpm.forceUpdateUserSetupComplete());
}
+ @Test
public void testForceUpdateUserSetupComplete_systemUser() {
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
// GIVEN calling from user 20
@@ -3737,6 +3853,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
() -> dpm.forceUpdateUserSetupComplete());
}
+ @Test
public void testForceUpdateUserSetupComplete_userbuild() {
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -3753,14 +3870,15 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// GIVEN it's user build
getServices().buildMock.isDebuggable = false;
- assertTrue(dpms.hasUserSetupCompleted());
+ assertThat(dpms.hasUserSetupCompleted()).isTrue();
dpm.forceUpdateUserSetupComplete();
// THEN the state in dpms is not changed
- assertTrue(dpms.hasUserSetupCompleted());
+ assertThat(dpms.hasUserSetupCompleted()).isTrue();
}
+ @Test
public void testForceUpdateUserSetupComplete_userDebugbuild() {
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -3777,12 +3895,12 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// GIVEN it's userdebug build
getServices().buildMock.isDebuggable = true;
- assertTrue(dpms.hasUserSetupCompleted());
+ assertThat(dpms.hasUserSetupCompleted()).isTrue();
dpm.forceUpdateUserSetupComplete();
// THEN the state in dpms is not changed
- assertFalse(dpms.hasUserSetupCompleted());
+ assertThat(dpms.hasUserSetupCompleted()).isFalse();
}
private void clearDeviceOwner() throws Exception {
@@ -3795,6 +3913,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
});
}
+ @Test
public void testGetLastSecurityLogRetrievalTime() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -3806,7 +3925,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.thenReturn(true);
// No logs were retrieved so far.
- assertEquals(-1, dpm.getLastSecurityLogRetrievalTime());
+ assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(-1);
// Enabling logging should not change the timestamp.
dpm.setSecurityLoggingEnabled(admin1, true);
@@ -3814,55 +3933,56 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.securityLogSetLoggingEnabledProperty(true);
when(getServices().settings.securityLogGetLoggingEnabledProperty())
.thenReturn(true);
- assertEquals(-1, dpm.getLastSecurityLogRetrievalTime());
+ assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(-1);
// Retrieving the logs should update the timestamp.
final long beforeRetrieval = System.currentTimeMillis();
dpm.retrieveSecurityLogs(admin1);
final long firstSecurityLogRetrievalTime = dpm.getLastSecurityLogRetrievalTime();
final long afterRetrieval = System.currentTimeMillis();
- assertTrue(firstSecurityLogRetrievalTime >= beforeRetrieval);
- assertTrue(firstSecurityLogRetrievalTime <= afterRetrieval);
+ assertThat(firstSecurityLogRetrievalTime >= beforeRetrieval).isTrue();
+ assertThat(firstSecurityLogRetrievalTime <= afterRetrieval).isTrue();
// Retrieving the pre-boot logs should update the timestamp.
Thread.sleep(2);
dpm.retrievePreRebootSecurityLogs(admin1);
final long secondSecurityLogRetrievalTime = dpm.getLastSecurityLogRetrievalTime();
- assertTrue(secondSecurityLogRetrievalTime > firstSecurityLogRetrievalTime);
+ assertThat(secondSecurityLogRetrievalTime > firstSecurityLogRetrievalTime).isTrue();
// Checking the timestamp again should not change it.
Thread.sleep(2);
- assertEquals(secondSecurityLogRetrievalTime, dpm.getLastSecurityLogRetrievalTime());
+ assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(secondSecurityLogRetrievalTime);
// Retrieving the logs again should update the timestamp.
dpm.retrieveSecurityLogs(admin1);
final long thirdSecurityLogRetrievalTime = dpm.getLastSecurityLogRetrievalTime();
- assertTrue(thirdSecurityLogRetrievalTime > secondSecurityLogRetrievalTime);
+ assertThat(thirdSecurityLogRetrievalTime > secondSecurityLogRetrievalTime).isTrue();
// Disabling logging should not change the timestamp.
Thread.sleep(2);
dpm.setSecurityLoggingEnabled(admin1, false);
- assertEquals(thirdSecurityLogRetrievalTime, dpm.getLastSecurityLogRetrievalTime());
+ assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(thirdSecurityLogRetrievalTime);
// Restarting the DPMS should not lose the timestamp.
initializeDpms();
- assertEquals(thirdSecurityLogRetrievalTime, dpm.getLastSecurityLogRetrievalTime());
+ assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(thirdSecurityLogRetrievalTime);
// Any uid holding MANAGE_USERS permission can retrieve the timestamp.
mContext.binder.callingUid = 1234567;
mContext.callerPermissions.add(permission.MANAGE_USERS);
- assertEquals(thirdSecurityLogRetrievalTime, dpm.getLastSecurityLogRetrievalTime());
+ assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(thirdSecurityLogRetrievalTime);
mContext.callerPermissions.remove(permission.MANAGE_USERS);
// System can retrieve the timestamp.
mContext.binder.clearCallingIdentity();
- assertEquals(thirdSecurityLogRetrievalTime, dpm.getLastSecurityLogRetrievalTime());
+ assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(thirdSecurityLogRetrievalTime);
// Removing the device owner should clear the timestamp.
clearDeviceOwner();
- assertEquals(-1, dpm.getLastSecurityLogRetrievalTime());
+ assertThat(dpm.getLastSecurityLogRetrievalTime()).isEqualTo(-1);
}
+ @Test
public void testSetConfiguredNetworksLockdownStateWithDO() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -3875,6 +3995,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0);
}
+ @Test
public void testSetConfiguredNetworksLockdownStateWithPO() throws Exception {
setupProfileOwner();
assertExpectException(SecurityException.class, null,
@@ -3883,6 +4004,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0);
}
+ @Test
public void testSetConfiguredNetworksLockdownStateWithPOOfOrganizationOwnedDevice()
throws Exception {
setupProfileOwner();
@@ -3896,6 +4018,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
Settings.Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0);
}
+ @Test
public void testSetSystemSettingFailWithNonWhitelistedSettings() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -3903,6 +4026,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setSystemSetting(admin1, Settings.System.SCREEN_BRIGHTNESS_FOR_VR, "0"));
}
+ @Test
public void testSetSystemSettingWithDO() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -3911,6 +4035,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
Settings.System.SCREEN_BRIGHTNESS, "0", UserHandle.USER_SYSTEM);
}
+ @Test
public void testSetSystemSettingWithPO() throws Exception {
setupProfileOwner();
dpm.setSystemSetting(admin1, Settings.System.SCREEN_BRIGHTNESS, "0");
@@ -3918,6 +4043,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
Settings.System.SCREEN_BRIGHTNESS, "0", CALLER_USER_HANDLE);
}
+ @Test
public void testSetAutoTimeEnabledModifiesSetting() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -3928,6 +4054,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
}
+ @Test
public void testSetAutoTimeEnabledWithPOOnUser0() throws Exception {
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
setupProfileOwnerOnUser0();
@@ -3938,6 +4065,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
}
+ @Test
public void testSetAutoTimeEnabledFailWithPONotOnUser0() throws Exception {
setupProfileOwner();
assertExpectException(SecurityException.class, null,
@@ -3945,6 +4073,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().settings, never()).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
}
+ @Test
public void testSetAutoTimeEnabledWithPOOfOrganizationOwnedDevice() throws Exception {
setupProfileOwner();
configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
@@ -3956,6 +4085,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
}
+ @Test
public void testSetAutoTimeZoneEnabledModifiesSetting() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -3966,6 +4096,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 0);
}
+ @Test
public void testSetAutoTimeZoneEnabledWithPOOnUser0() throws Exception {
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
setupProfileOwnerOnUser0();
@@ -3976,6 +4107,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 0);
}
+ @Test
public void testSetAutoTimeZoneEnabledFailWithPONotOnUser0() throws Exception {
setupProfileOwner();
assertExpectException(SecurityException.class, null,
@@ -3984,6 +4116,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
0);
}
+ @Test
public void testSetAutoTimeZoneEnabledWithPOOfOrganizationOwnedDevice() throws Exception {
setupProfileOwner();
configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
@@ -3995,12 +4128,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME_ZONE, 0);
}
+ @Test
public void testIsOrganizationOwnedDevice() throws Exception {
// Set up the user manager to return correct user info
addManagedProfile(admin1, DpmMockContext.CALLER_UID, admin1);
// Any caller should be able to call this method.
- assertFalse(dpm.isOrganizationOwnedDeviceWithManagedProfile());
+ assertThat(dpm.isOrganizationOwnedDeviceWithManagedProfile()).isFalse();
configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
verify(getServices().userManager).setUserRestriction(
@@ -4008,13 +4142,14 @@ public class DevicePolicyManagerTest extends DpmTestBase {
eq(true),
eq(UserHandle.of(UserHandle.USER_SYSTEM)));
- assertTrue(dpm.isOrganizationOwnedDeviceWithManagedProfile());
+ assertThat(dpm.isOrganizationOwnedDeviceWithManagedProfile()).isTrue();
// A random caller from another user should also be able to get the right result.
mContext.binder.callingUid = DpmMockContext.ANOTHER_UID;
- assertTrue(dpm.isOrganizationOwnedDeviceWithManagedProfile());
+ assertThat(dpm.isOrganizationOwnedDeviceWithManagedProfile()).isTrue();
}
+ @Test
public void testMarkOrganizationOwnedDevice_baseRestrictionsAdded() throws Exception {
addManagedProfile(admin1, DpmMockContext.CALLER_UID, admin1);
@@ -4044,6 +4179,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
parentDpm.clearUserRestriction(admin1, UserManager.DISALLOW_ADD_USER));
}
+ @Test
public void testSetTime() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -4051,11 +4187,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().alarmManager).setTime(0);
}
+ @Test
public void testSetTimeFailWithPO() throws Exception {
setupProfileOwner();
assertExpectException(SecurityException.class, null, () -> dpm.setTime(admin1, 0));
}
+ @Test
public void testSetTimeWithPOOfOrganizationOwnedDevice() throws Exception {
setupProfileOwner();
configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
@@ -4063,14 +4201,16 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().alarmManager).setTime(0);
}
+ @Test
public void testSetTimeWithAutoTimeOn() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
when(getServices().settings.settingsGlobalGetInt(Settings.Global.AUTO_TIME, 0))
.thenReturn(1);
- assertFalse(dpm.setTime(admin1, 0));
+ assertThat(dpm.setTime(admin1, 0)).isFalse();
}
+ @Test
public void testSetTimeZone() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -4078,12 +4218,14 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().alarmManager).setTimeZone("Asia/Shanghai");
}
+ @Test
public void testSetTimeZoneFailWithPO() throws Exception {
setupProfileOwner();
assertExpectException(SecurityException.class, null,
() -> dpm.setTimeZone(admin1, "Asia/Shanghai"));
}
+ @Test
public void testSetTimeZoneWithPOOfOrganizationOwnedDevice() throws Exception {
setupProfileOwner();
configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
@@ -4091,14 +4233,16 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().alarmManager).setTimeZone("Asia/Shanghai");
}
+ @Test
public void testSetTimeZoneWithAutoTimeZoneOn() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
when(getServices().settings.settingsGlobalGetInt(Settings.Global.AUTO_TIME_ZONE, 0))
.thenReturn(1);
- assertFalse(dpm.setTimeZone(admin1, "Asia/Shanghai"));
+ assertThat(dpm.setTimeZone(admin1, "Asia/Shanghai")).isFalse();
}
+ @Test
public void testGetLastBugReportRequestTime() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -4115,39 +4259,40 @@ public class DevicePolicyManagerTest extends DpmTestBase {
getServices().removeUser(CALLER_USER_HANDLE);
// No bug reports were requested so far.
- assertEquals(-1, dpm.getLastBugReportRequestTime());
+ assertThat(dpm.getLastBugReportRequestTime()).isEqualTo(-1);
// Requesting a bug report should update the timestamp.
final long beforeRequest = System.currentTimeMillis();
dpm.requestBugreport(admin1);
final long bugReportRequestTime = dpm.getLastBugReportRequestTime();
final long afterRequest = System.currentTimeMillis();
- assertTrue(bugReportRequestTime >= beforeRequest);
- assertTrue(bugReportRequestTime <= afterRequest);
+ assertThat(bugReportRequestTime).isAtLeast(beforeRequest);
+ assertThat(bugReportRequestTime).isAtMost(afterRequest);
// Checking the timestamp again should not change it.
Thread.sleep(2);
- assertEquals(bugReportRequestTime, dpm.getLastBugReportRequestTime());
+ assertThat(dpm.getLastBugReportRequestTime()).isEqualTo(bugReportRequestTime);
// Restarting the DPMS should not lose the timestamp.
initializeDpms();
- assertEquals(bugReportRequestTime, dpm.getLastBugReportRequestTime());
+ assertThat(dpm.getLastBugReportRequestTime()).isEqualTo(bugReportRequestTime);
// Any uid holding MANAGE_USERS permission can retrieve the timestamp.
mContext.binder.callingUid = 1234567;
mContext.callerPermissions.add(permission.MANAGE_USERS);
- assertEquals(bugReportRequestTime, dpm.getLastBugReportRequestTime());
+ assertThat(dpm.getLastBugReportRequestTime()).isEqualTo(bugReportRequestTime);
mContext.callerPermissions.remove(permission.MANAGE_USERS);
// System can retrieve the timestamp.
mContext.binder.clearCallingIdentity();
- assertEquals(bugReportRequestTime, dpm.getLastBugReportRequestTime());
+ assertThat(dpm.getLastBugReportRequestTime()).isEqualTo(bugReportRequestTime);
// Removing the device owner should clear the timestamp.
clearDeviceOwner();
- assertEquals(-1, dpm.getLastBugReportRequestTime());
+ assertThat(dpm.getLastBugReportRequestTime()).isEqualTo(-1);
}
+ @Test
public void testGetLastNetworkLogRetrievalTime() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -4165,57 +4310,58 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.thenReturn(true);
// No logs were retrieved so far.
- assertEquals(-1, dpm.getLastNetworkLogRetrievalTime());
+ assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1);
// Attempting to retrieve logs without enabling logging should not change the timestamp.
dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */);
- assertEquals(-1, dpm.getLastNetworkLogRetrievalTime());
+ assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1);
// Enabling logging should not change the timestamp.
dpm.setNetworkLoggingEnabled(admin1, true);
- assertEquals(-1, dpm.getLastNetworkLogRetrievalTime());
+ assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1);
// Retrieving the logs should update the timestamp.
final long beforeRetrieval = System.currentTimeMillis();
dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */);
final long firstNetworkLogRetrievalTime = dpm.getLastNetworkLogRetrievalTime();
final long afterRetrieval = System.currentTimeMillis();
- assertTrue(firstNetworkLogRetrievalTime >= beforeRetrieval);
- assertTrue(firstNetworkLogRetrievalTime <= afterRetrieval);
+ assertThat(firstNetworkLogRetrievalTime >= beforeRetrieval).isTrue();
+ assertThat(firstNetworkLogRetrievalTime <= afterRetrieval).isTrue();
// Checking the timestamp again should not change it.
Thread.sleep(2);
- assertEquals(firstNetworkLogRetrievalTime, dpm.getLastNetworkLogRetrievalTime());
+ assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(firstNetworkLogRetrievalTime);
// Retrieving the logs again should update the timestamp.
dpm.retrieveNetworkLogs(admin1, 0 /* batchToken */);
final long secondNetworkLogRetrievalTime = dpm.getLastNetworkLogRetrievalTime();
- assertTrue(secondNetworkLogRetrievalTime > firstNetworkLogRetrievalTime);
+ assertThat(secondNetworkLogRetrievalTime > firstNetworkLogRetrievalTime).isTrue();
// Disabling logging should not change the timestamp.
Thread.sleep(2);
dpm.setNetworkLoggingEnabled(admin1, false);
- assertEquals(secondNetworkLogRetrievalTime, dpm.getLastNetworkLogRetrievalTime());
+ assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(secondNetworkLogRetrievalTime);
// Restarting the DPMS should not lose the timestamp.
initializeDpms();
- assertEquals(secondNetworkLogRetrievalTime, dpm.getLastNetworkLogRetrievalTime());
+ assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(secondNetworkLogRetrievalTime);
// Any uid holding MANAGE_USERS permission can retrieve the timestamp.
mContext.binder.callingUid = 1234567;
mContext.callerPermissions.add(permission.MANAGE_USERS);
- assertEquals(secondNetworkLogRetrievalTime, dpm.getLastNetworkLogRetrievalTime());
+ assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(secondNetworkLogRetrievalTime);
mContext.callerPermissions.remove(permission.MANAGE_USERS);
// System can retrieve the timestamp.
mContext.binder.clearCallingIdentity();
- assertEquals(secondNetworkLogRetrievalTime, dpm.getLastNetworkLogRetrievalTime());
+ assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(secondNetworkLogRetrievalTime);
// Removing the device owner should clear the timestamp.
clearDeviceOwner();
- assertEquals(-1, dpm.getLastNetworkLogRetrievalTime());
+ assertThat(dpm.getLastNetworkLogRetrievalTime()).isEqualTo(-1);
}
+ @Test
public void testGetBindDeviceAdminTargetUsers() throws Exception {
// Setup device owner.
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -4268,9 +4414,9 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setLockTaskPackages(who, packages);
MoreAsserts.assertEquals(packages, dpm.getLockTaskPackages(who));
for (String p : packages) {
- assertTrue(dpm.isLockTaskPermitted(p));
+ assertThat(dpm.isLockTaskPermitted(p)).isTrue();
}
- assertFalse(dpm.isLockTaskPermitted("anotherPackage"));
+ assertThat(dpm.isLockTaskPermitted("anotherPackage")).isFalse();
// Test to see if set lock task features can be set
dpm.setLockTaskFeatures(who, flags);
verifyLockTaskState(userId, packages, flags);
@@ -4283,11 +4429,12 @@ public class DevicePolicyManagerTest extends DpmTestBase {
() -> dpm.setLockTaskPackages(who, packages));
assertExpectException(SecurityException.class, /* messageRegex =*/ null,
() -> dpm.getLockTaskPackages(who));
- assertFalse(dpm.isLockTaskPermitted("doPackage1"));
+ assertThat(dpm.isLockTaskPermitted("doPackage1")).isFalse();
assertExpectException(SecurityException.class, /* messageRegex =*/ null,
() -> dpm.setLockTaskFeatures(who, flags));
}
+ @Test
public void testLockTaskPolicyForProfileOwner() throws Exception {
// Setup a PO
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
@@ -4315,9 +4462,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
final int mpoFlags = DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS
| DevicePolicyManager.LOCK_TASK_FEATURE_HOME
| DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
- verifyCanNotSetLockTask(MANAGED_PROFILE_ADMIN_UID, adminDifferentPackage, mpoPackages, mpoFlags);
+ verifyCanNotSetLockTask(MANAGED_PROFILE_ADMIN_UID, adminDifferentPackage, mpoPackages,
+ mpoFlags);
}
+ @Test
public void testLockTaskFeatures_IllegalArgumentException() throws Exception {
// Setup a device owner.
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -4332,12 +4481,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
() -> dpm.setLockTaskFeatures(admin1, flags));
}
+ @Test
public void testSecondaryLockscreen_profileOwner() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
// Initial state is disabled.
- assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(
- CALLER_USER_HANDLE)));
+ assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(
+ CALLER_USER_HANDLE))).isFalse();
// Profile owner can set enabled state.
setAsProfileOwner(admin1);
@@ -4345,8 +4495,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.getString(R.string.config_defaultSupervisionProfileOwnerComponent))
.thenReturn(admin1.flattenToString());
dpm.setSecondaryLockscreenEnabled(admin1, true);
- assertTrue(dpm.isSecondaryLockscreenEnabled(UserHandle.of(
- CALLER_USER_HANDLE)));
+ assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(
+ CALLER_USER_HANDLE))).isTrue();
// Managed profile managed by different package is unaffiliated - cannot set enabled.
final int managedProfileUserId = 15;
@@ -4359,11 +4509,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
() -> dpm.setSecondaryLockscreenEnabled(adminDifferentPackage, false));
}
+ @Test
public void testSecondaryLockscreen_deviceOwner() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
// Initial state is disabled.
- assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(UserHandle.USER_SYSTEM)));
+ assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(UserHandle.USER_SYSTEM)))
+ .isFalse();
// Device owners can set enabled state.
setupDeviceOwner();
@@ -4371,14 +4523,16 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.getString(R.string.config_defaultSupervisionProfileOwnerComponent))
.thenReturn(admin1.flattenToString());
dpm.setSecondaryLockscreenEnabled(admin1, true);
- assertTrue(dpm.isSecondaryLockscreenEnabled(UserHandle.of(UserHandle.USER_SYSTEM)));
+ assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(UserHandle.USER_SYSTEM)))
+ .isTrue();
}
+ @Test
public void testSecondaryLockscreen_nonOwner() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
// Initial state is disabled.
- assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE)));
+ assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE))).isFalse();
// Non-DO/PO cannot set enabled state.
when(mServiceContext.resources
@@ -4386,9 +4540,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.thenReturn(admin1.flattenToString());
assertExpectException(SecurityException.class, /* messageRegex= */ null,
() -> dpm.setSecondaryLockscreenEnabled(admin1, true));
- assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE)));
+ assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE))).isFalse();
}
+ @Test
public void testSecondaryLockscreen_nonSupervisionApp() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
@@ -4403,13 +4558,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
eq(CALLER_USER_HANDLE));
// Initial state is disabled.
- assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE)));
+ assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE))).isFalse();
// Caller is Profile Owner, but no supervision app is configured.
setAsProfileOwner(admin1);
assertExpectException(SecurityException.class, "is not the default supervision component",
() -> dpm.setSecondaryLockscreenEnabled(admin1, true));
- assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE)));
+ assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE))).isFalse();
// Caller is Profile Owner, but is not the default configured supervision app.
when(mServiceContext.resources
@@ -4417,22 +4572,23 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.thenReturn(admin2.flattenToString());
assertExpectException(SecurityException.class, "is not the default supervision component",
() -> dpm.setSecondaryLockscreenEnabled(admin1, true));
- assertFalse(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE)));
+ assertThat(dpm.isSecondaryLockscreenEnabled(UserHandle.of(CALLER_USER_HANDLE))).isFalse();
}
+ @Test
public void testIsDeviceManaged() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
// The device owner itself, any uid holding MANAGE_USERS permission and the system can
// find out that the device has a device owner.
- assertTrue(dpm.isDeviceManaged());
+ assertThat(dpm.isDeviceManaged()).isTrue();
mContext.binder.callingUid = 1234567;
mContext.callerPermissions.add(permission.MANAGE_USERS);
- assertTrue(dpm.isDeviceManaged());
+ assertThat(dpm.isDeviceManaged()).isTrue();
mContext.callerPermissions.remove(permission.MANAGE_USERS);
mContext.binder.clearCallingIdentity();
- assertTrue(dpm.isDeviceManaged());
+ assertThat(dpm.isDeviceManaged()).isTrue();
clearDeviceOwner();
@@ -4440,12 +4596,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// not have a device owner.
mContext.binder.callingUid = 1234567;
mContext.callerPermissions.add(permission.MANAGE_USERS);
- assertFalse(dpm.isDeviceManaged());
+ assertThat(dpm.isDeviceManaged()).isFalse();
mContext.callerPermissions.remove(permission.MANAGE_USERS);
mContext.binder.clearCallingIdentity();
- assertFalse(dpm.isDeviceManaged());
+ assertThat(dpm.isDeviceManaged()).isFalse();
}
+ @Test
public void testDeviceOwnerOrganizationName() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -4453,23 +4610,24 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setOrganizationName(admin1, "organization");
// Device owner can retrieve organization managing the device.
- assertEquals("organization", dpm.getDeviceOwnerOrganizationName());
+ assertThat(dpm.getDeviceOwnerOrganizationName()).isEqualTo("organization");
// Any uid holding MANAGE_USERS permission can retrieve organization managing the device.
mContext.binder.callingUid = 1234567;
mContext.callerPermissions.add(permission.MANAGE_USERS);
- assertEquals("organization", dpm.getDeviceOwnerOrganizationName());
+ assertThat(dpm.getDeviceOwnerOrganizationName()).isEqualTo("organization");
mContext.callerPermissions.remove(permission.MANAGE_USERS);
// System can retrieve organization managing the device.
mContext.binder.clearCallingIdentity();
- assertEquals("organization", dpm.getDeviceOwnerOrganizationName());
+ assertThat(dpm.getDeviceOwnerOrganizationName()).isEqualTo("organization");
// Removing the device owner clears the organization managing the device.
clearDeviceOwner();
- assertNull(dpm.getDeviceOwnerOrganizationName());
+ assertThat(dpm.getDeviceOwnerOrganizationName()).isNull();
}
+ @Test
public void testWipeDataManagedProfile() throws Exception {
final int MANAGED_PROFILE_USER_ID = 15;
final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 19436);
@@ -4489,6 +4647,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
MANAGED_PROFILE_USER_ID);
}
+ @Test
public void testWipeDataManagedProfileDisallowed() throws Exception {
final int MANAGED_PROFILE_USER_ID = 15;
final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 19436);
@@ -4512,6 +4671,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
() -> dpm.wipeData(0));
}
+ @Test
public void testWipeDataDeviceOwner() throws Exception {
setDeviceOwner();
when(getServices().userManager.getUserRestrictionSource(
@@ -4527,6 +4687,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
/*wipeEuicc=*/ eq(false));
}
+ @Test
public void testWipeEuiccDataEnabled() throws Exception {
setDeviceOwner();
when(getServices().userManager.getUserRestrictionSource(
@@ -4542,6 +4703,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
/*wipeEuicc=*/ eq(true));
}
+ @Test
public void testWipeDataDeviceOwnerDisallowed() throws Exception {
setDeviceOwner();
when(getServices().userManager.getUserRestrictionSource(
@@ -4556,6 +4718,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
() -> dpm.wipeData(0));
}
+ @Test
public void testMaximumFailedPasswordAttemptsReachedManagedProfile() throws Exception {
final int MANAGED_PROFILE_USER_ID = 15;
final int MANAGED_PROFILE_ADMIN_UID = UserHandle.getUid(MANAGED_PROFILE_USER_ID, 19436);
@@ -4588,6 +4751,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verifyZeroInteractions(getServices().recoverySystem);
}
+ @Test
public void testMaximumFailedPasswordAttemptsReachedManagedProfileDisallowed()
throws Exception {
final int MANAGED_PROFILE_USER_ID = 15;
@@ -4621,6 +4785,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verifyZeroInteractions(getServices().recoverySystem);
}
+ @Test
public void testMaximumFailedPasswordAttemptsReachedDeviceOwner() throws Exception {
setDeviceOwner();
when(getServices().userManager.getUserRestrictionSource(
@@ -4643,6 +4808,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
/*wipeEuicc=*/ eq(false));
}
+ @Test
public void testMaximumFailedPasswordAttemptsReachedDeviceOwnerDisallowed() throws Exception {
setDeviceOwner();
when(getServices().userManager.getUserRestrictionSource(
@@ -4664,6 +4830,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.removeUserEvenWhenDisallowed(anyInt());
}
+ @Test
public void testMaximumFailedDevicePasswordAttemptsReachedOrgOwnedManagedProfile()
throws Exception {
final int MANAGED_PROFILE_USER_ID = 15;
@@ -4679,16 +4846,16 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
dpm.setMaximumFailedPasswordsForWipe(admin1, 3);
- assertEquals(3, dpm.getMaximumFailedPasswordsForWipe(admin1));
- assertEquals(3, dpm.getMaximumFailedPasswordsForWipe(null));
+ assertThat(dpm.getMaximumFailedPasswordsForWipe(admin1)).isEqualTo(3);
+ assertThat(dpm.getMaximumFailedPasswordsForWipe(null)).isEqualTo(3);
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
mContext.callerPermissions.add(permission.BIND_DEVICE_ADMIN);
- assertEquals(3, dpm.getMaximumFailedPasswordsForWipe(null, UserHandle.USER_SYSTEM));
+ assertThat(dpm.getMaximumFailedPasswordsForWipe(null, UserHandle.USER_SYSTEM)).isEqualTo(3);
// Check that primary will be wiped as a result of failed primary user unlock attempts.
- assertEquals(UserHandle.USER_SYSTEM,
- dpm.getProfileWithMinimumFailedPasswordsForWipe(UserHandle.USER_SYSTEM));
+ assertThat(dpm.getProfileWithMinimumFailedPasswordsForWipe(UserHandle.USER_SYSTEM))
+ .isEqualTo(UserHandle.USER_SYSTEM);
// Failed password attempts on the parent user are taken into account, as there isn't a
// separate work challenge.
@@ -4702,6 +4869,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
/*wipeEuicc=*/ eq(false));
}
+ @Test
public void testMaximumFailedProfilePasswordAttemptsReachedOrgOwnedManagedProfile()
throws Exception {
final int MANAGED_PROFILE_USER_ID = 15;
@@ -4724,14 +4892,15 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
mContext.callerPermissions.add(permission.BIND_DEVICE_ADMIN);
- assertEquals(0, dpm.getMaximumFailedPasswordsForWipe(null, UserHandle.USER_SYSTEM));
- assertEquals(3, dpm.getMaximumFailedPasswordsForWipe(null, MANAGED_PROFILE_USER_ID));
+ assertThat(dpm.getMaximumFailedPasswordsForWipe(null, UserHandle.USER_SYSTEM)).isEqualTo(0);
+ assertThat(dpm.getMaximumFailedPasswordsForWipe(null, MANAGED_PROFILE_USER_ID))
+ .isEqualTo(3);
// Check that the policy is not affecting primary profile challenge.
- assertEquals(UserHandle.USER_NULL,
- dpm.getProfileWithMinimumFailedPasswordsForWipe(UserHandle.USER_SYSTEM));
+ assertThat(dpm.getProfileWithMinimumFailedPasswordsForWipe(UserHandle.USER_SYSTEM))
+ .isEqualTo(UserHandle.USER_NULL);
// Check that primary will be wiped as a result of failed profile unlock attempts.
- assertEquals(UserHandle.USER_SYSTEM,
- dpm.getProfileWithMinimumFailedPasswordsForWipe(MANAGED_PROFILE_USER_ID));
+ assertThat(dpm.getProfileWithMinimumFailedPasswordsForWipe(MANAGED_PROFILE_USER_ID))
+ .isEqualTo(UserHandle.USER_SYSTEM);
// Simulate three failed attempts at solving the separate challenge.
dpm.reportFailedPasswordAttempt(MANAGED_PROFILE_USER_ID);
@@ -4744,6 +4913,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
/*wipeEuicc=*/ eq(false));
}
+ @Test
public void testGetPermissionGrantState() throws Exception {
final String permission = "some.permission";
final String app1 = "com.example.app1";
@@ -4766,10 +4936,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// System can retrieve permission grant state.
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
mContext.packageName = "android";
- assertEquals(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED,
- dpm.getPermissionGrantState(null, app1, permission));
- assertEquals(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT,
- dpm.getPermissionGrantState(null, app2, permission));
+ assertThat(dpm.getPermissionGrantState(null, app1, permission))
+ .isEqualTo(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
+ assertThat(dpm.getPermissionGrantState(null, app2, permission))
+ .isEqualTo(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
// A regular app cannot retrieve permission grant state.
mContext.binder.callingUid = setupPackageInPackageManager(app1, 1);
@@ -4781,12 +4951,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
mContext.packageName = admin1.getPackageName();
setAsProfileOwner(admin1);
- assertEquals(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED,
- dpm.getPermissionGrantState(admin1, app1, permission));
- assertEquals(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT,
- dpm.getPermissionGrantState(admin1, app2, permission));
+ assertThat(dpm.getPermissionGrantState(admin1, app1, permission))
+ .isEqualTo(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
+ assertThat(dpm.getPermissionGrantState(admin1, app2, permission))
+ .isEqualTo(DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT);
}
+ @Test
public void testResetPasswordWithToken() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -4801,27 +4972,26 @@ public class DevicePolicyManagerTest extends DpmTestBase {
when(getServices().lockPatternUtils.addEscrowToken(eq(token), eq(UserHandle.USER_SYSTEM),
nullable(EscrowTokenStateChangeCallback.class)))
.thenReturn(handle);
- assertTrue(dpm.setResetPasswordToken(admin1, token));
+ assertThat(dpm.setResetPasswordToken(admin1, token)).isTrue();
// test password activation
- when(getServices().lockPatternUtils.isEscrowTokenActive(eq(handle), eq(UserHandle.USER_SYSTEM)))
- .thenReturn(true);
- assertTrue(dpm.isResetPasswordTokenActive(admin1));
+ when(getServices().lockPatternUtils.isEscrowTokenActive(handle, UserHandle.USER_SYSTEM))
+ .thenReturn(true);
+ assertThat(dpm.isResetPasswordTokenActive(admin1)).isTrue();
// test reset password with token
when(getServices().lockPatternUtils.setLockCredentialWithToken(
- eq(LockscreenCredential.createPassword(password)),
- eq(handle), eq(token),
- eq(UserHandle.USER_SYSTEM)))
- .thenReturn(true);
- assertTrue(dpm.resetPasswordWithToken(admin1, password, token, 0));
+ LockscreenCredential.createPassword(password), handle, token,
+ UserHandle.USER_SYSTEM)).thenReturn(true);
+ assertThat(dpm.resetPasswordWithToken(admin1, password, token, 0)).isTrue();
// test removing a token
- when(getServices().lockPatternUtils.removeEscrowToken(eq(handle), eq(UserHandle.USER_SYSTEM)))
+ when(getServices().lockPatternUtils.removeEscrowToken(handle, UserHandle.USER_SYSTEM))
.thenReturn(true);
- assertTrue(dpm.clearResetPasswordToken(admin1));
+ assertThat(dpm.clearResetPasswordToken(admin1)).isTrue();
}
+ @Test
public void testIsActivePasswordSufficient() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
mContext.packageName = admin1.getPackageName();
@@ -4841,11 +5011,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
PasswordMetrics passwordMetricsNoSymbols = computeForPassword("abcdXYZ5".getBytes());
setActivePasswordState(passwordMetricsNoSymbols);
- assertTrue(dpm.isActivePasswordSufficient());
+ assertThat(dpm.isActivePasswordSufficient()).isTrue();
initializeDpms();
reset(mContext.spiedContext);
- assertTrue(dpm.isActivePasswordSufficient());
+ assertThat(dpm.isActivePasswordSufficient()).isTrue();
// This call simulates the user entering the password for the first time after a reboot.
// This causes password metrics to be reloaded into memory. Until this happens,
@@ -4854,23 +5024,24 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// requirements. This is a known limitation of the current implementation of
// isActivePasswordSufficient() - see b/34218769.
setActivePasswordState(passwordMetricsNoSymbols);
- assertTrue(dpm.isActivePasswordSufficient());
+ assertThat(dpm.isActivePasswordSufficient()).isTrue();
dpm.setPasswordMinimumSymbols(admin1, 1);
// This assertion would fail if we had not called setActivePasswordState() again after
// initializeDpms() - see previous comment.
- assertFalse(dpm.isActivePasswordSufficient());
+ assertThat(dpm.isActivePasswordSufficient()).isFalse();
initializeDpms();
reset(mContext.spiedContext);
- assertFalse(dpm.isActivePasswordSufficient());
+ assertThat(dpm.isActivePasswordSufficient()).isFalse();
PasswordMetrics passwordMetricsWithSymbols = computeForPassword("abcd.XY5".getBytes());
setActivePasswordState(passwordMetricsWithSymbols);
- assertTrue(dpm.isActivePasswordSufficient());
+ assertThat(dpm.isActivePasswordSufficient()).isTrue();
}
+ @Test
public void testIsActivePasswordSufficient_noLockScreen() throws Exception {
// If there is no lock screen, the password is considered empty no matter what, because
// it provides no security.
@@ -4885,7 +5056,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.thenReturn(new PasswordMetrics(CREDENTIAL_TYPE_NONE));
// If no password requirements are set, isActivePasswordSufficient should succeed.
- assertTrue(dpm.isActivePasswordSufficient());
+ assertThat(dpm.isActivePasswordSufficient()).isTrue();
// Now set some password quality requirements.
dpm.setPasswordQuality(admin1, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
@@ -4900,9 +5071,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
MockUtils.checkUserHandle(userHandle));
// The active (nonexistent) password doesn't comply with the requirements.
- assertFalse(dpm.isActivePasswordSufficient());
+ assertThat(dpm.isActivePasswordSufficient()).isFalse();
}
+ @Test
public void testIsPasswordSufficientAfterProfileUnification() throws Exception {
final int managedProfileUserId = CALLER_USER_HANDLE;
final int managedProfileAdminUid =
@@ -4921,13 +5093,13 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Numeric password is compliant with current requirement (QUALITY_NUMERIC set explicitly
// on the parent admin)
- assertTrue(dpm.isPasswordSufficientAfterProfileUnification(UserHandle.USER_SYSTEM,
- UserHandle.USER_NULL));
+ assertThat(dpm.isPasswordSufficientAfterProfileUnification(UserHandle.USER_SYSTEM,
+ UserHandle.USER_NULL)).isTrue();
// Numeric password is not compliant if profile is to be unified: the profile has a
// QUALITY_ALPHABETIC policy on itself which will be enforced on the password after
// unification.
- assertFalse(dpm.isPasswordSufficientAfterProfileUnification(UserHandle.USER_SYSTEM,
- managedProfileUserId));
+ assertThat(dpm.isPasswordSufficientAfterProfileUnification(UserHandle.USER_SYSTEM,
+ managedProfileUserId)).isFalse();
}
private void setActivePasswordState(PasswordMetrics passwordMetrics)
@@ -4961,6 +5133,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.binder.restoreCallingIdentity(ident);
}
+ @Test
public void testIsCurrentInputMethodSetByOwnerForDeviceOwner() throws Exception {
final String currentIme = Settings.Secure.DEFAULT_INPUT_METHOD;
final Uri currentImeUri = Settings.Secure.getUriFor(currentIme);
@@ -4976,70 +5149,71 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// First and second user set IMEs manually.
mContext.binder.callingUid = firstUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
mContext.binder.callingUid = secondUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
// Device owner changes IME for first user.
mContext.binder.callingUid = deviceOwnerUid;
- when(getServices().settings.settingsSecureGetStringForUser(currentIme, UserHandle.USER_SYSTEM))
- .thenReturn("ime1");
+ when(getServices().settings.settingsSecureGetStringForUser(currentIme,
+ UserHandle.USER_SYSTEM)).thenReturn("ime1");
dpm.setSecureSetting(admin1, currentIme, "ime2");
verify(getServices().settings).settingsSecurePutStringForUser(currentIme, "ime2",
UserHandle.USER_SYSTEM);
reset(getServices().settings);
dpms.notifyChangeToContentObserver(currentImeUri, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = firstUserSystemUid;
- assertTrue(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
mContext.binder.callingUid = secondUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
// Second user changes IME manually.
dpms.notifyChangeToContentObserver(currentImeUri, CALLER_USER_HANDLE);
mContext.binder.callingUid = firstUserSystemUid;
- assertTrue(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
mContext.binder.callingUid = secondUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
// First user changes IME manually.
dpms.notifyChangeToContentObserver(currentImeUri, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = firstUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
mContext.binder.callingUid = secondUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
// Device owner changes IME for first user again.
mContext.binder.callingUid = deviceOwnerUid;
- when(getServices().settings.settingsSecureGetStringForUser(currentIme, UserHandle.USER_SYSTEM))
- .thenReturn("ime2");
+ when(getServices().settings.settingsSecureGetStringForUser(currentIme,
+ UserHandle.USER_SYSTEM)).thenReturn("ime2");
dpm.setSecureSetting(admin1, currentIme, "ime3");
verify(getServices().settings).settingsSecurePutStringForUser(currentIme, "ime3",
UserHandle.USER_SYSTEM);
dpms.notifyChangeToContentObserver(currentImeUri, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = firstUserSystemUid;
- assertTrue(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
mContext.binder.callingUid = secondUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
// Restarting the DPMS should not lose information.
initializeDpms();
mContext.binder.callingUid = firstUserSystemUid;
- assertTrue(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
mContext.binder.callingUid = secondUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
// Device owner can find out whether it set the current IME itself.
mContext.binder.callingUid = deviceOwnerUid;
- assertTrue(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
// Removing the device owner should clear the information that it set the current IME.
clearDeviceOwner();
mContext.binder.callingUid = firstUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
mContext.binder.callingUid = secondUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
}
+ @Test
public void testIsCurrentInputMethodSetByOwnerForProfileOwner() throws Exception {
final String currentIme = Settings.Secure.DEFAULT_INPUT_METHOD;
final Uri currentImeUri = Settings.Secure.getUriFor(currentIme);
@@ -5055,9 +5229,9 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// First and second user set IMEs manually.
mContext.binder.callingUid = firstUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
mContext.binder.callingUid = secondUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
// Profile owner changes IME for second user.
mContext.binder.callingUid = profileOwnerUid;
@@ -5069,23 +5243,23 @@ public class DevicePolicyManagerTest extends DpmTestBase {
reset(getServices().settings);
dpms.notifyChangeToContentObserver(currentImeUri, CALLER_USER_HANDLE);
mContext.binder.callingUid = firstUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
mContext.binder.callingUid = secondUserSystemUid;
- assertTrue(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
// First user changes IME manually.
dpms.notifyChangeToContentObserver(currentImeUri, UserHandle.USER_SYSTEM);
mContext.binder.callingUid = firstUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
mContext.binder.callingUid = secondUserSystemUid;
- assertTrue(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
// Second user changes IME manually.
dpms.notifyChangeToContentObserver(currentImeUri, CALLER_USER_HANDLE);
mContext.binder.callingUid = firstUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
mContext.binder.callingUid = secondUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
// Profile owner changes IME for second user again.
mContext.binder.callingUid = profileOwnerUid;
@@ -5096,29 +5270,30 @@ public class DevicePolicyManagerTest extends DpmTestBase {
CALLER_USER_HANDLE);
dpms.notifyChangeToContentObserver(currentImeUri, CALLER_USER_HANDLE);
mContext.binder.callingUid = firstUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
mContext.binder.callingUid = secondUserSystemUid;
- assertTrue(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
// Restarting the DPMS should not lose information.
initializeDpms();
mContext.binder.callingUid = firstUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
mContext.binder.callingUid = secondUserSystemUid;
- assertTrue(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
// Profile owner can find out whether it set the current IME itself.
mContext.binder.callingUid = profileOwnerUid;
- assertTrue(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isTrue();
// Removing the profile owner should clear the information that it set the current IME.
dpm.clearProfileOwner(admin1);
mContext.binder.callingUid = firstUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
mContext.binder.callingUid = secondUserSystemUid;
- assertFalse(dpm.isCurrentInputMethodSetByOwner());
+ assertThat(dpm.isCurrentInputMethodSetByOwner()).isFalse();
}
+ @Test
public void testSetPermittedCrossProfileNotificationListeners_unavailableForDo()
throws Exception {
// Set up a device owner.
@@ -5127,6 +5302,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertSetPermittedCrossProfileNotificationListenersUnavailable(mContext.binder.callingUid);
}
+ @Test
public void testSetPermittedCrossProfileNotificationListeners_unavailableForPoOnUser()
throws Exception {
// Set up a profile owner.
@@ -5141,23 +5317,24 @@ public class DevicePolicyManagerTest extends DpmTestBase {
final int userId = UserHandle.getUserId(adminUid);
final String packageName = "some.package";
- assertFalse(dpms.setPermittedCrossProfileNotificationListeners(
- admin1, Collections.singletonList(packageName)));
- assertNull(dpms.getPermittedCrossProfileNotificationListeners(admin1));
+ assertThat(dpms.setPermittedCrossProfileNotificationListeners(
+ admin1, Collections.singletonList(packageName))).isFalse();
+ assertThat(dpms.getPermittedCrossProfileNotificationListeners(admin1)).isNull();
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertTrue(dpms.isNotificationListenerServicePermitted(packageName, userId));
+ assertThat(dpms.isNotificationListenerServicePermitted(packageName, userId)).isTrue();
// Attempt to set to empty list (which means no listener is allowlisted)
mContext.binder.callingUid = adminUid;
- assertFalse(dpms.setPermittedCrossProfileNotificationListeners(
- admin1, Collections.emptyList()));
- assertNull(dpms.getPermittedCrossProfileNotificationListeners(admin1));
+ assertThat(dpms.setPermittedCrossProfileNotificationListeners(
+ admin1, Collections.emptyList())).isFalse();
+ assertThat(dpms.getPermittedCrossProfileNotificationListeners(admin1)).isNull();
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertTrue(dpms.isNotificationListenerServicePermitted(packageName, userId));
+ assertThat(dpms.isNotificationListenerServicePermitted(packageName, userId)).isTrue();
}
+ @Test
public void testIsNotificationListenerServicePermitted_onlySystemCanCall() throws Exception {
// Set up a managed profile
final int MANAGED_PROFILE_USER_ID = 15;
@@ -5171,8 +5348,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
UserHandle.USER_SYSTEM, // We check the packageInfo from the primary user.
/*appId=*/ 12345, /*flags=*/ 0);
- assertTrue(dpms.setPermittedCrossProfileNotificationListeners(
- admin1, Collections.singletonList(permittedListener)));
+ assertThat(dpms.setPermittedCrossProfileNotificationListeners(
+ admin1, Collections.singletonList(permittedListener))).isTrue();
// isNotificationListenerServicePermitted should throw if not called from System.
assertExpectException(SecurityException.class, /* messageRegex= */ null,
@@ -5180,10 +5357,11 @@ public class DevicePolicyManagerTest extends DpmTestBase {
permittedListener, MANAGED_PROFILE_USER_ID));
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertTrue(dpms.isNotificationListenerServicePermitted(
- permittedListener, MANAGED_PROFILE_USER_ID));
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ permittedListener, MANAGED_PROFILE_USER_ID)).isTrue();
}
+ @Test
public void testSetPermittedCrossProfileNotificationListeners_managedProfile()
throws Exception {
// Set up a managed profile
@@ -5212,63 +5390,64 @@ public class DevicePolicyManagerTest extends DpmTestBase {
++appId, ApplicationInfo.FLAG_SYSTEM);
// By default all packages are allowed
- assertNull(dpms.getPermittedCrossProfileNotificationListeners(admin1));
+ assertThat(dpms.getPermittedCrossProfileNotificationListeners(admin1)).isNull();
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertTrue(dpms.isNotificationListenerServicePermitted(
- permittedListener, MANAGED_PROFILE_USER_ID));
- assertTrue(dpms.isNotificationListenerServicePermitted(
- notPermittedListener, MANAGED_PROFILE_USER_ID));
- assertTrue(dpms.isNotificationListenerServicePermitted(
- systemListener, MANAGED_PROFILE_USER_ID));
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ permittedListener, MANAGED_PROFILE_USER_ID)).isTrue();
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ notPermittedListener, MANAGED_PROFILE_USER_ID)).isTrue();
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
// Setting only one package in the allowlist
mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- assertTrue(dpms.setPermittedCrossProfileNotificationListeners(
- admin1, Collections.singletonList(permittedListener)));
+ assertThat(dpms.setPermittedCrossProfileNotificationListeners(
+ admin1, Collections.singletonList(permittedListener))).isTrue();
final List<String> permittedListeners =
dpms.getPermittedCrossProfileNotificationListeners(admin1);
- assertEquals(1, permittedListeners.size());
- assertEquals(permittedListener, permittedListeners.get(0));
+ assertThat(permittedListeners.size()).isEqualTo(1);
+ assertThat(permittedListeners.get(0)).isEqualTo(permittedListener);
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertTrue(dpms.isNotificationListenerServicePermitted(
- permittedListener, MANAGED_PROFILE_USER_ID));
- assertFalse(dpms.isNotificationListenerServicePermitted(
- notPermittedListener, MANAGED_PROFILE_USER_ID));
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ permittedListener, MANAGED_PROFILE_USER_ID)).isTrue();
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ notPermittedListener, MANAGED_PROFILE_USER_ID)).isFalse();
// System packages are always allowed (even if not in the allowlist)
- assertTrue(dpms.isNotificationListenerServicePermitted(
- systemListener, MANAGED_PROFILE_USER_ID));
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
// Setting an empty allowlist - only system listeners allowed
mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- assertTrue(dpms.setPermittedCrossProfileNotificationListeners(
- admin1, Collections.emptyList()));
- assertEquals(0, dpms.getPermittedCrossProfileNotificationListeners(admin1).size());
+ assertThat(dpms.setPermittedCrossProfileNotificationListeners(
+ admin1, Collections.emptyList())).isTrue();
+ assertThat(dpms.getPermittedCrossProfileNotificationListeners(admin1).size()).isEqualTo(0);
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertFalse(dpms.isNotificationListenerServicePermitted(
- permittedListener, MANAGED_PROFILE_USER_ID));
- assertFalse(dpms.isNotificationListenerServicePermitted(
- notPermittedListener, MANAGED_PROFILE_USER_ID));
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ permittedListener, MANAGED_PROFILE_USER_ID)).isFalse();
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ notPermittedListener, MANAGED_PROFILE_USER_ID)).isFalse();
// System packages are always allowed (even if not in the allowlist)
- assertTrue(dpms.isNotificationListenerServicePermitted(
- systemListener, MANAGED_PROFILE_USER_ID));
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
// Setting a null allowlist - all listeners allowed
mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- assertTrue(dpms.setPermittedCrossProfileNotificationListeners(admin1, null));
- assertNull(dpms.getPermittedCrossProfileNotificationListeners(admin1));
+ assertThat(dpms.setPermittedCrossProfileNotificationListeners(admin1, null)).isTrue();
+ assertThat(dpms.getPermittedCrossProfileNotificationListeners(admin1)).isNull();
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertTrue(dpms.isNotificationListenerServicePermitted(
- permittedListener, MANAGED_PROFILE_USER_ID));
- assertTrue(dpms.isNotificationListenerServicePermitted(
- notPermittedListener, MANAGED_PROFILE_USER_ID));
- assertTrue(dpms.isNotificationListenerServicePermitted(
- systemListener, MANAGED_PROFILE_USER_ID));
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ permittedListener, MANAGED_PROFILE_USER_ID)).isTrue();
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ notPermittedListener, MANAGED_PROFILE_USER_ID)).isTrue();
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
}
+ @Test
public void testSetPermittedCrossProfileNotificationListeners_doesNotAffectPrimaryProfile()
throws Exception {
// Set up a managed profile
@@ -5291,36 +5470,37 @@ public class DevicePolicyManagerTest extends DpmTestBase {
++appId, ApplicationInfo.FLAG_SYSTEM);
// By default all packages are allowed (for all profiles)
- assertNull(dpms.getPermittedCrossProfileNotificationListeners(admin1));
+ assertThat(dpms.getPermittedCrossProfileNotificationListeners(admin1)).isNull();
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertTrue(dpms.isNotificationListenerServicePermitted(
- nonSystemPackage, MANAGED_PROFILE_USER_ID));
- assertTrue(dpms.isNotificationListenerServicePermitted(
- systemListener, MANAGED_PROFILE_USER_ID));
- assertTrue(dpms.isNotificationListenerServicePermitted(
- nonSystemPackage, UserHandle.USER_SYSTEM));
- assertTrue(dpms.isNotificationListenerServicePermitted(
- systemListener, UserHandle.USER_SYSTEM));
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ nonSystemPackage, MANAGED_PROFILE_USER_ID)).isTrue();
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ nonSystemPackage, UserHandle.USER_SYSTEM)).isTrue();
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ systemListener, UserHandle.USER_SYSTEM)).isTrue();
// Setting an empty allowlist - only system listeners allowed in managed profile, but
// all allowed in primary profile
mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
- assertTrue(dpms.setPermittedCrossProfileNotificationListeners(
- admin1, Collections.emptyList()));
- assertEquals(0, dpms.getPermittedCrossProfileNotificationListeners(admin1).size());
+ assertThat(dpms.setPermittedCrossProfileNotificationListeners(
+ admin1, Collections.emptyList())).isTrue();
+ assertThat(dpms.getPermittedCrossProfileNotificationListeners(admin1).size()).isEqualTo(0);
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertFalse(dpms.isNotificationListenerServicePermitted(
- nonSystemPackage, MANAGED_PROFILE_USER_ID));
- assertTrue(dpms.isNotificationListenerServicePermitted(
- systemListener, MANAGED_PROFILE_USER_ID));
- assertTrue(dpms.isNotificationListenerServicePermitted(
- nonSystemPackage, UserHandle.USER_SYSTEM));
- assertTrue(dpms.isNotificationListenerServicePermitted(
- systemListener, UserHandle.USER_SYSTEM));
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ nonSystemPackage, MANAGED_PROFILE_USER_ID)).isFalse();
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ systemListener, MANAGED_PROFILE_USER_ID)).isTrue();
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ nonSystemPackage, UserHandle.USER_SYSTEM)).isTrue();
+ assertThat(dpms.isNotificationListenerServicePermitted(
+ systemListener, UserHandle.USER_SYSTEM)).isTrue();
}
+ @Test
public void testGetOwnerInstalledCaCertsForDeviceOwner() throws Exception {
mServiceContext.packageName = mRealTestContext.getPackageName();
mServiceContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
@@ -5330,6 +5510,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verifyCanGetOwnerInstalledCaCerts(admin1, mAdmin1Context);
}
+ @Test
public void testGetOwnerInstalledCaCertsForProfileOwner() throws Exception {
mServiceContext.packageName = mRealTestContext.getPackageName();
mServiceContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
@@ -5340,6 +5521,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verifyCantGetOwnerInstalledCaCertsProfileOwnerRemoval(admin1, mAdmin1Context);
}
+ @Test
public void testGetOwnerInstalledCaCertsForDelegate() throws Exception {
mServiceContext.packageName = mRealTestContext.getPackageName();
mServiceContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
@@ -5359,6 +5541,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verifyCantGetOwnerInstalledCaCertsProfileOwnerRemoval(null, caller);
}
+ @Test
public void testDisallowSharingIntoProfileSetRestriction() {
when(mServiceContext.resources.getString(R.string.config_managed_provisioning_package))
.thenReturn("com.android.managedprovisioning");
@@ -5371,6 +5554,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verifyDataSharingChangedBroadcast();
}
+ @Test
public void testDisallowSharingIntoProfileClearRestriction() {
when(mServiceContext.resources.getString(R.string.config_managed_provisioning_package))
.thenReturn("com.android.managedprovisioning");
@@ -5383,6 +5567,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verifyDataSharingChangedBroadcast();
}
+ @Test
public void testDisallowSharingIntoProfileUnchanged() {
RestrictionsListener listener = new RestrictionsListener(mContext);
listener.onUserRestrictionsChanged(CALLER_USER_HANDLE, new Bundle(), new Bundle());
@@ -5399,6 +5584,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
MockUtils.checkUserHandle(UserHandle.USER_SYSTEM));
}
+ @Test
public void testOverrideApnAPIsFailWithPO() throws Exception {
setupProfileOwner();
ApnSetting apn = (new ApnSetting.Builder())
@@ -5446,13 +5632,14 @@ public class DevicePolicyManagerTest extends DpmTestBase {
runAsCaller(callerContext, dpms, (dpm) -> {
when(getServices().keyChainConnection.getService().installCaCertificate(caCert))
.thenReturn(alias);
- assertTrue(dpm.installCaCert(caller, caCert));
+ assertThat(dpm.installCaCert(caller, caCert)).isTrue();
when(getServices().keyChainConnection.getService().getUserCaAliases())
.thenReturn(asSlice(new String[] {alias}));
});
- getServices().injectBroadcast(mServiceContext, new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED)
- .putExtra(Intent.EXTRA_USER_HANDLE, callerUser.getIdentifier()),
+ getServices().injectBroadcast(mServiceContext,
+ new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED)
+ .putExtra(Intent.EXTRA_USER_HANDLE, callerUser.getIdentifier()),
callerUser.getIdentifier());
flushTasks(dpms);
@@ -5461,25 +5648,27 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Device Owner / Profile Owner can find out which CA certs were installed by itself.
runAsCaller(admin1Context, dpms, (dpm) -> {
final List<String> installedCaCerts = dpm.getOwnerInstalledCaCerts(callerUser);
- assertEquals(Collections.singletonList(alias), installedCaCerts);
+ assertThat(installedCaCerts).isEqualTo(Collections.singletonList(alias));
ownerInstalledCaCerts.addAll(installedCaCerts);
});
// Restarting the DPMS should not lose information.
initializeDpms();
- runAsCaller(admin1Context, dpms, (dpm) ->
- assertEquals(ownerInstalledCaCerts, dpm.getOwnerInstalledCaCerts(callerUser)));
+ runAsCaller(admin1Context, dpms,
+ (dpm) -> assertThat(dpm.getOwnerInstalledCaCerts(callerUser))
+ .isEqualTo(ownerInstalledCaCerts));
// System can find out which CA certs were installed by the Device Owner / Profile Owner.
runAsCaller(serviceContext, dpms, (dpm) -> {
- assertEquals(ownerInstalledCaCerts, dpm.getOwnerInstalledCaCerts(callerUser));
+ assertThat(dpm.getOwnerInstalledCaCerts(callerUser)).isEqualTo(ownerInstalledCaCerts);
// Remove the CA cert.
reset(getServices().keyChainConnection.getService());
});
- getServices().injectBroadcast(mServiceContext, new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED)
- .putExtra(Intent.EXTRA_USER_HANDLE, callerUser.getIdentifier()),
+ getServices().injectBroadcast(mServiceContext,
+ new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED)
+ .putExtra(Intent.EXTRA_USER_HANDLE, callerUser.getIdentifier()),
callerUser.getIdentifier());
flushTasks(dpms);
@@ -5516,14 +5705,15 @@ public class DevicePolicyManagerTest extends DpmTestBase {
runAsCaller(callerContext, dpms, (dpm) -> {
when(getServices().keyChainConnection.getService().installCaCertificate(caCert))
.thenReturn(alias);
- assertTrue(dpm.installCaCert(callerName, caCert));
+ assertThat(dpm.installCaCert(callerName, caCert)).isTrue();
});
// Fake the CA cert as having been installed
when(getServices().keyChainConnection.getService().getUserCaAliases())
.thenReturn(asSlice(new String[] {alias}));
- getServices().injectBroadcast(mServiceContext, new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED)
- .putExtra(Intent.EXTRA_USER_HANDLE, callerUser.getIdentifier()),
+ getServices().injectBroadcast(mServiceContext,
+ new Intent(KeyChain.ACTION_TRUST_STORE_CHANGED)
+ .putExtra(Intent.EXTRA_USER_HANDLE, callerUser.getIdentifier()),
callerUser.getIdentifier());
flushTasks(dpms);
@@ -5532,8 +5722,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
runAsCaller(serviceContext, dpms, (dpm) -> {
final List<String> ownerInstalledCaCerts = dpm.getOwnerInstalledCaCerts(callerUser);
- assertNotNull(ownerInstalledCaCerts);
- assertTrue(ownerInstalledCaCerts.isEmpty());
+ assertThat(ownerInstalledCaCerts).isNotNull();
+ assertThat(ownerInstalledCaCerts.isEmpty()).isTrue();
});
}
@@ -5541,9 +5731,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
int[] gotFlags = DevicePolicyManagerService.translateIdAttestationFlags(attestationFlags);
Arrays.sort(gotFlags);
Arrays.sort(expectedFlags);
- assertTrue(Arrays.equals(expectedFlags, gotFlags));
+ assertThat(Arrays.equals(expectedFlags, gotFlags)).isTrue();
}
+ @Test
public void testTranslationOfIdAttestationFlag() {
int[] allIdTypes = new int[]{ID_TYPE_SERIAL, ID_TYPE_IMEI, ID_TYPE_MEID};
int[] correspondingAttUtilsTypes = new int[]{
@@ -5551,7 +5742,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
AttestationUtils.ID_TYPE_MEID};
// Test translation of zero flags
- assertNull(DevicePolicyManagerService.translateIdAttestationFlags(0));
+ assertThat(DevicePolicyManagerService.translateIdAttestationFlags(0)).isNull();
// Test translation of the ID_TYPE_BASE_INFO flag, which should yield an empty, but
// non-null array
@@ -5578,39 +5769,41 @@ public class DevicePolicyManagerTest extends DpmTestBase {
AttestationUtils.ID_TYPE_MEID});
}
+ @Test
public void testRevertDeviceOwnership_noMetadataFile() throws Exception {
setDeviceOwner();
initializeDpms();
- assertFalse(getMockTransferMetadataManager().metadataFileExists());
- assertTrue(dpms.isDeviceOwner(admin1, UserHandle.USER_SYSTEM));
- assertTrue(dpms.isAdminActive(admin1, UserHandle.USER_SYSTEM));
- }
-
- // @FlakyTest(bugId = 148934649)
- // public void testRevertDeviceOwnership_adminAndDeviceMigrated() throws Exception {
- // DpmTestUtils.writeInputStreamToFile(
- // getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
- // getDeviceOwnerPoliciesFile());
- // DpmTestUtils.writeInputStreamToFile(
- // getRawStream(com.android.frameworks.servicestests.R.raw.device_owner_migrated),
- // getDeviceOwnerFile());
- // assertDeviceOwnershipRevertedWithFakeTransferMetadata();
- // }
-
- // @FlakyTest(bugId = 148934649)
- // public void testRevertDeviceOwnership_deviceNotMigrated()
- // throws Exception {
- // DpmTestUtils.writeInputStreamToFile(
- // getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
- // getDeviceOwnerPoliciesFile());
- // DpmTestUtils.writeInputStreamToFile(
- // getRawStream(com.android.frameworks.servicestests.R.raw.device_owner_not_migrated),
- // getDeviceOwnerFile());
- // assertDeviceOwnershipRevertedWithFakeTransferMetadata();
- // }
-
- public void testRevertDeviceOwnership_adminAndDeviceNotMigrated()
- throws Exception {
+ assertThat(getMockTransferMetadataManager().metadataFileExists()).isFalse();
+ assertThat(dpms.isDeviceOwner(admin1, UserHandle.USER_SYSTEM)).isTrue();
+ assertThat(dpms.isAdminActive(admin1, UserHandle.USER_SYSTEM)).isTrue();
+ }
+
+ @FlakyTest(bugId = 148934649)
+ @Test
+ public void testRevertDeviceOwnership_adminAndDeviceMigrated() throws Exception {
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
+ getDeviceOwnerPoliciesFile());
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.device_owner_migrated),
+ getDeviceOwnerFile());
+ assertDeviceOwnershipRevertedWithFakeTransferMetadata();
+ }
+
+ @FlakyTest(bugId = 148934649)
+ @Test
+ public void testRevertDeviceOwnership_deviceNotMigrated() throws Exception {
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
+ getDeviceOwnerPoliciesFile());
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.device_owner_not_migrated),
+ getDeviceOwnerFile());
+ assertDeviceOwnershipRevertedWithFakeTransferMetadata();
+ }
+
+ @Test
+ public void testRevertDeviceOwnership_adminAndDeviceNotMigrated() throws Exception {
DpmTestUtils.writeInputStreamToFile(
getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_not_migrated),
getDeviceOwnerPoliciesFile());
@@ -5620,40 +5813,44 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertDeviceOwnershipRevertedWithFakeTransferMetadata();
}
+ @Test
public void testRevertProfileOwnership_noMetadataFile() throws Exception {
setupProfileOwner();
initializeDpms();
- assertFalse(getMockTransferMetadataManager().metadataFileExists());
- assertTrue(dpms.isProfileOwner(admin1, CALLER_USER_HANDLE));
- assertTrue(dpms.isAdminActive(admin1, CALLER_USER_HANDLE));
- }
-
- // @FlakyTest(bugId = 148934649)
- // public void testRevertProfileOwnership_adminAndProfileMigrated() throws Exception {
- // getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
- // UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
- // DpmTestUtils.writeInputStreamToFile(
- // getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
- // getProfileOwnerPoliciesFile());
- // DpmTestUtils.writeInputStreamToFile(
- // getRawStream(com.android.frameworks.servicestests.R.raw.profile_owner_migrated),
- // getProfileOwnerFile());
- // assertProfileOwnershipRevertedWithFakeTransferMetadata();
- // }
-
- // @FlakyTest(bugId = 148934649)
- // public void testRevertProfileOwnership_profileNotMigrated() throws Exception {
- // getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
- // UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
- // DpmTestUtils.writeInputStreamToFile(
- // getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
- // getProfileOwnerPoliciesFile());
- // DpmTestUtils.writeInputStreamToFile(
- // getRawStream(com.android.frameworks.servicestests.R.raw.profile_owner_not_migrated),
- // getProfileOwnerFile());
- // assertProfileOwnershipRevertedWithFakeTransferMetadata();
- // }
+ assertThat(getMockTransferMetadataManager().metadataFileExists()).isFalse();
+ assertThat(dpms.isProfileOwner(admin1, CALLER_USER_HANDLE)).isTrue();
+ assertThat(dpms.isAdminActive(admin1, CALLER_USER_HANDLE)).isTrue();
+ }
+
+ @FlakyTest(bugId = 148934649)
+ @Test
+ public void testRevertProfileOwnership_adminAndProfileMigrated() throws Exception {
+ getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
+ UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
+ getProfileOwnerPoliciesFile());
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.profile_owner_migrated),
+ getProfileOwnerFile());
+ assertProfileOwnershipRevertedWithFakeTransferMetadata();
+ }
+ @FlakyTest(bugId = 148934649)
+ @Test
+ public void testRevertProfileOwnership_profileNotMigrated() throws Exception {
+ getServices().addUser(DpmMockContext.CALLER_USER_HANDLE, 0,
+ UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.active_admin_migrated),
+ getProfileOwnerPoliciesFile());
+ DpmTestUtils.writeInputStreamToFile(
+ getRawStream(com.android.frameworks.servicestests.R.raw.profile_owner_not_migrated),
+ getProfileOwnerFile());
+ assertProfileOwnershipRevertedWithFakeTransferMetadata();
+ }
+
+ @Test
public void testRevertProfileOwnership_adminAndProfileNotMigrated() throws Exception {
getServices().addUser(CALLER_USER_HANDLE, 0,
UserManager.USER_TYPE_PROFILE_MANAGED, UserHandle.USER_SYSTEM);
@@ -5666,6 +5863,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertProfileOwnershipRevertedWithFakeTransferMetadata();
}
+ @Test
public void testGrantDeviceIdsAccess_notToProfileOwner() throws Exception {
setupProfileOwner();
configureContextForAccess(mContext, false);
@@ -5674,6 +5872,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
() -> dpm.markProfileOwnerOnOrganizationOwnedDevice(admin2));
}
+ @Test
public void testGrantDeviceIdsAccess_notByAuthorizedCaller() throws Exception {
setupProfileOwner();
configureContextForAccess(mContext, false);
@@ -5682,6 +5881,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
() -> dpm.markProfileOwnerOnOrganizationOwnedDevice(admin1));
}
+ @Test
public void testGrantDeviceIdsAccess_byAuthorizedSystemCaller() throws Exception {
setupProfileOwner();
@@ -5700,6 +5900,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.thenReturn(UserHandle.SYSTEM);
}
+ @Test
public void testGrantDeviceIdsAccess_byAuthorizedManagedProvisioning() throws Exception {
setupProfileOwner();
@@ -5719,6 +5920,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
}
+ @Test
public void testEnforceCallerCanRequestDeviceIdAttestation_deviceOwnerCaller()
throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
@@ -5741,6 +5943,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpms.getCallerIdentity(admin2)));
}
+ @Test
public void testEnforceCallerCanRequestDeviceIdAttestation_profileOwnerCaller()
throws Exception {
configureContextForAccess(mContext, false);
@@ -5781,6 +5984,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
}
+ @Test
public void testEnforceCallerCanRequestDeviceIdAttestation_delegateCaller() throws Exception {
setupProfileOwner();
markDelegatedCertInstallerAsInstalled();
@@ -5800,6 +6004,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpms.getCallerIdentity(null, DpmMockContext.DELEGATE_PACKAGE_NAME)));
}
+ @Test
public void testEnforceCallerCanRequestDeviceIdAttestation_delegateCallerWithoutPermissions()
throws Exception {
setupProfileOwner();
@@ -5821,6 +6026,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
});
}
+ @Test
public void testGetPasswordComplexity_securityExceptionNotThrownForParentInstance() {
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
when(getServices().packageManager.getPackagesForUid(DpmMockContext.CALLER_UID)).thenReturn(
@@ -5830,9 +6036,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
parentDpm.getPasswordComplexity();
- assertEquals(PASSWORD_COMPLEXITY_NONE, dpm.getPasswordComplexity());
+ assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_NONE);
}
+ @Test
public void testGetPasswordComplexity_illegalStateExceptionIfLocked() {
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
when(getServices().packageManager.getPackagesForUid(DpmMockContext.CALLER_UID)).thenReturn(
@@ -5841,6 +6048,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertThrows(IllegalStateException.class, () -> dpm.getPasswordComplexity());
}
+ @Test
public void testGetPasswordComplexity_securityExceptionWithoutPermissions() {
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
when(getServices().packageManager.getPackagesForUid(DpmMockContext.CALLER_UID)).thenReturn(
@@ -5850,6 +6058,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
+ @Test
public void testGetPasswordComplexity_currentUserNoPassword() {
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
when(getServices().packageManager.getPackagesForUid(DpmMockContext.CALLER_UID)).thenReturn(
@@ -5859,9 +6068,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
when(getServices().userManager.getCredentialOwnerProfile(CALLER_USER_HANDLE))
.thenReturn(CALLER_USER_HANDLE);
- assertEquals(PASSWORD_COMPLEXITY_NONE, dpm.getPasswordComplexity());
+ assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_NONE);
}
+ @Test
public void testGetPasswordComplexity_currentUserHasPassword() {
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
when(getServices().packageManager.getPackagesForUid(DpmMockContext.CALLER_UID)).thenReturn(
@@ -5874,9 +6084,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.getUserPasswordMetrics(CALLER_USER_HANDLE))
.thenReturn(computeForPassword("asdf".getBytes()));
- assertEquals(PASSWORD_COMPLEXITY_MEDIUM, dpm.getPasswordComplexity());
+ assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_MEDIUM);
}
+ @Test
public void testGetPasswordComplexity_unifiedChallengeReturnsParentUserPassword() {
mContext.binder.callingUid = DpmMockContext.CALLER_UID;
when(getServices().packageManager.getPackagesForUid(DpmMockContext.CALLER_UID)).thenReturn(
@@ -5896,23 +6107,25 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.getUserPasswordMetrics(parentUser.id))
.thenReturn(computeForPassword("parentUser".getBytes()));
- assertEquals(PASSWORD_COMPLEXITY_HIGH, dpm.getPasswordComplexity());
+ assertThat(dpm.getPasswordComplexity()).isEqualTo(PASSWORD_COMPLEXITY_HIGH);
}
+ @Test
public void testCrossProfileCalendarPackages_initiallyEmpty() {
setAsProfileOwner(admin1);
final Set<String> packages = dpm.getCrossProfileCalendarPackages(admin1);
assertCrossProfileCalendarPackagesEqual(packages, Collections.emptySet());
}
+ @Test
public void testCrossProfileCalendarPackages_reopenDpms() {
setAsProfileOwner(admin1);
dpm.setCrossProfileCalendarPackages(admin1, null);
Set<String> packages = dpm.getCrossProfileCalendarPackages(admin1);
- assertTrue(packages == null);
+ assertThat(packages == null).isTrue();
initializeDpms();
packages = dpm.getCrossProfileCalendarPackages(admin1);
- assertTrue(packages == null);
+ assertThat(packages == null).isTrue();
dpm.setCrossProfileCalendarPackages(admin1, Collections.emptySet());
packages = dpm.getCrossProfileCalendarPackages(admin1);
@@ -5932,21 +6145,22 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
private void assertCrossProfileCalendarPackagesEqual(Set<String> expected, Set<String> actual) {
- assertTrue(expected != null);
- assertTrue(actual != null);
- assertTrue(expected.containsAll(actual));
- assertTrue(actual.containsAll(expected));
+ assertThat(expected).isNotNull();
+ assertThat(actual).isNotNull();
+ assertThat(actual).containsExactlyElementsIn(expected);
}
+ @Test
public void testIsPackageAllowedToAccessCalendar_adminNotAllowed() {
setAsProfileOwner(admin1);
dpm.setCrossProfileCalendarPackages(admin1, Collections.emptySet());
when(getServices().settings.settingsSecureGetIntForUser(
Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED,
0, CALLER_USER_HANDLE)).thenReturn(1);
- assertFalse(dpm.isPackageAllowedToAccessCalendar("TEST_PACKAGE"));
+ assertThat(dpm.isPackageAllowedToAccessCalendar("TEST_PACKAGE")).isFalse();
}
+ @Test
public void testIsPackageAllowedToAccessCalendar_settingOff() {
final String testPackage = "TEST_PACKAGE";
setAsProfileOwner(admin1);
@@ -5954,9 +6168,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
when(getServices().settings.settingsSecureGetIntForUser(
Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED,
0, CALLER_USER_HANDLE)).thenReturn(0);
- assertFalse(dpm.isPackageAllowedToAccessCalendar(testPackage));
+ assertThat(dpm.isPackageAllowedToAccessCalendar(testPackage)).isFalse();
}
+ @Test
public void testIsPackageAllowedToAccessCalendar_bothAllowed() {
final String testPackage = "TEST_PACKAGE";
setAsProfileOwner(admin1);
@@ -5964,9 +6179,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
when(getServices().settings.settingsSecureGetIntForUser(
Settings.Secure.CROSS_PROFILE_CALENDAR_ENABLED,
0, CALLER_USER_HANDLE)).thenReturn(1);
- assertTrue(dpm.isPackageAllowedToAccessCalendar(testPackage));
+ assertThat(dpm.isPackageAllowedToAccessCalendar(testPackage)).isTrue();
}
+ @Test
public void testSetUserControlDisabledPackages_asDO() throws Exception {
final List<String> testPackages = new ArrayList<>();
testPackages.add("package_1");
@@ -5979,9 +6195,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
verify(getServices().packageManagerInternal).setDeviceOwnerProtectedPackages(testPackages);
- assertEquals(testPackages, dpm.getUserControlDisabledPackages(admin1));
+ assertThat(dpm.getUserControlDisabledPackages(admin1)).isEqualTo(testPackages);
}
+ @Test
public void testSetUserControlDisabledPackages_failingAsPO() throws Exception {
final List<String> testPackages = new ArrayList<>();
testPackages.add("package_1");
@@ -6008,28 +6225,32 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mServiceContext.binder.restoreCallingIdentity(ident);
}
+ @Test
public void testGetCrossProfilePackages_notSet_returnsEmpty() {
setAsProfileOwner(admin1);
- assertTrue(dpm.getCrossProfilePackages(admin1).isEmpty());
+ assertThat(dpm.getCrossProfilePackages(admin1).isEmpty()).isTrue();
}
+ @Test
public void testGetCrossProfilePackages_notSet_dpmsReinitialized_returnsEmpty() {
setAsProfileOwner(admin1);
initializeDpms();
- assertTrue(dpm.getCrossProfilePackages(admin1).isEmpty());
+ assertThat(dpm.getCrossProfilePackages(admin1).isEmpty()).isTrue();
}
+ @Test
public void testGetCrossProfilePackages_whenSet_returnsEqual() {
setAsProfileOwner(admin1);
Set<String> packages = Collections.singleton("TEST_PACKAGE");
dpm.setCrossProfilePackages(admin1, packages);
- assertEquals(packages, dpm.getCrossProfilePackages(admin1));
+ assertThat(dpm.getCrossProfilePackages(admin1)).isEqualTo(packages);
}
+ @Test
public void testGetCrossProfilePackages_whenSet_dpmsReinitialized_returnsEqual() {
setAsProfileOwner(admin1);
Set<String> packages = Collections.singleton("TEST_PACKAGE");
@@ -6037,9 +6258,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
dpm.setCrossProfilePackages(admin1, packages);
initializeDpms();
- assertEquals(packages, dpm.getCrossProfilePackages(admin1));
+ assertThat(dpm.getCrossProfilePackages(admin1)).isEqualTo(packages);
}
+ @Test
public void testGetAllCrossProfilePackages_notSet_returnsEmpty() throws Exception {
addManagedProfile(admin1, mServiceContext.binder.callingUid, admin1);
mContext.packageName = admin1.getPackageName();
@@ -6047,9 +6269,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setCrossProfileAppsList();
setVendorCrossProfileAppsList();
- assertTrue(dpm.getAllCrossProfilePackages().isEmpty());
+ assertThat(dpm.getAllCrossProfilePackages().isEmpty()).isTrue();
}
+ @Test
public void testGetAllCrossProfilePackages_notSet_dpmsReinitialized_returnsEmpty()
throws Exception {
addManagedProfile(admin1, mServiceContext.binder.callingUid, admin1);
@@ -6059,9 +6282,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setVendorCrossProfileAppsList();
initializeDpms();
- assertTrue(dpm.getAllCrossProfilePackages().isEmpty());
+ assertThat(dpm.getAllCrossProfilePackages().isEmpty()).isTrue();
}
+ @Test
public void testGetAllCrossProfilePackages_whenSet_returnsCombinedSet() throws Exception {
addManagedProfile(admin1, mServiceContext.binder.callingUid, admin1);
final Set<String> packages = Sets.newSet("TEST_PACKAGE", "TEST_COMMON_PACKAGE");
@@ -6071,13 +6295,12 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setCrossProfileAppsList("TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE");
setVendorCrossProfileAppsList("TEST_VENDOR_DEFAULT_PACKAGE");
- assertEquals(Sets.newSet(
- "TEST_PACKAGE", "TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE",
- "TEST_VENDOR_DEFAULT_PACKAGE"),
- dpm.getAllCrossProfilePackages());
-
+ assertThat(dpm.getAllCrossProfilePackages()).containsExactly(
+ "TEST_PACKAGE", "TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE",
+ "TEST_VENDOR_DEFAULT_PACKAGE");
}
+ @Test
public void testGetAllCrossProfilePackages_whenSet_dpmsReinitialized_returnsCombinedSet()
throws Exception {
addManagedProfile(admin1, mServiceContext.binder.callingUid, admin1);
@@ -6089,12 +6312,12 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setVendorCrossProfileAppsList("TEST_VENDOR_DEFAULT_PACKAGE");
initializeDpms();
- assertEquals(Sets.newSet(
+ assertThat(dpm.getAllCrossProfilePackages()).containsExactly(
"TEST_PACKAGE", "TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE",
- "TEST_VENDOR_DEFAULT_PACKAGE"),
- dpm.getAllCrossProfilePackages());
+ "TEST_VENDOR_DEFAULT_PACKAGE");
}
+ @Test
public void testGetDefaultCrossProfilePackages_noPackagesSet_returnsEmpty() {
setCrossProfileAppsList();
setVendorCrossProfileAppsList();
@@ -6102,27 +6325,29 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertThat(dpm.getDefaultCrossProfilePackages()).isEmpty();
}
+ @Test
public void testGetDefaultCrossProfilePackages_packagesSet_returnsCombinedSet() {
setCrossProfileAppsList("TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE");
setVendorCrossProfileAppsList("TEST_VENDOR_DEFAULT_PACKAGE");
- assertThat(dpm.getDefaultCrossProfilePackages()).isEqualTo(Sets.newSet(
- "TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE", "TEST_VENDOR_DEFAULT_PACKAGE"
- ));
+ assertThat(dpm.getDefaultCrossProfilePackages()).containsExactly(
+ "TEST_DEFAULT_PACKAGE", "TEST_COMMON_PACKAGE", "TEST_VENDOR_DEFAULT_PACKAGE");
}
+ @Test
public void testSetCommonCriteriaMode_asDeviceOwner() throws Exception {
setDeviceOwner();
- assertFalse(dpm.isCommonCriteriaModeEnabled(admin1));
- assertFalse(dpm.isCommonCriteriaModeEnabled(null));
+ assertThat(dpm.isCommonCriteriaModeEnabled(admin1)).isFalse();
+ assertThat(dpm.isCommonCriteriaModeEnabled(null)).isFalse();
dpm.setCommonCriteriaModeEnabled(admin1, true);
- assertTrue(dpm.isCommonCriteriaModeEnabled(admin1));
- assertTrue(dpm.isCommonCriteriaModeEnabled(null));
+ assertThat(dpm.isCommonCriteriaModeEnabled(admin1)).isTrue();
+ assertThat(dpm.isCommonCriteriaModeEnabled(null)).isTrue();
}
+ @Test
public void testSetCommonCriteriaMode_asPoOfOrgOwnedDevice() throws Exception {
final int managedProfileUserId = 15;
final int managedProfileAdminUid = UserHandle.getUid(managedProfileUserId, 19436);
@@ -6130,15 +6355,16 @@ public class DevicePolicyManagerTest extends DpmTestBase {
configureProfileOwnerOfOrgOwnedDevice(admin1, managedProfileUserId);
mContext.binder.callingUid = managedProfileAdminUid;
- assertFalse(dpm.isCommonCriteriaModeEnabled(admin1));
- assertFalse(dpm.isCommonCriteriaModeEnabled(null));
+ assertThat(dpm.isCommonCriteriaModeEnabled(admin1)).isFalse();
+ assertThat(dpm.isCommonCriteriaModeEnabled(null)).isFalse();
dpm.setCommonCriteriaModeEnabled(admin1, true);
- assertTrue(dpm.isCommonCriteriaModeEnabled(admin1));
- assertTrue(dpm.isCommonCriteriaModeEnabled(null));
+ assertThat(dpm.isCommonCriteriaModeEnabled(admin1)).isTrue();
+ assertThat(dpm.isCommonCriteriaModeEnabled(null)).isTrue();
}
+ @Test
public void testCanProfileOwnerResetPasswordWhenLocked_nonDirectBootAwarePo()
throws Exception {
setDeviceEncryptionPerUser();
@@ -6146,30 +6372,33 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setupPasswordResetToken();
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertFalse("po is not direct boot aware",
- dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE));
+ assertWithMessage("po is not direct boot aware")
+ .that(dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE)).isFalse();
}
+ @Test
public void testCanProfileOwnerResetPasswordWhenLocked_noActiveToken() throws Exception {
setDeviceEncryptionPerUser();
setupProfileOwner();
makeAdmin1DirectBootAware();
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertFalse("po doesn't have an active password reset token",
- dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE));
+ assertWithMessage("po doesn't have an active password reset token")
+ .that(dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE)).isFalse();
}
+ @Test
public void testCanProfileOwnerResetPasswordWhenLocked_nonFbeDevice() throws Exception {
setupProfileOwner();
makeAdmin1DirectBootAware();
setupPasswordResetToken();
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertFalse("device is not FBE",
- dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE));
+ assertWithMessage("device is not FBE")
+ .that(dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE)).isFalse();
}
+ @Test
public void testCanProfileOwnerResetPasswordWhenLocked() throws Exception {
setDeviceEncryptionPerUser();
setupProfileOwner();
@@ -6177,8 +6406,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
setupPasswordResetToken();
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
- assertTrue("direct boot aware po with active password reset token",
- dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE));
+ assertWithMessage("direct boot aware po with active password reset token")
+ .that(dpm.canProfileOwnerResetPasswordWhenLocked(CALLER_USER_HANDLE)).isTrue();
}
private void setupPasswordResetToken() {
@@ -6196,7 +6425,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.isEscrowTokenActive(eq(handle), eq(CALLER_USER_HANDLE)))
.thenReturn(true);
- assertTrue("failed to activate token", dpm.isResetPasswordTokenActive(admin1));
+ assertWithMessage("failed to activate token").that(dpm.isResetPasswordTokenActive(admin1))
+ .isTrue();
}
private void makeAdmin1DirectBootAware()
@@ -6231,6 +6461,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
.thenReturn(packages);
}
+ @Test
public void testSetAccountTypesWithManagementDisabledOnManagedProfile() throws Exception {
setupProfileOwner();
@@ -6249,6 +6480,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertThat(dpm.getAccountTypesWithManagementDisabled()).isEmpty();
}
+ @Test
public void testSetAccountTypesWithManagementDisabledOnOrgOwnedManagedProfile()
throws Exception {
final int managedProfileUserId = 15;
@@ -6284,6 +6516,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
* Tests the case when the user doesn't turn the profile on in time, verifies that the user is
* warned with a notification and then the apps get suspended.
*/
+ @Test
public void testMaximumProfileTimeOff_profileOffTimeExceeded() throws Exception {
prepareMocksForSetMaximumProfileTimeOff();
@@ -6346,6 +6579,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
/**
* Tests the case when the user turns the profile back on long before the deadline (> 1 day).
*/
+ @Test
public void testMaximumProfileTimeOff_turnOnBeforeWarning() throws Exception {
prepareMocksForSetMaximumProfileTimeOff();
@@ -6366,6 +6600,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
/**
* Tests the case when the user turns the profile back on after the warning notification.
*/
+ @Test
public void testMaximumProfileTimeOff_turnOnAfterWarning() throws Exception {
prepareMocksForSetMaximumProfileTimeOff();
@@ -6395,6 +6630,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
/**
* Tests the case when the user turns the profile back on when the apps are already suspended.
*/
+ @Test
public void testMaximumProfileTimeOff_turnOnAfterDeadline() throws Exception {
prepareMocksForSetMaximumProfileTimeOff();
@@ -6482,7 +6718,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
private static Matcher<Notification> hasExtra(String... extras) {
- assertEquals("Odd number of extra key-values", 0, extras.length % 2);
+ assertWithMessage("Odd number of extra key-values").that(extras.length % 2).isEqualTo(0);
return new BaseMatcher<Notification>() {
@Override
public boolean matches(Object item) {
@@ -6520,17 +6756,17 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// To simulate a reboot, we just reinitialize dpms and call systemReady
initializeDpms();
- assertTrue(dpm.isDeviceOwnerApp(admin1.getPackageName()));
- assertFalse(dpm.isDeviceOwnerApp(adminAnotherPackage.getPackageName()));
- assertFalse(dpm.isAdminActive(adminAnotherPackage));
- assertTrue(dpm.isAdminActive(admin1));
- assertTrue(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName()));
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnCallingUser());
+ assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isTrue();
+ assertThat(dpm.isDeviceOwnerApp(adminAnotherPackage.getPackageName())).isFalse();
+ assertThat(dpm.isAdminActive(adminAnotherPackage)).isFalse();
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
+ assertThat(dpm.isDeviceOwnerAppOnCallingUser(admin1.getPackageName())).isTrue();
+ assertThat(dpm.getDeviceOwnerComponentOnCallingUser()).isEqualTo(admin1);
- assertTrue(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName()));
- assertEquals(admin1, dpm.getDeviceOwnerComponentOnAnyUser());
- assertEquals(UserHandle.USER_SYSTEM, dpm.getDeviceOwnerUserId());
- assertFalse(getMockTransferMetadataManager().metadataFileExists());
+ assertThat(dpm.isDeviceOwnerAppOnAnyUser(admin1.getPackageName())).isTrue();
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isEqualTo(admin1);
+ assertThat(dpm.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
+ assertThat(getMockTransferMetadataManager().metadataFileExists()).isFalse();
mServiceContext.binder.restoreCallingIdentity(ident);
}
@@ -6547,12 +6783,12 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// To simulate a reboot, we just reinitialize dpms and call systemReady
initializeDpms();
- assertTrue(dpm.isProfileOwnerApp(admin1.getPackageName()));
- assertTrue(dpm.isAdminActive(admin1));
- assertFalse(dpm.isProfileOwnerApp(adminAnotherPackage.getPackageName()));
- assertFalse(dpm.isAdminActive(adminAnotherPackage));
- assertEquals(dpm.getProfileOwnerAsUser(CALLER_USER_HANDLE), admin1);
- assertFalse(getMockTransferMetadataManager().metadataFileExists());
+ assertThat(dpm.isProfileOwnerApp(admin1.getPackageName())).isTrue();
+ assertThat(dpm.isAdminActive(admin1)).isTrue();
+ assertThat(dpm.isProfileOwnerApp(adminAnotherPackage.getPackageName())).isFalse();
+ assertThat(dpm.isAdminActive(adminAnotherPackage)).isFalse();
+ assertThat(admin1).isEqualTo(dpm.getProfileOwnerAsUser(CALLER_USER_HANDLE));
+ assertThat(getMockTransferMetadataManager().metadataFileExists()).isFalse();
}
private void writeFakeTransferMetadataFile(int callerUserHandle, String adminType) {
@@ -6597,8 +6833,8 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
private void assertProvisioningAllowed(String action, boolean expected) {
- assertEquals("isProvisioningAllowed(" + action + ") returning unexpected result", expected,
- dpm.isProvisioningAllowed(action));
+ assertWithMessage("isProvisioningAllowed(%s) returning unexpected result", action)
+ .that(dpm.isProvisioningAllowed(action)).isEqualTo(expected);
}
private void assertProvisioningAllowed(String action, boolean expected, String packageName,
@@ -6622,9 +6858,9 @@ public class DevicePolicyManagerTest extends DpmTestBase {
private void assertCheckProvisioningPreCondition(
String action, String packageName, int provisioningCondition) {
- assertEquals("checkProvisioningPreCondition("
- + action + ", " + packageName + ") returning unexpected result",
- provisioningCondition, dpm.checkProvisioningPreCondition(action, packageName));
+ assertWithMessage("checkProvisioningPreCondition(%s, %s) returning unexpected result",
+ action, packageName).that(dpm.checkProvisioningPreCondition(action, packageName))
+ .isEqualTo(provisioningCondition);
}
/**
@@ -6642,7 +6878,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
mContext.callerPermissions.addAll(OWNER_SETUP_PERMISSIONS);
setUpPackageManagerForFakeAdmin(admin, adminUid, copyFromAdmin);
dpm.setActiveAdmin(admin, false, userId);
- assertTrue(dpm.setProfileOwner(admin, null, userId));
+ assertThat(dpm.setProfileOwner(admin, null, userId)).isTrue();
mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
index 41d54e9010d3..81570a10fc13 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DpmTestBase.java
@@ -16,6 +16,8 @@
package com.android.server.devicepolicy;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
@@ -35,18 +37,28 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.UserHandle;
-import android.test.AndroidTestCase;
+
+import androidx.test.InstrumentationRegistry;
+
+import org.junit.Before;
import java.io.InputStream;
import java.util.List;
-public abstract class DpmTestBase extends AndroidTestCase {
+/**
+ * Temporary copy of DpmTestBase using JUnit 4 - once all tests extend it, it should be renamed
+ * back to DpmTestBase (with the temporary methods removed.
+ *
+ */
+public abstract class DpmTestBase {
+
public static final String TAG = "DpmTest";
- protected Context mRealTestContext;
+ protected final Context mRealTestContext = InstrumentationRegistry.getTargetContext();
protected DpmMockContext mMockContext;
private MockSystemServices mServices;
+ // Attributes below are public so they don't need to be prefixed with m
public ComponentName admin1;
public ComponentName admin2;
public ComponentName admin3;
@@ -54,12 +66,8 @@ public abstract class DpmTestBase extends AndroidTestCase {
public ComponentName adminNoPerm;
public ComponentName delegateCertInstaller;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
-
- mRealTestContext = super.getContext();
-
+ @Before
+ public void setFixtures() throws Exception {
mServices = new MockSystemServices(mRealTestContext, "test-data");
mMockContext = new DpmMockContext(mServices, mRealTestContext);
@@ -74,8 +82,7 @@ public abstract class DpmTestBase extends AndroidTestCase {
mockSystemPropertiesToReturnDefault();
}
- @Override
- public DpmMockContext getContext() {
+ protected DpmMockContext getContext() {
return mMockContext;
}
@@ -136,20 +143,15 @@ public abstract class DpmTestBase extends AndroidTestCase {
final PackageInfo pi = DpmTestUtils.cloneParcelable(
mRealTestContext.getPackageManager().getPackageInfo(
mRealTestContext.getPackageName(), 0));
- assertTrue(pi.applicationInfo.flags != 0);
+ assertThat(pi.applicationInfo.flags).isNotEqualTo(0);
if (ai != null) {
pi.applicationInfo = ai;
}
- doReturn(pi).when(mServices.ipackageManager).getPackageInfo(
- eq(packageName),
- eq(0),
- eq(userId));
+ doReturn(pi).when(mServices.ipackageManager).getPackageInfo(packageName, 0, userId);
- doReturn(ai.uid).when(mServices.packageManager).getPackageUidAsUser(
- eq(packageName),
- eq(userId));
+ doReturn(ai.uid).when(mServices.packageManager).getPackageUidAsUser(packageName, userId);
}
protected void markDelegatedCertInstallerAsInstalled() throws Exception {
@@ -230,8 +232,8 @@ public abstract class DpmTestBase extends AndroidTestCase {
mRealTestContext.getPackageManager().queryBroadcastReceivers(
resolveIntent,
PackageManager.GET_META_DATA);
- assertNotNull(realResolveInfo);
- assertEquals(1, realResolveInfo.size());
+ assertThat(realResolveInfo).isNotNull();
+ assertThat(realResolveInfo).hasSize(1);
// We need to change AI, so set a clone.
realResolveInfo.set(0, DpmTestUtils.cloneParcelable(realResolveInfo.get(0)));
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/FactoryResetProtectionPolicyTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/FactoryResetProtectionPolicyTest.java
index e8818a3f4940..3aa5a80d814f 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/FactoryResetProtectionPolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/FactoryResetProtectionPolicyTest.java
@@ -16,8 +16,8 @@
package com.android.server.devicepolicy;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -100,7 +100,7 @@ public class FactoryResetProtectionPolicyTest {
ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new InputStreamReader(inStream));
- assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertThat(parser.next()).isEqualTo(XmlPullParser.START_TAG);
assertPoliciesAreEqual(policy, policy.readFromXml(parser));
}
@@ -114,7 +114,7 @@ public class FactoryResetProtectionPolicyTest {
parser.setInput(new InputStreamReader(inStream));
// If deserialization fails, then null is returned.
- assertNull(policy.readFromXml(parser));
+ assertThat(policy.readFromXml(parser)).isNull();
}
private ByteArrayOutputStream serialize(FactoryResetProtectionPolicy policy)
@@ -133,17 +133,17 @@ public class FactoryResetProtectionPolicyTest {
private void assertPoliciesAreEqual(FactoryResetProtectionPolicy expectedPolicy,
FactoryResetProtectionPolicy actualPolicy) {
- assertEquals(expectedPolicy.isFactoryResetProtectionEnabled(),
- actualPolicy.isFactoryResetProtectionEnabled());
+ assertThat(actualPolicy.isFactoryResetProtectionEnabled())
+ .isEqualTo(expectedPolicy.isFactoryResetProtectionEnabled());
assertAccountsAreEqual(expectedPolicy.getFactoryResetProtectionAccounts(),
actualPolicy.getFactoryResetProtectionAccounts());
}
private void assertAccountsAreEqual(List<String> expectedAccounts,
List<String> actualAccounts) {
- assertEquals(expectedAccounts.size(), actualAccounts.size());
+ assertThat(actualAccounts.size()).isEqualTo(expectedAccounts.size());
for (int i = 0; i < expectedAccounts.size(); i++) {
- assertEquals(expectedAccounts.get(i), actualAccounts.get(i));
+ assertThat(actualAccounts.get(i)).isEqualTo(expectedAccounts.get(i));
}
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
index c698312eedec..7506dd45ad82 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/NetworkEventTest.java
@@ -17,6 +17,9 @@ package com.android.server.devicepolicy;
import static com.android.server.devicepolicy.NetworkLoggingHandler.LOG_NETWORK_EVENT_MSG;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.spy;
@@ -37,8 +40,9 @@ import android.os.test.TestLooper;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.server.LocalServices;
-import com.android.server.SystemService;
+import org.junit.Before;
+import org.junit.Test;
import org.mockito.ArgumentCaptor;
import java.util.List;
@@ -50,9 +54,8 @@ public class NetworkEventTest extends DpmTestBase {
private DpmMockContext mSpiedDpmMockContext;
private DevicePolicyManagerServiceTestable mDpmTestable;
- @Override
- protected void setUp() throws Exception {
- super.setUp();
+ @Before
+ public void setUp() throws Exception {
mSpiedDpmMockContext = spy(mMockContext);
mSpiedDpmMockContext.callerPermissions.add(
android.Manifest.permission.MANAGE_DEVICE_ADMINS);
@@ -64,6 +67,7 @@ public class NetworkEventTest extends DpmTestBase {
mDpmTestable.setActiveAdmin(admin1, true, DpmMockContext.CALLER_USER_HANDLE);
}
+ @Test
public void testNetworkEventId_monotonicallyIncreasing() throws Exception {
// GIVEN the handler has not processed any events.
long startingId = 0;
@@ -72,17 +76,20 @@ public class NetworkEventTest extends DpmTestBase {
List<NetworkEvent> events = fillHandlerWithFullBatchOfEvents(startingId);
// THEN the events are in a batch.
- assertTrue("Batch not at the returned token.",
- events != null && events.size() == MAX_EVENTS_PER_BATCH);
+ assertWithMessage("Batch not at the returned token.").that(events).isNotNull();
+ assertWithMessage("Batch not at the returned token.").that(events)
+ .hasSize(MAX_EVENTS_PER_BATCH);
+
// THEN event ids are monotonically increasing.
long expectedId = startingId;
for (int i = 0; i < MAX_EVENTS_PER_BATCH; i++) {
- assertEquals("At index " + i + ", the event has the wrong id.", expectedId,
- events.get(i).getId());
+ assertWithMessage("At index %s, the event has the wrong id.", i)
+ .that(events.get(i).getId()).isEqualTo(expectedId);
expectedId++;
}
}
+ @Test
public void testNetworkEventId_wrapsAround() throws Exception {
// GIVEN the handler has almost processed Long.MAX_VALUE events.
int gap = 5;
@@ -92,24 +99,25 @@ public class NetworkEventTest extends DpmTestBase {
List<NetworkEvent> events = fillHandlerWithFullBatchOfEvents(startingId);
// THEN the events are in a batch.
- assertTrue("Batch not at the returned token.",
- events != null && events.size() == MAX_EVENTS_PER_BATCH);
+ assertWithMessage("Batch not at the returned token.").that(events).isNotNull();
+ assertWithMessage("Batch not at the returned token.").that(events)
+ .hasSize(MAX_EVENTS_PER_BATCH);
// THEN event ids are monotonically increasing.
long expectedId = startingId;
for (int i = 0; i < gap; i++) {
- assertEquals("At index " + i + ", the event has the wrong id.", expectedId,
- events.get(i).getId());
+ assertWithMessage("At index %s, the event has the wrong id.", i)
+ .that(events.get(i).getId()).isEqualTo(expectedId);
expectedId++;
}
// THEN event ids are reset when the id reaches the maximum possible value.
- assertEquals("Event was not assigned the maximum id value.", Long.MAX_VALUE,
- events.get(gap).getId());
- assertEquals("Event id was not reset.", 0, events.get(gap + 1).getId());
+ assertWithMessage("Event was not assigned the maximum id value.")
+ .that(events.get(gap).getId()).isEqualTo(Long.MAX_VALUE);
+ assertWithMessage("Event id was not reset.").that(events.get(gap + 1).getId()).isEqualTo(0);
// THEN event ids are monotonically increasing.
expectedId = 0;
for (int i = gap + 1; i < MAX_EVENTS_PER_BATCH; i++) {
- assertEquals("At index " + i + ", the event has the wrong id.", expectedId,
- events.get(i).getId());
+ assertWithMessage("At index %s, the event has the wrong id.", i)
+ .that(events.get(i).getId()).isEqualTo(expectedId);
expectedId++;
}
}
@@ -134,8 +142,8 @@ public class NetworkEventTest extends DpmTestBase {
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
verify(mSpiedDpmMockContext).sendBroadcastAsUser(intentCaptor.capture(),
any(UserHandle.class));
- assertEquals(intentCaptor.getValue().getAction(),
- DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE);
+ assertThat(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE)
+ .isEqualTo(intentCaptor.getValue().getAction());
long token = intentCaptor.getValue().getExtras().getLong(
DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, 0);
return handler.retrieveFullLogBatch(token);
@@ -144,6 +152,7 @@ public class NetworkEventTest extends DpmTestBase {
/**
* Test parceling and unparceling of a ConnectEvent.
*/
+ @Test
public void testConnectEventParceling() {
ConnectEvent event = new ConnectEvent("127.0.0.1", 80, "com.android.whateverdude", 100000);
event.setId(5L);
@@ -152,16 +161,17 @@ public class NetworkEventTest extends DpmTestBase {
p.setDataPosition(0);
ConnectEvent unparceledEvent = p.readParcelable(NetworkEventTest.class.getClassLoader());
p.recycle();
- assertEquals(event.getInetAddress(), unparceledEvent.getInetAddress());
- assertEquals(event.getPort(), unparceledEvent.getPort());
- assertEquals(event.getPackageName(), unparceledEvent.getPackageName());
- assertEquals(event.getTimestamp(), unparceledEvent.getTimestamp());
- assertEquals(event.getId(), unparceledEvent.getId());
+ assertThat(unparceledEvent.getInetAddress()).isEqualTo(event.getInetAddress());
+ assertThat(unparceledEvent.getPort()).isEqualTo(event.getPort());
+ assertThat(unparceledEvent.getPackageName()).isEqualTo(event.getPackageName());
+ assertThat(unparceledEvent.getTimestamp()).isEqualTo(event.getTimestamp());
+ assertThat(unparceledEvent.getId()).isEqualTo(event.getId());
}
/**
* Test parceling and unparceling of a DnsEvent.
*/
+ @Test
public void testDnsEventParceling() {
DnsEvent event = new DnsEvent("d.android.com", new String[]{"192.168.0.1", "127.0.0.1"}, 2,
"com.android.whateverdude", 100000);
@@ -171,13 +181,15 @@ public class NetworkEventTest extends DpmTestBase {
p.setDataPosition(0);
DnsEvent unparceledEvent = p.readParcelable(NetworkEventTest.class.getClassLoader());
p.recycle();
- assertEquals(event.getHostname(), unparceledEvent.getHostname());
- assertEquals(event.getInetAddresses().get(0), unparceledEvent.getInetAddresses().get(0));
- assertEquals(event.getInetAddresses().get(1), unparceledEvent.getInetAddresses().get(1));
- assertEquals(event.getTotalResolvedAddressCount(),
- unparceledEvent.getTotalResolvedAddressCount());
- assertEquals(event.getPackageName(), unparceledEvent.getPackageName());
- assertEquals(event.getTimestamp(), unparceledEvent.getTimestamp());
- assertEquals(event.getId(), unparceledEvent.getId());
+ assertThat(unparceledEvent.getHostname()).isEqualTo(event.getHostname());
+ assertThat(unparceledEvent.getInetAddresses().get(0))
+ .isEqualTo(event.getInetAddresses().get(0));
+ assertThat(unparceledEvent.getInetAddresses().get(1))
+ .isEqualTo(event.getInetAddresses().get(1));
+ assertThat(unparceledEvent.getTotalResolvedAddressCount())
+ .isEqualTo(event.getTotalResolvedAddressCount());
+ assertThat(unparceledEvent.getPackageName()).isEqualTo(event.getPackageName());
+ assertThat(unparceledEvent.getTimestamp()).isEqualTo(event.getTimestamp());
+ assertThat(unparceledEvent.getId()).isEqualTo(event.getId());
}
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
index a3cc915b3eba..24e226a64917 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
@@ -20,6 +20,9 @@ import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEV
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE;
import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
@@ -32,16 +35,17 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
-import android.test.AndroidTestCase;
import android.test.mock.MockPackageManager;
import android.view.inputmethod.InputMethodInfo;
import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
import com.android.internal.R;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -51,18 +55,23 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
-public class OverlayPackagesProviderTest extends AndroidTestCase {
+/**
+ * Run this test with:
+ *
+ * {@code atest FrameworksServicesTests:com.android.server.devicepolicy.OwnersTest}
+ *
+ */
+@RunWith(AndroidJUnit4.class)
+public class OverlayPackagesProviderTest {
private static final String TEST_DPC_PACKAGE_NAME = "dpc.package.name";
private static final ComponentName TEST_MDM_COMPONENT_NAME = new ComponentName(
TEST_DPC_PACKAGE_NAME, "pc.package.name.DeviceAdmin");
private static final int TEST_USER_ID = 123;
- private @Mock
- Resources mResources;
- @Mock
- private OverlayPackagesProvider.Injector mInjector;
- private @Mock
- Context mTestContext;
+ private @Mock Resources mResources;
+
+ private @Mock OverlayPackagesProvider.Injector mInjector;
+ private @Mock Context mTestContext;
private Resources mRealResources;
private FakePackageManager mPackageManager;
@@ -256,12 +265,12 @@ public class OverlayPackagesProviderTest extends AndroidTestCase {
ArrayList<String> required = getStringArrayInRealResources(requiredId);
ArrayList<String> disallowed = getStringArrayInRealResources(disallowedId);
required.retainAll(disallowed);
- assertTrue(required.isEmpty());
+ assertThat(required.isEmpty()).isTrue();
}
private void verifyAppsAreNonRequired(String action, String... appArray) {
- assertEquals(setFromArray(appArray),
- mHelper.getNonRequiredApps(TEST_MDM_COMPONENT_NAME, TEST_USER_ID, action));
+ assertThat(mHelper.getNonRequiredApps(TEST_MDM_COMPONENT_NAME, TEST_USER_ID, action))
+ .containsExactlyElementsIn(setFromArray(appArray));
}
private void setRequiredAppsManagedDevice(String... apps) {
@@ -348,19 +357,19 @@ public class OverlayPackagesProviderTest extends AndroidTestCase {
class FakePackageManager extends MockPackageManager {
@Override
public List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) {
- assertTrue("Expected an intent with action ACTION_MAIN",
- Intent.ACTION_MAIN.equals(intent.getAction()));
- assertEquals("Expected an intent with category CATEGORY_LAUNCHER",
- setFromArray(Intent.CATEGORY_LAUNCHER), intent.getCategories());
- assertTrue("Expected the flag MATCH_UNINSTALLED_PACKAGES",
- (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0);
- assertTrue("Expected the flag MATCH_DISABLED_COMPONENTS",
- (flags & PackageManager.MATCH_DISABLED_COMPONENTS) != 0);
- assertTrue("Expected the flag MATCH_DIRECT_BOOT_AWARE",
- (flags & PackageManager.MATCH_DIRECT_BOOT_AWARE) != 0);
- assertTrue("Expected the flag MATCH_DIRECT_BOOT_UNAWARE",
- (flags & PackageManager.MATCH_DIRECT_BOOT_UNAWARE) != 0);
- assertEquals(userId, TEST_USER_ID);
+ assertWithMessage("Expected an intent with action ACTION_MAIN")
+ .that(Intent.ACTION_MAIN.equals(intent.getAction())).isTrue();
+ assertWithMessage("Expected an intent with category CATEGORY_LAUNCHER")
+ .that(intent.getCategories()).containsExactly(Intent.CATEGORY_LAUNCHER);
+ assertWithMessage("Expected the flag MATCH_UNINSTALLED_PACKAGES")
+ .that((flags & PackageManager.MATCH_UNINSTALLED_PACKAGES)).isNotEqualTo(0);
+ assertWithMessage("Expected the flag MATCH_DISABLED_COMPONENTS")
+ .that((flags & PackageManager.MATCH_DISABLED_COMPONENTS)).isNotEqualTo(0);
+ assertWithMessage("Expected the flag MATCH_DIRECT_BOOT_AWARE")
+ .that((flags & PackageManager.MATCH_DIRECT_BOOT_AWARE)).isNotEqualTo(0);
+ assertWithMessage("Expected the flag MATCH_DIRECT_BOOT_UNAWARE")
+ .that((flags & PackageManager.MATCH_DIRECT_BOOT_UNAWARE)).isNotEqualTo(0);
+ assertThat(TEST_USER_ID).isEqualTo(userId);
List<ResolveInfo> result = new ArrayList<>();
if (mSystemAppsWithLauncher == null) {
return result;
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
index 5899bb0e94fe..bfe183cc608b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OwnersTest.java
@@ -16,25 +16,32 @@
package com.android.server.devicepolicy;
+import static com.google.common.truth.Truth.assertThat;
+
import android.content.ComponentName;
import android.os.UserHandle;
import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
import com.android.server.devicepolicy.DevicePolicyManagerServiceTestable.OwnersTestable;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
/**
* Tests for the DeviceOwner object that saves & loads device and policy owner information.
- * run this test with:
- m FrameworksServicesTests &&
- adb install \
- -r out/target/product/hammerhead/data/app/FrameworksServicesTests/FrameworksServicesTests.apk &&
- adb shell am instrument -e class com.android.server.devicepolicy.OwnersTest \
- -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
-
- (mmma frameworks/base/services/tests/servicestests/ for non-ninja build)
+ *
+ * <p>Run this test with:
+ *
+ * {@code atest FrameworksServicesTests:com.android.server.devicepolicy.OwnersTest}
+ *
*/
@SmallTest
+@RunWith(AndroidJUnit4.class)
public class OwnersTest extends DpmTestBase {
+
+ @Test
public void testUpgrade01() throws Exception {
getServices().addUsers(10, 11, 20, 21);
@@ -48,26 +55,26 @@ public class OwnersTest extends DpmTestBase {
owners.load();
// The legacy file should be removed.
- assertFalse(owners.getLegacyConfigFile().exists());
+ assertThat(owners.getLegacyConfigFile().exists()).isFalse();
// File was empty, so no new files should be created.
- assertFalse(owners.getDeviceOwnerFile().exists());
-
- assertFalse(owners.getProfileOwnerFile(10).exists());
- assertFalse(owners.getProfileOwnerFile(11).exists());
- assertFalse(owners.getProfileOwnerFile(20).exists());
- assertFalse(owners.getProfileOwnerFile(21).exists());
-
- assertFalse(owners.hasDeviceOwner());
- assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
- assertNull(owners.getSystemUpdatePolicy());
- assertEquals(0, owners.getProfileOwnerKeys().size());
-
- assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+ assertThat(owners.getDeviceOwnerFile().exists()).isFalse();
+
+ assertThat(owners.getProfileOwnerFile(10).exists()).isFalse();
+ assertThat(owners.getProfileOwnerFile(11).exists()).isFalse();
+ assertThat(owners.getProfileOwnerFile(20).exists()).isFalse();
+ assertThat(owners.getProfileOwnerFile(21).exists()).isFalse();
+
+ assertThat(owners.hasDeviceOwner()).isFalse();
+ assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+ assertThat(owners.getSystemUpdatePolicy()).isNull();
+ assertThat(owners.getProfileOwnerKeys()).isEmpty();
+
+ assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
}
// Then re-read and check.
@@ -75,19 +82,20 @@ public class OwnersTest extends DpmTestBase {
final OwnersTestable owners = new OwnersTestable(getServices());
owners.load();
- assertFalse(owners.hasDeviceOwner());
- assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
- assertNull(owners.getSystemUpdatePolicy());
- assertEquals(0, owners.getProfileOwnerKeys().size());
+ assertThat(owners.hasDeviceOwner()).isFalse();
+ assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+ assertThat(owners.getSystemUpdatePolicy()).isNull();
+ assertThat(owners.getProfileOwnerKeys()).isEmpty();
- assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+ assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
}
}
+ @Test
public void testUpgrade02() throws Exception {
getServices().addUsers(10, 11, 20, 21);
@@ -101,28 +109,28 @@ public class OwnersTest extends DpmTestBase {
owners.load();
// The legacy file should be removed.
- assertFalse(owners.getLegacyConfigFile().exists());
+ assertThat(owners.getLegacyConfigFile().exists()).isFalse();
- assertTrue(owners.getDeviceOwnerFile().exists()); // TODO Check content
+ assertThat(owners.getDeviceOwnerFile().exists()).isTrue(); // TODO Check content
- assertFalse(owners.getProfileOwnerFile(10).exists());
- assertFalse(owners.getProfileOwnerFile(11).exists());
- assertFalse(owners.getProfileOwnerFile(20).exists());
- assertFalse(owners.getProfileOwnerFile(21).exists());
+ assertThat(owners.getProfileOwnerFile(10).exists()).isFalse();
+ assertThat(owners.getProfileOwnerFile(11).exists()).isFalse();
+ assertThat(owners.getProfileOwnerFile(20).exists()).isFalse();
+ assertThat(owners.getProfileOwnerFile(21).exists()).isFalse();
- assertTrue(owners.hasDeviceOwner());
- assertEquals(null, owners.getDeviceOwnerName());
- assertEquals("com.google.android.testdpc", owners.getDeviceOwnerPackageName());
- assertEquals(UserHandle.USER_SYSTEM, owners.getDeviceOwnerUserId());
+ assertThat(owners.hasDeviceOwner()).isTrue();
+ assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
+ assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
+ assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
- assertNull(owners.getSystemUpdatePolicy());
- assertEquals(0, owners.getProfileOwnerKeys().size());
+ assertThat(owners.getSystemUpdatePolicy()).isNull();
+ assertThat(owners.getProfileOwnerKeys()).isEmpty();
- assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+ assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isTrue();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
}
// Then re-read and check.
@@ -130,22 +138,23 @@ public class OwnersTest extends DpmTestBase {
final OwnersTestable owners = new OwnersTestable(getServices());
owners.load();
- assertTrue(owners.hasDeviceOwner());
- assertEquals(null, owners.getDeviceOwnerName());
- assertEquals("com.google.android.testdpc", owners.getDeviceOwnerPackageName());
- assertEquals(UserHandle.USER_SYSTEM, owners.getDeviceOwnerUserId());
+ assertThat(owners.hasDeviceOwner()).isTrue();
+ assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
+ assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
+ assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
- assertNull(owners.getSystemUpdatePolicy());
- assertEquals(0, owners.getProfileOwnerKeys().size());
+ assertThat(owners.getSystemUpdatePolicy()).isNull();
+ assertThat(owners.getProfileOwnerKeys()).isEmpty();
- assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+ assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isTrue();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
}
}
+ @Test
public void testUpgrade03() throws Exception {
getServices().addUsers(10, 11, 20, 21);
@@ -159,36 +168,36 @@ public class OwnersTest extends DpmTestBase {
owners.load();
// The legacy file should be removed.
- assertFalse(owners.getLegacyConfigFile().exists());
-
- assertFalse(owners.getDeviceOwnerFile().exists());
-
- assertTrue(owners.getProfileOwnerFile(10).exists());
- assertTrue(owners.getProfileOwnerFile(11).exists());
- assertFalse(owners.getProfileOwnerFile(20).exists());
- assertFalse(owners.getProfileOwnerFile(21).exists());
-
- assertFalse(owners.hasDeviceOwner());
- assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
- assertNull(owners.getSystemUpdatePolicy());
-
- assertEquals(2, owners.getProfileOwnerKeys().size());
- assertEquals(new ComponentName("com.google.android.testdpc",
- "com.google.android.testdpc.DeviceAdminReceiver0"),
- owners.getProfileOwnerComponent(10));
- assertEquals("0", owners.getProfileOwnerName(10));
- assertEquals("com.google.android.testdpc", owners.getProfileOwnerPackage(10));
-
- assertEquals(new ComponentName("com.google.android.testdpc1", ""),
- owners.getProfileOwnerComponent(11));
- assertEquals("1", owners.getProfileOwnerName(11));
- assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
-
- assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
- assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+ assertThat(owners.getLegacyConfigFile().exists()).isFalse();
+
+ assertThat(owners.getDeviceOwnerFile().exists()).isFalse();
+
+ assertThat(owners.getProfileOwnerFile(10).exists()).isTrue();
+ assertThat(owners.getProfileOwnerFile(11).exists()).isTrue();
+ assertThat(owners.getProfileOwnerFile(20).exists()).isFalse();
+ assertThat(owners.getProfileOwnerFile(21).exists()).isFalse();
+
+ assertThat(owners.hasDeviceOwner()).isFalse();
+ assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+ assertThat(owners.getSystemUpdatePolicy()).isNull();
+
+ assertThat(owners.getProfileOwnerKeys()).hasSize(2);
+ assertThat(owners.getProfileOwnerComponent(10))
+ .isEqualTo(new ComponentName("com.google.android.testdpc",
+ "com.google.android.testdpc.DeviceAdminReceiver0"));
+ assertThat(owners.getProfileOwnerName(10)).isEqualTo("0");
+ assertThat(owners.getProfileOwnerPackage(10)).isEqualTo("com.google.android.testdpc");
+
+ assertThat(owners.getProfileOwnerComponent(11))
+ .isEqualTo(new ComponentName("com.google.android.testdpc1", ""));
+ assertThat(owners.getProfileOwnerName(11)).isEqualTo("1");
+ assertThat(owners.getProfileOwnerPackage(11)).isEqualTo("com.google.android.testdpc1");
+
+ assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
}
// Then re-read and check.
@@ -196,27 +205,27 @@ public class OwnersTest extends DpmTestBase {
final OwnersTestable owners = new OwnersTestable(getServices());
owners.load();
- assertFalse(owners.hasDeviceOwner());
- assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
- assertNull(owners.getSystemUpdatePolicy());
-
- assertEquals(2, owners.getProfileOwnerKeys().size());
- assertEquals(new ComponentName("com.google.android.testdpc",
- "com.google.android.testdpc.DeviceAdminReceiver0"),
- owners.getProfileOwnerComponent(10));
- assertEquals("0", owners.getProfileOwnerName(10));
- assertEquals("com.google.android.testdpc", owners.getProfileOwnerPackage(10));
-
- assertEquals(new ComponentName("com.google.android.testdpc1", ""),
- owners.getProfileOwnerComponent(11));
- assertEquals("1", owners.getProfileOwnerName(11));
- assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
-
- assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
- assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+ assertThat(owners.hasDeviceOwner()).isFalse();
+ assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+ assertThat(owners.getSystemUpdatePolicy()).isNull();
+
+ assertThat(owners.getProfileOwnerKeys()).hasSize(2);
+ assertThat(owners.getProfileOwnerComponent(10))
+ .isEqualTo(new ComponentName("com.google.android.testdpc",
+ "com.google.android.testdpc.DeviceAdminReceiver0"));
+ assertThat(owners.getProfileOwnerName(10)).isEqualTo("0");
+ assertThat(owners.getProfileOwnerPackage(10)).isEqualTo("com.google.android.testdpc");
+
+ assertThat(owners.getProfileOwnerComponent(11))
+ .isEqualTo(new ComponentName("com.google.android.testdpc1", ""));
+ assertThat(owners.getProfileOwnerName(11)).isEqualTo("1");
+ assertThat(owners.getProfileOwnerPackage(11)).isEqualTo("com.google.android.testdpc1");
+
+ assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
}
}
@@ -224,6 +233,7 @@ public class OwnersTest extends DpmTestBase {
* Note this also tests {@link Owners#setDeviceOwnerUserRestrictionsMigrated()}
* and {@link Owners#setProfileOwnerUserRestrictionsMigrated(int)}.
*/
+ @Test
public void testUpgrade04() throws Exception {
getServices().addUsers(10, 11, 20, 21);
@@ -237,40 +247,40 @@ public class OwnersTest extends DpmTestBase {
owners.load();
// The legacy file should be removed.
- assertFalse(owners.getLegacyConfigFile().exists());
-
- assertTrue(owners.getDeviceOwnerFile().exists());
-
- assertTrue(owners.getProfileOwnerFile(10).exists());
- assertTrue(owners.getProfileOwnerFile(11).exists());
- assertFalse(owners.getProfileOwnerFile(20).exists());
- assertFalse(owners.getProfileOwnerFile(21).exists());
-
- assertTrue(owners.hasDeviceOwner());
- assertEquals(null, owners.getDeviceOwnerName());
- assertEquals("com.google.android.testdpc", owners.getDeviceOwnerPackageName());
- assertEquals(UserHandle.USER_SYSTEM, owners.getDeviceOwnerUserId());
-
- assertNotNull(owners.getSystemUpdatePolicy());
- assertEquals(5, owners.getSystemUpdatePolicy().getPolicyType());
-
- assertEquals(2, owners.getProfileOwnerKeys().size());
- assertEquals(new ComponentName("com.google.android.testdpc",
- "com.google.android.testdpc.DeviceAdminReceiver0"),
- owners.getProfileOwnerComponent(10));
- assertEquals("0", owners.getProfileOwnerName(10));
- assertEquals("com.google.android.testdpc", owners.getProfileOwnerPackage(10));
-
- assertEquals(new ComponentName("com.google.android.testdpc1", ""),
- owners.getProfileOwnerComponent(11));
- assertEquals("1", owners.getProfileOwnerName(11));
- assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
-
- assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
- assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+ assertThat(owners.getLegacyConfigFile().exists()).isFalse();
+
+ assertThat(owners.getDeviceOwnerFile().exists()).isTrue();
+
+ assertThat(owners.getProfileOwnerFile(10).exists()).isTrue();
+ assertThat(owners.getProfileOwnerFile(11).exists()).isTrue();
+ assertThat(owners.getProfileOwnerFile(20).exists()).isFalse();
+ assertThat(owners.getProfileOwnerFile(21).exists()).isFalse();
+
+ assertThat(owners.hasDeviceOwner()).isTrue();
+ assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
+ assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
+ assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
+
+ assertThat(owners.getSystemUpdatePolicy()).isNotNull();
+ assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5);
+
+ assertThat(owners.getProfileOwnerKeys()).hasSize(2);
+ assertThat(owners.getProfileOwnerComponent(10))
+ .isEqualTo(new ComponentName("com.google.android.testdpc",
+ "com.google.android.testdpc.DeviceAdminReceiver0"));
+ assertThat(owners.getProfileOwnerName(10)).isEqualTo("0");
+ assertThat(owners.getProfileOwnerPackage(10)).isEqualTo("com.google.android.testdpc");
+
+ assertThat(owners.getProfileOwnerComponent(11))
+ .isEqualTo(new ComponentName("com.google.android.testdpc1", ""));
+ assertThat(owners.getProfileOwnerName(11)).isEqualTo("1");
+ assertThat(owners.getProfileOwnerPackage(11)).isEqualTo("com.google.android.testdpc1");
+
+ assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isTrue();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
}
// Then re-read and check.
@@ -278,31 +288,31 @@ public class OwnersTest extends DpmTestBase {
final OwnersTestable owners = new OwnersTestable(getServices());
owners.load();
- assertTrue(owners.hasDeviceOwner());
- assertEquals(null, owners.getDeviceOwnerName());
- assertEquals("com.google.android.testdpc", owners.getDeviceOwnerPackageName());
- assertEquals(UserHandle.USER_SYSTEM, owners.getDeviceOwnerUserId());
+ assertThat(owners.hasDeviceOwner()).isTrue();
+ assertThat(owners.getDeviceOwnerName()).isEqualTo(null);
+ assertThat(owners.getDeviceOwnerPackageName()).isEqualTo("com.google.android.testdpc");
+ assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_SYSTEM);
- assertNotNull(owners.getSystemUpdatePolicy());
- assertEquals(5, owners.getSystemUpdatePolicy().getPolicyType());
+ assertThat(owners.getSystemUpdatePolicy()).isNotNull();
+ assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5);
- assertEquals(2, owners.getProfileOwnerKeys().size());
- assertEquals(new ComponentName("com.google.android.testdpc",
- "com.google.android.testdpc.DeviceAdminReceiver0"),
- owners.getProfileOwnerComponent(10));
- assertEquals("0", owners.getProfileOwnerName(10));
- assertEquals("com.google.android.testdpc", owners.getProfileOwnerPackage(10));
+ assertThat(owners.getProfileOwnerKeys()).hasSize(2);
+ assertThat(owners.getProfileOwnerComponent(10))
+ .isEqualTo(new ComponentName("com.google.android.testdpc",
+ "com.google.android.testdpc.DeviceAdminReceiver0"));
+ assertThat(owners.getProfileOwnerName(10)).isEqualTo("0");
+ assertThat(owners.getProfileOwnerPackage(10)).isEqualTo("com.google.android.testdpc");
- assertEquals(new ComponentName("com.google.android.testdpc1", ""),
- owners.getProfileOwnerComponent(11));
- assertEquals("1", owners.getProfileOwnerName(11));
- assertEquals("com.google.android.testdpc1", owners.getProfileOwnerPackage(11));
+ assertThat(owners.getProfileOwnerComponent(11))
+ .isEqualTo(new ComponentName("com.google.android.testdpc1", ""));
+ assertThat(owners.getProfileOwnerName(11)).isEqualTo("1");
+ assertThat(owners.getProfileOwnerPackage(11)).isEqualTo("com.google.android.testdpc1");
- assertTrue(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
- assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+ assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isTrue();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
owners.setDeviceOwnerUserRestrictionsMigrated();
}
@@ -311,11 +321,11 @@ public class OwnersTest extends DpmTestBase {
final OwnersTestable owners = new OwnersTestable(getServices());
owners.load();
- assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
- assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+ assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isTrue();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
owners.setProfileOwnerUserRestrictionsMigrated(11);
}
@@ -324,16 +334,17 @@ public class OwnersTest extends DpmTestBase {
final OwnersTestable owners = new OwnersTestable(getServices());
owners.load();
- assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertTrue(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+ assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isTrue();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
owners.setProfileOwnerUserRestrictionsMigrated(11);
}
}
+ @Test
public void testUpgrade05() throws Exception {
getServices().addUsers(10, 11, 20, 21);
@@ -347,27 +358,27 @@ public class OwnersTest extends DpmTestBase {
owners.load();
// The legacy file should be removed.
- assertFalse(owners.getLegacyConfigFile().exists());
+ assertThat(owners.getLegacyConfigFile().exists()).isFalse();
// Note device initializer is no longer supported. No need to write the DO file.
- assertFalse(owners.getDeviceOwnerFile().exists());
+ assertThat(owners.getDeviceOwnerFile().exists()).isFalse();
- assertFalse(owners.getProfileOwnerFile(10).exists());
- assertFalse(owners.getProfileOwnerFile(11).exists());
- assertFalse(owners.getProfileOwnerFile(20).exists());
+ assertThat(owners.getProfileOwnerFile(10).exists()).isFalse();
+ assertThat(owners.getProfileOwnerFile(11).exists()).isFalse();
+ assertThat(owners.getProfileOwnerFile(20).exists()).isFalse();
- assertFalse(owners.hasDeviceOwner());
- assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
+ assertThat(owners.hasDeviceOwner()).isFalse();
+ assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
- assertNull(owners.getSystemUpdatePolicy());
- assertEquals(0, owners.getProfileOwnerKeys().size());
+ assertThat(owners.getSystemUpdatePolicy()).isNull();
+ assertThat(owners.getProfileOwnerKeys()).isEmpty();
- assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+ assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
}
// Then re-read and check.
@@ -375,21 +386,22 @@ public class OwnersTest extends DpmTestBase {
final OwnersTestable owners = new OwnersTestable(getServices());
owners.load();
- assertFalse(owners.hasDeviceOwner());
- assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
+ assertThat(owners.hasDeviceOwner()).isFalse();
+ assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
- assertNull(owners.getSystemUpdatePolicy());
- assertEquals(0, owners.getProfileOwnerKeys().size());
+ assertThat(owners.getSystemUpdatePolicy()).isNull();
+ assertThat(owners.getProfileOwnerKeys()).isEmpty();
- assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+ assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
}
}
+ @Test
public void testUpgrade06() throws Exception {
getServices().addUsers(10, 11, 20, 21);
@@ -403,26 +415,26 @@ public class OwnersTest extends DpmTestBase {
owners.load();
// The legacy file should be removed.
- assertFalse(owners.getLegacyConfigFile().exists());
+ assertThat(owners.getLegacyConfigFile().exists()).isFalse();
- assertTrue(owners.getDeviceOwnerFile().exists());
+ assertThat(owners.getDeviceOwnerFile().exists()).isTrue();
- assertFalse(owners.getProfileOwnerFile(10).exists());
- assertFalse(owners.getProfileOwnerFile(11).exists());
- assertFalse(owners.getProfileOwnerFile(20).exists());
+ assertThat(owners.getProfileOwnerFile(10).exists()).isFalse();
+ assertThat(owners.getProfileOwnerFile(11).exists()).isFalse();
+ assertThat(owners.getProfileOwnerFile(20).exists()).isFalse();
- assertFalse(owners.hasDeviceOwner());
- assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
- assertEquals(0, owners.getProfileOwnerKeys().size());
+ assertThat(owners.hasDeviceOwner()).isFalse();
+ assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+ assertThat(owners.getProfileOwnerKeys()).isEmpty();
- assertNotNull(owners.getSystemUpdatePolicy());
- assertEquals(5, owners.getSystemUpdatePolicy().getPolicyType());
+ assertThat(owners.getSystemUpdatePolicy()).isNotNull();
+ assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5);
- assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+ assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
}
// Then re-read and check.
@@ -430,21 +442,22 @@ public class OwnersTest extends DpmTestBase {
final OwnersTestable owners = new OwnersTestable(getServices());
owners.load();
- assertFalse(owners.hasDeviceOwner());
- assertEquals(UserHandle.USER_NULL, owners.getDeviceOwnerUserId());
- assertEquals(0, owners.getProfileOwnerKeys().size());
+ assertThat(owners.hasDeviceOwner()).isFalse();
+ assertThat(owners.getDeviceOwnerUserId()).isEqualTo(UserHandle.USER_NULL);
+ assertThat(owners.getProfileOwnerKeys()).isEmpty();
- assertNotNull(owners.getSystemUpdatePolicy());
- assertEquals(5, owners.getSystemUpdatePolicy().getPolicyType());
+ assertThat(owners.getSystemUpdatePolicy()).isNotNull();
+ assertThat(owners.getSystemUpdatePolicy().getPolicyType()).isEqualTo(5);
- assertFalse(owners.getDeviceOwnerUserRestrictionsNeedsMigration());
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(10));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(11));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(20));
- assertFalse(owners.getProfileOwnerUserRestrictionsNeedsMigration(21));
+ assertThat(owners.getDeviceOwnerUserRestrictionsNeedsMigration()).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(10)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(11)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(20)).isFalse();
+ assertThat(owners.getProfileOwnerUserRestrictionsNeedsMigration(21)).isFalse();
}
}
+ @Test
public void testRemoveExistingFiles() throws Exception {
getServices().addUsers(10, 11, 20, 21);
@@ -456,11 +469,11 @@ public class OwnersTest extends DpmTestBase {
owners.load();
- assertFalse(owners.getLegacyConfigFile().exists());
+ assertThat(owners.getLegacyConfigFile().exists()).isFalse();
- assertTrue(owners.getDeviceOwnerFile().exists());
- assertTrue(owners.getProfileOwnerFile(10).exists());
- assertTrue(owners.getProfileOwnerFile(11).exists());
+ assertThat(owners.getDeviceOwnerFile().exists()).isTrue();
+ assertThat(owners.getProfileOwnerFile(10).exists()).isTrue();
+ assertThat(owners.getProfileOwnerFile(11).exists()).isTrue();
// Then clear all information and save.
owners.clearDeviceOwner();
@@ -475,8 +488,8 @@ public class OwnersTest extends DpmTestBase {
owners.writeProfileOwner(21);
// Now all files should be removed.
- assertFalse(owners.getDeviceOwnerFile().exists());
- assertFalse(owners.getProfileOwnerFile(10).exists());
- assertFalse(owners.getProfileOwnerFile(11).exists());
+ assertThat(owners.getDeviceOwnerFile().exists()).isFalse();
+ assertThat(owners.getProfileOwnerFile(10).exists()).isFalse();
+ assertThat(owners.getProfileOwnerFile(11).exists()).isFalse();
}
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/SecurityEventTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/SecurityEventTest.java
index 8dcf21f9fe77..6cefaebbff7a 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/SecurityEventTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/SecurityEventTest.java
@@ -1,3 +1,18 @@
+/*
+ * 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.devicepolicy;
import static android.app.admin.SecurityLog.TAG_ADB_SHELL_CMD;
@@ -11,6 +26,8 @@ import static android.app.admin.SecurityLog.TAG_KEY_INTEGRITY_VIOLATION;
import static android.app.admin.SecurityLog.TAG_MEDIA_MOUNT;
import static android.app.admin.SecurityLog.TAG_MEDIA_UNMOUNT;
+import static com.google.common.truth.Truth.assertThat;
+
import android.app.admin.SecurityLog.SecurityEvent;
import android.os.Parcel;
import android.os.UserHandle;
@@ -18,21 +35,37 @@ import android.text.TextUtils;
import android.util.EventLog;
import android.util.EventLog.Event;
+import androidx.test.runner.AndroidJUnit4;
+
import junit.framework.AssertionFailedError;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
import java.util.ArrayList;
import java.util.List;
+/**
+ * Tests for the DeviceOwner object that saves & loads device and policy owner information.
+ *
+ * <p>Run this test with:
+ *
+ * {@code atest FrameworksServicesTests:com.android.server.devicepolicy.SecurityEventTest}
+ *
+ */
+@RunWith(AndroidJUnit4.class)
public class SecurityEventTest extends DpmTestBase {
+ @Test
public void testSecurityEventId() throws Exception {
SecurityEvent event = createEvent(() -> {
EventLog.writeEvent(TAG_ADB_SHELL_CMD, 0);
}, TAG_ADB_SHELL_CMD);
event.setId(20);
- assertEquals(20, event.getId());
+ assertThat(event.getId()).isEqualTo(20);
}
+ @Test
public void testSecurityEventParceling() throws Exception {
// GIVEN an event.
SecurityEvent event = createEvent(() -> {
@@ -45,12 +78,13 @@ public class SecurityEventTest extends DpmTestBase {
SecurityEvent unparceledEvent = p.readParcelable(SecurityEventTest.class.getClassLoader());
p.recycle();
// THEN the event state is preserved.
- assertEquals(event.getTag(), unparceledEvent.getTag());
- assertEquals(event.getData(), unparceledEvent.getData());
- assertEquals(event.getTimeNanos(), unparceledEvent.getTimeNanos());
- assertEquals(event.getId(), unparceledEvent.getId());
+ assertThat(unparceledEvent.getTag()).isEqualTo(event.getTag());
+ assertThat(unparceledEvent.getData()).isEqualTo(event.getData());
+ assertThat(unparceledEvent.getTimeNanos()).isEqualTo(event.getTimeNanos());
+ assertThat(unparceledEvent.getId()).isEqualTo(event.getId());
}
+ @Test
public void testSecurityEventRedaction() throws Exception {
SecurityEvent event;
@@ -58,75 +92,75 @@ public class SecurityEventTest extends DpmTestBase {
event = createEvent(() -> {
EventLog.writeEvent(TAG_ADB_SHELL_CMD, "command");
}, TAG_ADB_SHELL_CMD);
- assertFalse(TextUtils.isEmpty((String) event.getData()));
+ assertThat(TextUtils.isEmpty((String) event.getData())).isFalse();
// TAG_MEDIA_MOUNT will have the volume label redacted (second data)
event = createEvent(() -> {
EventLog.writeEvent(TAG_MEDIA_MOUNT, new Object[] {"path", "label"});
}, TAG_MEDIA_MOUNT);
- assertFalse(TextUtils.isEmpty(event.getStringData(1)));
- assertTrue(TextUtils.isEmpty(event.redact(0).getStringData(1)));
+ assertThat(TextUtils.isEmpty(event.getStringData(1))).isFalse();
+ assertThat(TextUtils.isEmpty(event.redact(0).getStringData(1))).isTrue();
// TAG_MEDIA_UNMOUNT will have the volume label redacted (second data)
event = createEvent(() -> {
EventLog.writeEvent(TAG_MEDIA_UNMOUNT, new Object[] {"path", "label"});
}, TAG_MEDIA_UNMOUNT);
- assertFalse(TextUtils.isEmpty(event.getStringData(1)));
- assertTrue(TextUtils.isEmpty(event.redact(0).getStringData(1)));
+ assertThat(TextUtils.isEmpty(event.getStringData(1))).isFalse();
+ assertThat(TextUtils.isEmpty(event.redact(0).getStringData(1))).isTrue();
// TAG_APP_PROCESS_START will be fully redacted if user does not match
event = createEvent(() -> {
EventLog.writeEvent(TAG_APP_PROCESS_START, new Object[] {"process", 12345L,
UserHandle.getUid(10, 123), 456, "seinfo", "hash"});
}, TAG_APP_PROCESS_START);
- assertNotNull(event.redact(10));
- assertNull(event.redact(11));
+ assertThat(event.redact(10)).isNotNull();
+ assertThat(event.redact(11)).isNull();
// TAG_CERT_AUTHORITY_INSTALLED will be fully redacted if user does not match
event = createEvent(() -> {
EventLog.writeEvent(TAG_CERT_AUTHORITY_INSTALLED, new Object[] {1, "subject", 10});
}, TAG_CERT_AUTHORITY_INSTALLED);
- assertNotNull(event.redact(10));
- assertNull(event.redact(11));
+ assertThat(event.redact(10)).isNotNull();
+ assertThat(event.redact(11)).isNull();
// TAG_CERT_AUTHORITY_REMOVED will be fully redacted if user does not match
event = createEvent(() -> {
EventLog.writeEvent(TAG_CERT_AUTHORITY_REMOVED, new Object[] {1, "subject", 20});
}, TAG_CERT_AUTHORITY_REMOVED);
- assertNotNull(event.redact(20));
- assertNull(event.redact(0));
+ assertThat(event.redact(20)).isNotNull();
+ assertThat(event.redact(0)).isNull();
// TAG_KEY_GENERATED will be fully redacted if user does not match
event = createEvent(() -> {
EventLog.writeEvent(TAG_KEY_GENERATED,
new Object[] {1, "alias", UserHandle.getUid(0, 123)});
}, TAG_KEY_GENERATED);
- assertNotNull(event.redact(0));
- assertNull(event.redact(10));
+ assertThat(event.redact(0)).isNotNull();
+ assertThat(event.redact(10)).isNull();
// TAG_KEY_IMPORT will be fully redacted if user does not match
event = createEvent(() -> {
EventLog.writeEvent(TAG_KEY_IMPORT,
new Object[] {1, "alias", UserHandle.getUid(1, 123)});
}, TAG_KEY_IMPORT);
- assertNotNull(event.redact(1));
- assertNull(event.redact(10));
+ assertThat(event.redact(1)).isNotNull();
+ assertThat(event.redact(10)).isNull();
// TAG_KEY_DESTRUCTION will be fully redacted if user does not match
event = createEvent(() -> {
EventLog.writeEvent(TAG_KEY_DESTRUCTION,
new Object[] {1, "alias", UserHandle.getUid(2, 123)});
}, TAG_KEY_DESTRUCTION);
- assertNotNull(event.redact(2));
- assertNull(event.redact(10));
+ assertThat(event.redact(2)).isNotNull();
+ assertThat(event.redact(10)).isNull();
// TAG_KEY_INTEGRITY_VIOLATION will be fully redacted if user does not match
event = createEvent(() -> {
EventLog.writeEvent(TAG_KEY_INTEGRITY_VIOLATION,
new Object[] {"alias", UserHandle.getUid(2, 123)});
}, TAG_KEY_INTEGRITY_VIOLATION);
- assertNotNull(event.redact(2));
- assertNull(event.redact(10));
+ assertThat(event.redact(2)).isNotNull();
+ assertThat(event.redact(10)).isNull();
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
index e51859b5c829..0a9aad771ff0 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/SystemUpdatePolicyTest.java
@@ -21,8 +21,9 @@ import static android.app.admin.SystemUpdatePolicy.ValidationFailedException.ERR
import static android.app.admin.SystemUpdatePolicy.ValidationFailedException.ERROR_NEW_FREEZE_PERIOD_TOO_CLOSE;
import static android.app.admin.SystemUpdatePolicy.ValidationFailedException.ERROR_NEW_FREEZE_PERIOD_TOO_LONG;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import static org.junit.Assert.fail;
import android.app.admin.FreezePeriod;
@@ -53,10 +54,12 @@ import java.util.concurrent.TimeUnit;
/**
* Unit tests for {@link android.app.admin.SystemUpdatePolicy}.
- * Throughout this test, we use "MM-DD" format to denote dates without year.
*
- * atest com.android.server.devicepolicy.SystemUpdatePolicyTest
- * runtest -c com.android.server.devicepolicy.SystemUpdatePolicyTest frameworks-services
+ * <p>NOTE: Throughout this test, we use {@code "MM-DD"} format to denote dates without year.
+ *
+ * <p>Run this test with:
+ *
+ * {@code atest FrameworksServicesTests:com.android.server.devicepolicy.SystemUpdatePolicyTest}
*/
@RunWith(AndroidJUnit4.class)
public final class SystemUpdatePolicyTest {
@@ -224,37 +227,37 @@ public final class SystemUpdatePolicyTest {
@Test
public void testDistanceWithoutLeapYear() {
- assertEquals(364, FreezePeriod.distanceWithoutLeapYear(
- LocalDate.of(2016, 12, 31), LocalDate.of(2016, 1, 1)));
- assertEquals(365, FreezePeriod.distanceWithoutLeapYear(
- LocalDate.of(2017, 1, 1), LocalDate.of(2016, 1, 1)));
- assertEquals(365, FreezePeriod.distanceWithoutLeapYear(
- LocalDate.of(2017, 2, 28), LocalDate.of(2016, 2, 29)));
- assertEquals(-365, FreezePeriod.distanceWithoutLeapYear(
- LocalDate.of(2016, 1, 1), LocalDate.of(2017, 1, 1)));
- assertEquals(1, FreezePeriod.distanceWithoutLeapYear(
- LocalDate.of(2016, 3, 1), LocalDate.of(2016, 2, 29)));
- assertEquals(1, FreezePeriod.distanceWithoutLeapYear(
- LocalDate.of(2016, 3, 1), LocalDate.of(2016, 2, 28)));
- assertEquals(0, FreezePeriod.distanceWithoutLeapYear(
- LocalDate.of(2016, 2, 29), LocalDate.of(2016, 2, 28)));
- assertEquals(0, FreezePeriod.distanceWithoutLeapYear(
- LocalDate.of(2016, 2, 28), LocalDate.of(2016, 2, 28)));
-
- assertEquals(59, FreezePeriod.distanceWithoutLeapYear(
- LocalDate.of(2016, 3, 1), LocalDate.of(2016, 1, 1)));
- assertEquals(59, FreezePeriod.distanceWithoutLeapYear(
- LocalDate.of(2017, 3, 1), LocalDate.of(2017, 1, 1)));
-
- assertEquals(365 * 40, FreezePeriod.distanceWithoutLeapYear(
- LocalDate.of(2040, 1, 1), LocalDate.of(2000, 1, 1)));
-
- assertEquals(365 * 2, FreezePeriod.distanceWithoutLeapYear(
- LocalDate.of(2019, 3, 1), LocalDate.of(2017, 3, 1)));
- assertEquals(365 * 2, FreezePeriod.distanceWithoutLeapYear(
- LocalDate.of(2018, 3, 1), LocalDate.of(2016, 3, 1)));
- assertEquals(365 * 2, FreezePeriod.distanceWithoutLeapYear(
- LocalDate.of(2017, 3, 1), LocalDate.of(2015, 3, 1)));
+ assertThat(FreezePeriod.distanceWithoutLeapYear(
+ LocalDate.of(2016, 12, 31), LocalDate.of(2016, 1, 1))).isEqualTo(364);
+ assertThat(FreezePeriod.distanceWithoutLeapYear(
+ LocalDate.of(2017, 1, 1), LocalDate.of(2016, 1, 1))).isEqualTo(365);
+ assertThat(FreezePeriod.distanceWithoutLeapYear(
+ LocalDate.of(2017, 2, 28), LocalDate.of(2016, 2, 29))).isEqualTo(365);
+ assertThat(FreezePeriod.distanceWithoutLeapYear(
+ LocalDate.of(2016, 1, 1), LocalDate.of(2017, 1, 1))).isEqualTo(-365);
+ assertThat(FreezePeriod.distanceWithoutLeapYear(
+ LocalDate.of(2016, 3, 1), LocalDate.of(2016, 2, 29))).isEqualTo(1);
+ assertThat(FreezePeriod.distanceWithoutLeapYear(
+ LocalDate.of(2016, 3, 1), LocalDate.of(2016, 2, 28))).isEqualTo(1);
+ assertThat(FreezePeriod.distanceWithoutLeapYear(
+ LocalDate.of(2016, 2, 29), LocalDate.of(2016, 2, 28))).isEqualTo(0);
+ assertThat(FreezePeriod.distanceWithoutLeapYear(
+ LocalDate.of(2016, 2, 28), LocalDate.of(2016, 2, 28))).isEqualTo(0);
+
+ assertThat(FreezePeriod.distanceWithoutLeapYear(
+ LocalDate.of(2016, 3, 1), LocalDate.of(2016, 1, 1))).isEqualTo(59);
+ assertThat(FreezePeriod.distanceWithoutLeapYear(
+ LocalDate.of(2017, 3, 1), LocalDate.of(2017, 1, 1))).isEqualTo(59);
+
+ assertThat(FreezePeriod.distanceWithoutLeapYear(
+ LocalDate.of(2040, 1, 1), LocalDate.of(2000, 1, 1))).isEqualTo(365 * 40);
+
+ assertThat(FreezePeriod.distanceWithoutLeapYear(
+ LocalDate.of(2019, 3, 1), LocalDate.of(2017, 3, 1))).isEqualTo(365 * 2);
+ assertThat(FreezePeriod.distanceWithoutLeapYear(
+ LocalDate.of(2018, 3, 1), LocalDate.of(2016, 3, 1))).isEqualTo(365 * 2);
+ assertThat(FreezePeriod.distanceWithoutLeapYear(
+ LocalDate.of(2017, 3, 1), LocalDate.of(2015, 3, 1))).isEqualTo(365 * 2);
}
@@ -395,8 +398,8 @@ public final class SystemUpdatePolicyTest {
private void assertInstallationOption(int expectedType, long expectedTime, long now,
SystemUpdatePolicy p) {
- assertEquals(expectedType, p.getInstallationOptionAt(now).getType());
- assertEquals(expectedTime, p.getInstallationOptionAt(now).getEffectiveTime());
+ assertThat(p.getInstallationOptionAt(now).getType()).isEqualTo(expectedType);
+ assertThat(p.getInstallationOptionAt(now).getEffectiveTime()).isEqualTo(expectedTime);
}
private void testFreezePeriodsSucceeds(String...dates) throws Exception {
@@ -410,8 +413,8 @@ public final class SystemUpdatePolicyTest {
setFreezePeriods(p, dates);
fail("Invalid periods (" + expectedError + ") not flagged: " + String.join(" ", dates));
} catch (SystemUpdatePolicy.ValidationFailedException e) {
- assertTrue("Exception not expected: " + e.getMessage(),
- e.getErrorCode() == expectedError);
+ assertWithMessage("Exception not expected: %s", e.getMessage()).that(e.getErrorCode())
+ .isEqualTo(expectedError);
}
}
@@ -426,8 +429,8 @@ public final class SystemUpdatePolicyTest {
createPrevFreezePeriod(prevStart, prevEnd, now, dates);
fail("Invalid period (" + expectedError + ") not flagged: " + String.join(" ", dates));
} catch (SystemUpdatePolicy.ValidationFailedException e) {
- assertTrue("Exception not expected: " + e.getMessage(),
- e.getErrorCode() == expectedError);
+ assertWithMessage("Exception not expected: %s", e.getMessage()).that(e.getErrorCode())
+ .isEqualTo(expectedError);
}
}
@@ -480,7 +483,7 @@ public final class SystemUpdatePolicyTest {
ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
XmlPullParser parser = Xml.newPullParser();
parser.setInput(new InputStreamReader(inStream));
- assertEquals(XmlPullParser.START_TAG, parser.next());
+ assertThat(parser.next()).isEqualTo(XmlPullParser.START_TAG);
checkFreezePeriods(SystemUpdatePolicy.restoreFromXml(parser), expectedPeriods);
}
@@ -488,8 +491,8 @@ public final class SystemUpdatePolicyTest {
List<FreezePeriod> expectedPeriods) {
int i = 0;
for (FreezePeriod period : policy.getFreezePeriods()) {
- assertEquals(expectedPeriods.get(i).getStart(), period.getStart());
- assertEquals(expectedPeriods.get(i).getEnd(), period.getEnd());
+ assertThat(period.getStart()).isEqualTo(expectedPeriods.get(i).getStart());
+ assertThat(period.getEnd()).isEqualTo(expectedPeriods.get(i).getEnd());
i++;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
index 2005dd901ad1..07ea85535f50 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
@@ -25,14 +25,13 @@ import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.T
import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.TAG_TARGET_COMPONENT;
import static com.android.server.devicepolicy.TransferOwnershipMetadataManager.TAG_USER_ID;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static com.google.common.truth.Truth.assertThat;
import android.os.Environment;
-import androidx.test.runner.AndroidJUnit4;
import android.util.Log;
+import androidx.test.runner.AndroidJUnit4;
+
import com.android.server.devicepolicy.TransferOwnershipMetadataManager.Injector;
import com.android.server.devicepolicy.TransferOwnershipMetadataManager.Metadata;
@@ -51,12 +50,14 @@ import java.nio.file.Paths;
/**
* Unit tests for {@link TransferOwnershipMetadataManager}.
*
- * bit FrameworksServicesTests:com.android.server.devicepolicy.TransferOwnershipMetadataManagerTest
- * runtest -x frameworks/base/services/tests/servicestests/src/com/android/server/devicepolicy/TransferOwnershipMetadataManagerTest.java
-* */
-
+ * <p>Run this test with:
+ *
+ * <pre><code>
+ atest FrameworksServicesTests:com.android.server.devicepolicy.TransferOwnershipMetadataManagerTest
+ * </code></pre>
+ */
@RunWith(AndroidJUnit4.class)
-public class TransferOwnershipMetadataManagerTest {
+public final class TransferOwnershipMetadataManagerTest {
private final static String TAG = TransferOwnershipMetadataManagerTest.class.getName();
private final static String SOURCE_COMPONENT =
"com.dummy.admin.package/com.dummy.admin.package.SourceClassName";
@@ -77,28 +78,27 @@ public class TransferOwnershipMetadataManagerTest {
@Test
public void testSave() {
TransferOwnershipMetadataManager paramsManager = getOwnerTransferParams();
- assertTrue(paramsManager.saveMetadataFile(TEST_PARAMS));
- assertTrue(paramsManager.metadataFileExists());
+ assertThat(paramsManager.saveMetadataFile(TEST_PARAMS)).isTrue();
+ assertThat(paramsManager.metadataFileExists()).isTrue();
}
@Test
public void testFileContentValid() {
TransferOwnershipMetadataManager paramsManager = getOwnerTransferParams();
- assertTrue(paramsManager.saveMetadataFile(TEST_PARAMS));
+ assertThat(paramsManager.saveMetadataFile(TEST_PARAMS)).isTrue();
Path path = Paths.get(new File(mMockInjector.getOwnerTransferMetadataDir(),
OWNER_TRANSFER_METADATA_XML).getAbsolutePath());
try {
String contents = new String(Files.readAllBytes(path), Charset.forName("UTF-8"));
- assertEquals(
- "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
- + "<" + TAG_USER_ID + ">" + USER_ID + "</" + TAG_USER_ID + ">\n"
- + "<" + TAG_SOURCE_COMPONENT + ">" + SOURCE_COMPONENT + "</"
- + TAG_SOURCE_COMPONENT + ">\n"
- + "<" + TAG_TARGET_COMPONENT + ">" + TARGET_COMPONENT + "</"
- + TAG_TARGET_COMPONENT + ">\n"
- + "<" + TAG_ADMIN_TYPE + ">" + ADMIN_TYPE_DEVICE_OWNER + "</"
- + TAG_ADMIN_TYPE + ">\n",
- contents);
+ assertThat(contents).isEqualTo(
+ "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<" + TAG_USER_ID + ">" + USER_ID + "</" + TAG_USER_ID + ">\n"
+ + "<" + TAG_SOURCE_COMPONENT + ">" + SOURCE_COMPONENT + "</"
+ + TAG_SOURCE_COMPONENT + ">\n"
+ + "<" + TAG_TARGET_COMPONENT + ">" + TARGET_COMPONENT + "</"
+ + TAG_TARGET_COMPONENT + ">\n"
+ + "<" + TAG_ADMIN_TYPE + ">" + ADMIN_TYPE_DEVICE_OWNER + "</"
+ + TAG_ADMIN_TYPE + ">\n");
} catch (IOException e) {
e.printStackTrace();
}
@@ -124,7 +124,7 @@ public class TransferOwnershipMetadataManagerTest {
Log.d(TAG, "testLoad: failed to get canonical file");
}
paramsManager.saveMetadataFile(TEST_PARAMS);
- assertEquals(TEST_PARAMS, paramsManager.loadMetadataFile());
+ assertThat(paramsManager.loadMetadataFile()).isEqualTo(TEST_PARAMS);
}
@Test
@@ -132,7 +132,7 @@ public class TransferOwnershipMetadataManagerTest {
TransferOwnershipMetadataManager paramsManager = getOwnerTransferParams();
paramsManager.saveMetadataFile(TEST_PARAMS);
paramsManager.deleteMetadataFile();
- assertFalse(paramsManager.metadataFileExists());
+ assertThat(paramsManager.metadataFileExists()).isFalse();
}
@After
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
index 470294073535..553df3bafd00 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecMessageValidatorTest.java
@@ -130,6 +130,17 @@ public class HdmiCecMessageValidatorTest {
}
@Test
+ public void isValid_setTimerProgramTitle() {
+ assertMessageValidity("40:67:47:61:6D:65:20:6F:66:20:54:68:72:6F:6E:65:73").isEqualTo(OK);
+ assertMessageValidity("40:67:4A").isEqualTo(OK);
+
+ assertMessageValidity("4F:67:47:4F:54").isEqualTo(ERROR_DESTINATION);
+ assertMessageValidity("F4:67:47:4F:54").isEqualTo(ERROR_SOURCE);
+ assertMessageValidity("40:67").isEqualTo(ERROR_PARAMETER_SHORT);
+ assertMessageValidity("40:67:47:9A:54").isEqualTo(ERROR_PARAMETER);
+ }
+
+ @Test
public void isValid_setMenuLanguage() {
assertMessageValidity("4F:32:53:50:41").isEqualTo(OK);
assertMessageValidity("0F:32:45:4E:47:8C:49:D3:48").isEqualTo(OK);
@@ -182,6 +193,166 @@ public class HdmiCecMessageValidatorTest {
assertMessageValidity("40:0A:30").isEqualTo(ERROR_PARAMETER);
}
+ @Test
+ public void isValid_setAnalogueTimer_clearAnalogueTimer() {
+ assertMessageValidity("04:33:0C:08:10:1E:04:30:08:00:13:AD:06").isEqualTo(OK);
+ assertMessageValidity("04:34:04:0C:16:0F:08:37:00:02:EA:60:03:34").isEqualTo(OK);
+
+ assertMessageValidity("0F:33:0C:08:10:1E:04:30:08:00:13:AD:06")
+ .isEqualTo(ERROR_DESTINATION);
+ assertMessageValidity("F0:34:04:0C:16:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_SOURCE);
+ assertMessageValidity("04:33:0C:08:10:1E:04:30:08:13:AD:06")
+ .isEqualTo(ERROR_PARAMETER_SHORT);
+ // Out of range Day of Month
+ assertMessageValidity("04:34:20:0C:16:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
+ // Out of range Month of Year
+ assertMessageValidity("04:33:0C:00:10:1E:04:30:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
+ // Out of range Start Time - Hour
+ assertMessageValidity("04:34:04:0C:18:0F:08:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
+ // Out of range Start Time - Minute
+ assertMessageValidity("04:33:0C:08:10:50:04:30:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
+ // Out of range Duration - Duration Hours
+ assertMessageValidity("04:34:04:0C:16:0F:64:37:00:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
+ // Out of range Duration - Minute
+ assertMessageValidity("04:33:0C:08:10:1E:04:64:08:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
+ // Invalid Recording Sequence
+ assertMessageValidity("04:34:04:0C:16:0F:08:37:88:02:EA:60:03").isEqualTo(ERROR_PARAMETER);
+ // Invalid Recording Sequence
+ assertMessageValidity("04:33:0C:08:10:1E:04:30:A2:00:13:AD:06").isEqualTo(ERROR_PARAMETER);
+ // Out of range Analogue Broadcast Type
+ assertMessageValidity("04:34:04:0C:16:0F:08:37:00:03:EA:60:03").isEqualTo(ERROR_PARAMETER);
+ // Out of range Analogue Frequency
+ assertMessageValidity("04:33:0C:08:10:1E:04:30:08:00:FF:FF:06").isEqualTo(ERROR_PARAMETER);
+ // Out of range Broadcast System
+ assertMessageValidity("04:34:04:0C:16:0F:08:37:00:02:EA:60:20").isEqualTo(ERROR_PARAMETER);
+ }
+
+ @Test
+ public void isValid_setDigitalTimer_clearDigitalTimer() {
+ // Services identified by Digital IDs - ARIB Broadcast System
+ assertMessageValidity("04:99:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75:30").isEqualTo(OK);
+ // Service identified by Digital IDs - ATSC Broadcast System
+ assertMessageValidity("04:97:1E:07:12:20:50:28:01:01:8B:5E:39:5A").isEqualTo(OK);
+ // Service identified by Digital IDs - DVB Broadcast System
+ assertMessageValidity("04:99:05:0C:06:0A:19:3B:40:19:8B:44:03:11:04:FC").isEqualTo(OK);
+ // Service identified by Channel - 1 part channel number
+ assertMessageValidity("04:97:12:06:0C:2D:5A:19:08:91:04:00:B1").isEqualTo(OK);
+ // Service identified by Channel - 2 part channel number
+ assertMessageValidity("04:99:15:09:00:0F:00:2D:04:82:09:C8:72:C8").isEqualTo(OK);
+
+ assertMessageValidity("4F:97:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75:30")
+ .isEqualTo(ERROR_DESTINATION);
+ assertMessageValidity("F0:99:15:09:00:0F:00:2D:04:82:09:C8:72:C8").isEqualTo(ERROR_SOURCE);
+ assertMessageValidity("04:97:1E:12:20:58:01:01:8B:5E:39:5A")
+ .isEqualTo(ERROR_PARAMETER_SHORT);
+ // Out of range Day of Month
+ assertMessageValidity("04:99:24:0C:06:0A:19:3B:40:19:8B:44:03:11:04:FC")
+ .isEqualTo(ERROR_PARAMETER);
+ // Out of range Month of Year
+ assertMessageValidity("04:97:12:10:0C:2D:5A:19:08:91:04:00:B1").isEqualTo(ERROR_PARAMETER);
+ // Out of range Start Time - Hour
+ assertMessageValidity("04:99:0C:08:20:05:04:1E:00:00:C4:C2:11:D8:75:30")
+ .isEqualTo(ERROR_PARAMETER);
+ // Out of range Start Time - Minute
+ assertMessageValidity("04:97:15:09:00:4B:00:2D:04:82:09:C8:72:C8")
+ .isEqualTo(ERROR_PARAMETER);
+ // Out of range Duration - Duration Hours
+ assertMessageValidity("04:99:1E:07:12:20:78:28:01:01:8B:5E:39:5A")
+ .isEqualTo(ERROR_PARAMETER);
+ // Out of range Duration - Minute
+ assertMessageValidity("04:97:05:0C:06:0A:19:48:40:19:8B:44:03:11:04:FC")
+ .isEqualTo(ERROR_PARAMETER);
+ // Invalid Recording Sequence
+ assertMessageValidity("04:99:12:06:0C:2D:5A:19:90:91:04:00:B1").isEqualTo(ERROR_PARAMETER);
+ // Invalid Recording Sequence
+ assertMessageValidity("04:97:0C:08:15:05:04:1E:21:00:C4:C2:11:D8:75:30")
+ .isEqualTo(ERROR_PARAMETER);
+
+ // Invalid Digital Broadcast System
+ assertMessageValidity("04:99:1E:07:12:20:50:28:01:04:8B:5E:39:5A")
+ .isEqualTo(ERROR_PARAMETER);
+ // Invalid Digital Broadcast System
+ assertMessageValidity("04:97:05:0C:06:0A:19:3B:40:93:8B:44:03:11:04:FC")
+ .isEqualTo(ERROR_PARAMETER);
+ // Insufficient data for ARIB Broadcast system
+ assertMessageValidity("04:99:0C:08:15:05:04:1E:00:00:C4:C2:11:D8:75")
+ .isEqualTo(ERROR_PARAMETER);
+ // Insufficient data for ATSC Broadcast system
+ assertMessageValidity("04:97:1E:07:12:20:50:28:01:01:8B:5E:39").isEqualTo(ERROR_PARAMETER);
+ // Insufficient data for DVB Broadcast system
+ assertMessageValidity("04:99:05:0C:06:0A:19:3B:40:19:8B:44:03:11:04")
+ .isEqualTo(ERROR_PARAMETER);
+ // Insufficient data for 2 part channel number
+ assertMessageValidity("04:97:15:09:00:0F:00:2D:04:82:09:C8:72").isEqualTo(ERROR_PARAMETER);
+ // Invalid Channel Number format
+ assertMessageValidity("04:99:12:06:0C:2D:5A:19:08:91:0D:00:B1").isEqualTo(ERROR_PARAMETER);
+ }
+
+ @Test
+ public void isValid_setExternalTimer_clearExternalTimer() {
+ assertMessageValidity("40:A1:0C:08:15:05:04:1E:02:04:20").isEqualTo(OK);
+ assertMessageValidity("40:A2:14:09:12:28:4B:19:10:05:10:00").isEqualTo(OK);
+
+ assertMessageValidity("4F:A1:0C:08:15:05:04:1E:02:04:20").isEqualTo(ERROR_DESTINATION);
+ assertMessageValidity("F4:A2:14:09:12:28:4B:19:10:05:10:00").isEqualTo(ERROR_SOURCE);
+ assertMessageValidity("40:A1:0C:08:15:05:04:1E:02:04").isEqualTo(ERROR_PARAMETER_SHORT);
+ // Out of range Day of Month
+ assertMessageValidity("40:A2:28:09:12:28:4B:19:10:05:10:00").isEqualTo(ERROR_PARAMETER);
+ // Out of range Month of Year
+ assertMessageValidity("40:A1:0C:0F:15:05:04:1E:02:04:20").isEqualTo(ERROR_PARAMETER);
+ // Out of range Start Time - Hour
+ assertMessageValidity("40:A2:14:09:1A:28:4B:19:10:05:10:00").isEqualTo(ERROR_PARAMETER);
+ // Out of range Start Time - Minute
+ assertMessageValidity("40:A1:0C:08:15:48:04:1E:02:04:20").isEqualTo(ERROR_PARAMETER);
+ // Out of range Duration - Duration Hours
+ assertMessageValidity("40:A2:14:09:12:28:66:19:10:05:10:00").isEqualTo(ERROR_PARAMETER);
+ // Out of range Duration - Minute
+ assertMessageValidity("40:A1:0C:08:15:05:04:3F:02:04:20").isEqualTo(ERROR_PARAMETER);
+ // Invalid Recording Sequence
+ assertMessageValidity("40:A2:14:09:12:28:4B:19:84:05:10:00").isEqualTo(ERROR_PARAMETER);
+ // Invalid Recording Sequence
+ assertMessageValidity("40:A1:0C:08:15:05:04:1E:14:04:20").isEqualTo(ERROR_PARAMETER);
+ // Invalid external source specifier
+ assertMessageValidity("40:A2:14:09:12:28:4B:19:10:08:10:00").isEqualTo(ERROR_PARAMETER);
+ // Invalid External PLug
+ assertMessageValidity("04:A1:0C:08:15:05:04:1E:02:04:00").isEqualTo(ERROR_PARAMETER);
+ }
+
+ @Test
+ public void isValid_timerClearedStatus() {
+ assertMessageValidity("40:43:01:7E").isEqualTo(OK);
+ assertMessageValidity("40:43:80").isEqualTo(OK);
+
+ assertMessageValidity("4F:43:01").isEqualTo(ERROR_DESTINATION);
+ assertMessageValidity("F0:43:80").isEqualTo(ERROR_SOURCE);
+ assertMessageValidity("40:43").isEqualTo(ERROR_PARAMETER_SHORT);
+ assertMessageValidity("40:43:03").isEqualTo(ERROR_PARAMETER);
+ }
+
+ @Test
+ public void isValid_timerStatus() {
+ // Programmed - Space available
+ assertMessageValidity("40:35:58").isEqualTo(OK);
+ // Programmed - Not enough space available
+ assertMessageValidity("40:35:B9:32:1C:4F").isEqualTo(OK);
+ // Not programmed - Date out of range
+ assertMessageValidity("40:35:82:3B").isEqualTo(OK);
+ // Not programmed - Duplicate
+ assertMessageValidity("40:35:EE:52:0C").isEqualTo(OK);
+
+ assertMessageValidity("4F:35:58").isEqualTo(ERROR_DESTINATION);
+ assertMessageValidity("F0:35:82").isEqualTo(ERROR_SOURCE);
+ assertMessageValidity("40:35").isEqualTo(ERROR_PARAMETER_SHORT);
+ // Programmed - Invalid programmed info
+ assertMessageValidity("40:35:BD").isEqualTo(ERROR_PARAMETER);
+ // Non programmed - Invalid not programmed error info
+ assertMessageValidity("40:35:DE").isEqualTo(ERROR_PARAMETER);
+ // Programmed - Might not be enough space available - Invalid duration hours
+ assertMessageValidity("40:35:BB:96:1C").isEqualTo(ERROR_PARAMETER);
+ // Not programmed - Duplicate - Invalid duration minutes
+ assertMessageValidity("40:35:EE:52:4A").isEqualTo(ERROR_PARAMETER);
+ }
+
private IntegerSubject assertMessageValidity(String message) {
return assertThat(mHdmiCecMessageValidator.isValid(buildMessage(message)));
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/permission/PermissionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/permission/PermissionManagerServiceTest.java
index 56966776c8fb..6cea9280f080 100644
--- a/services/tests/servicestests/src/com/android/server/pm/permission/PermissionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/permission/PermissionManagerServiceTest.java
@@ -69,8 +69,7 @@ public class PermissionManagerServiceTest {
MockitoAnnotations.initMocks(this);
mContext = InstrumentationRegistry.getContext();
- Object lock = new Object();
- mPermissionManagerService = new PermissionManagerService(mContext, lock, mInjector);
+ mPermissionManagerService = new PermissionManagerService(mContext, mInjector);
}
@After
diff --git a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
index af161ee8b818..ca0270deb398 100644
--- a/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/AttentionDetectorTest.java
@@ -70,7 +70,6 @@ public class AttentionDetectorTest extends AndroidTestCase {
private Runnable mOnUserAttention;
private TestableAttentionDetector mAttentionDetector;
private AttentionDetector mRealAttentionDetector;
- private long mPreDimCheckDuration;
private long mNextDimming;
private int mIsSettingEnabled;
@@ -342,23 +341,14 @@ public class AttentionDetectorTest extends AndroidTestCase {
public void testGetPostDimCheckDurationMillis_handlesGoodFlagValue() {
DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
KEY_POST_DIM_CHECK_DURATION_MILLIS, "333", false);
- assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis(
- DEFAULT_DIM_DURATION_MILLIS)).isEqualTo(333);
- }
-
- @Test
- public void testGetPostDimCheckDurationMillis_capsGoodFlagValueByMaxDimDuration() {
- DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
- KEY_POST_DIM_CHECK_DURATION_MILLIS, "7000", false);
- assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis(6500)).isEqualTo(6500);
+ assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis()).isEqualTo(333);
}
@Test
public void testGetPostDimCheckDurationMillis_rejectsNegativeValue() {
DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
KEY_POST_DIM_CHECK_DURATION_MILLIS, "-50", false);
- assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis(
- DEFAULT_DIM_DURATION_MILLIS)).isEqualTo(
+ assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis()).isEqualTo(
DEFAULT_POST_DIM_CHECK_DURATION_MILLIS);
}
@@ -366,8 +356,7 @@ public class AttentionDetectorTest extends AndroidTestCase {
public void testGetPostDimCheckDurationMillis_rejectsTooBigValue() {
DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
KEY_POST_DIM_CHECK_DURATION_MILLIS, "20000", false);
- assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis(
- DEFAULT_DIM_DURATION_MILLIS)).isEqualTo(
+ assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis()).isEqualTo(
DEFAULT_POST_DIM_CHECK_DURATION_MILLIS);
}
@@ -375,14 +364,12 @@ public class AttentionDetectorTest extends AndroidTestCase {
public void testGetPostDimCheckDurationMillis_handlesBadFlagValue() {
DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
KEY_POST_DIM_CHECK_DURATION_MILLIS, "20000k", false);
- assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis(
- DEFAULT_DIM_DURATION_MILLIS)).isEqualTo(
+ assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis()).isEqualTo(
DEFAULT_POST_DIM_CHECK_DURATION_MILLIS);
DeviceConfig.setProperty(NAMESPACE_ATTENTION_MANAGER_SERVICE,
KEY_POST_DIM_CHECK_DURATION_MILLIS, "0.25", false);
- assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis(
- DEFAULT_DIM_DURATION_MILLIS)).isEqualTo(
+ assertThat(mRealAttentionDetector.getPostDimCheckDurationMillis()).isEqualTo(
DEFAULT_POST_DIM_CHECK_DURATION_MILLIS);
}
@@ -423,7 +410,7 @@ public class AttentionDetectorTest extends AndroidTestCase {
}
private long registerAttention() {
- mPreDimCheckDuration = 4000L;
+ mAttentionDetector.mPreDimCheckDurationMillis = 4000L;
mAttentionDetector.onUserActivity(SystemClock.uptimeMillis(),
PowerManager.USER_ACTIVITY_EVENT_TOUCH);
return mAttentionDetector.updateUserActivity(mNextDimming, DEFAULT_DIM_DURATION_MILLIS);
@@ -447,10 +434,5 @@ public class AttentionDetectorTest extends AndroidTestCase {
public boolean isAttentionServiceSupported() {
return mAttentionServiceSupported;
}
-
- @Override
- public long getPreDimCheckDurationMillis() {
- return mPreDimCheckDuration;
- }
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index bf742b7f96dc..7ec8689e5387 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -19,6 +19,7 @@ import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
import static android.app.NotificationChannel.CONVERSATION_CHANNEL_ID_FORMAT;
+import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
@@ -3796,4 +3797,40 @@ public class PreferencesHelperTest extends UiServiceTestCase {
}
}
}
+
+ @Test
+ public void testUnlockNotificationChannelImportance() {
+ NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW);
+ mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false);
+ channel.lockFields(USER_LOCKED_IMPORTANCE);
+ assertTrue((channel.getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0);
+
+ mHelper.unlockNotificationChannelImportance(PKG_O, UID_O, channel.getId());
+ assertTrue((channel.getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0);
+
+ }
+
+ @Test
+ public void testUnlockAllNotificationChannels() {
+ NotificationChannel channelA = new NotificationChannel("a", "a", IMPORTANCE_LOW);
+ mHelper.createNotificationChannel(PKG_O, UID_O, channelA, true, false);
+ NotificationChannel channelB = new NotificationChannel("b", "b", IMPORTANCE_DEFAULT);
+ mHelper.createNotificationChannel(PKG_P, UID_P, channelB, true, false);
+ NotificationChannel channelC = new NotificationChannel("c", "c", IMPORTANCE_HIGH);
+ mHelper.createNotificationChannel(PKG_P, UID_O, channelC, false, false);
+
+ channelA.lockFields(USER_LOCKED_IMPORTANCE);
+ channelB.lockFields(USER_LOCKED_IMPORTANCE);
+ channelC.lockFields(USER_LOCKED_IMPORTANCE);
+
+ assertTrue((channelA.getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0);
+ assertTrue((channelB.getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0);
+ assertTrue((channelC.getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0);
+
+ mHelper.unlockAllNotificationChannels();
+ assertTrue((channelA.getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0);
+ assertTrue((channelB.getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0);
+ assertTrue((channelC.getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0);
+
+ }
}
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 f026b852f08c..5685ea5a336e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityDisplayTests.java
@@ -197,8 +197,7 @@ public class ActivityDisplayTests extends WindowTestsBase {
// Add activity that should be shown on the keyguard.
final ActivityRecord showWhenLockedActivity = new ActivityBuilder(mAtm)
- .setCreateTask(true)
- .setStack(stack)
+ .setTask(stack)
.setActivityFlags(FLAG_SHOW_WHEN_LOCKED)
.build();
@@ -225,8 +224,8 @@ public class ActivityDisplayTests extends WindowTestsBase {
final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
final Task alwaysOnTopStack = taskDisplayArea.createStack(WINDOWING_MODE_FREEFORM,
ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(alwaysOnTopStack).build();
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setTask(alwaysOnTopStack).build();
alwaysOnTopStack.setAlwaysOnTop(true);
taskDisplayArea.positionChildAt(POSITION_TOP, alwaysOnTopStack,
false /* includingParents */);
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 f1d3e1840588..0654968d0c2f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -362,8 +362,7 @@ public class ActivityMetricsLaunchObserverTests extends WindowTestsBase {
.setDisplay(addNewDisplayContentAt(DisplayContent.POSITION_BOTTOM))
.build();
final ActivityRecord activityOnNewDisplay = new ActivityBuilder(mAtm)
- .setStack(stack)
- .setCreateTask(true)
+ .setTask(stack)
.setProcessName("new")
.build();
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 f37834560fff..93666b4c46fe 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -131,8 +131,9 @@ public class ActivityRecordTests extends WindowTestsBase {
@Before
public void setUp() throws Exception {
- mStack = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
- mTask = mStack.getBottomMostTask();
+ mTask = new TaskBuilder(mSupervisor)
+ .setCreateParentTask(true).setCreateActivity(true).build();
+ mStack = mTask.getRootTask();
mActivity = mTask.getTopNonFinishingActivity();
setBooted(mAtm);
@@ -787,7 +788,7 @@ public class ActivityRecordTests extends WindowTestsBase {
// Have two tasks (topRootableTask and mTask) as the children of mStack.
ActivityRecord topActivity = new ActivityBuilder(mActivity.mAtmService)
.setCreateTask(true)
- .setStack(mStack)
+ .setParentTask(mStack)
.build();
Task topRootableTask = topActivity.getTask();
topRootableTask.moveToFront("test");
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 f9ad49bb5034..1d5dc43876d5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackSupervisorTests.java
@@ -71,8 +71,8 @@ public class ActivityStackSupervisorTests extends WindowTestsBase {
*/
@Test
public void testStoppingActivityRemovedWhenResumed() {
- final ActivityRecord firstActivity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(mFullscreenStack).build();
+ final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
+ .setTask(mFullscreenStack).build();
mSupervisor.mStoppingActivities.add(firstActivity);
firstActivity.completeResumeLocked();
@@ -85,8 +85,8 @@ public class ActivityStackSupervisorTests extends WindowTestsBase {
*/
@Test
public void testReportWaitingActivityLaunchedIfNeeded() {
- final ActivityRecord firstActivity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(mFullscreenStack).build();
+ final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
+ .setTask(mFullscreenStack).build();
final WaitResult taskToFrontWait = new WaitResult();
mSupervisor.mWaitingActivityLaunched.add(taskToFrontWait);
@@ -153,7 +153,7 @@ public class ActivityStackSupervisorTests extends WindowTestsBase {
@Test
public void testNotifyTaskFocusChanged() {
final ActivityRecord fullScreenActivityA = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(mFullscreenStack).build();
+ .setParentTask(mFullscreenStack).build();
final Task taskA = fullScreenActivityA.getTask();
final TaskChangeNotificationController taskChangeNotifier =
@@ -166,7 +166,7 @@ public class ActivityStackSupervisorTests extends WindowTestsBase {
reset(taskChangeNotifier);
final ActivityRecord fullScreenActivityB = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(mFullscreenStack).build();
+ .setParentTask(mFullscreenStack).build();
final Task taskB = fullScreenActivityB.getTask();
mAtm.setResumedActivityUncheckLocked(fullScreenActivityB, "resumeB");
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 b6323313dd27..3c5b9f9cee05 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -242,8 +242,7 @@ public class ActivityStackTests extends WindowTestsBase {
public void testRemoveOrganizedTask_UpdateStackReference() {
final Task rootHomeTask = mDefaultTaskDisplayArea.getRootHomeTask();
final ActivityRecord homeActivity = new ActivityBuilder(mAtm)
- .setStack(rootHomeTask)
- .setCreateTask(true)
+ .setTask(rootHomeTask)
.build();
final Task secondaryStack = mAtm.mTaskOrganizerController.createRootTask(
rootHomeTask.getDisplayContent(), WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, null);
@@ -291,7 +290,7 @@ public class ActivityStackTests extends WindowTestsBase {
@Test
public void testStopActivityWhenActivityDestroyed() {
- final ActivityRecord r = new ActivityBuilder(mAtm).setTask(mTask).build();
+ final ActivityRecord r = new ActivityBuilder(mAtm).setCreateTask(true).build();
r.info.flags |= ActivityInfo.FLAG_NO_HISTORY;
mStack.moveToFront("testStopActivityWithDestroy");
r.stopIfPossible();
@@ -303,7 +302,6 @@ public class ActivityStackTests extends WindowTestsBase {
public void testFindTaskWithOverlay() {
final ActivityRecord r = new ActivityBuilder(mAtm)
.setCreateTask(true)
- .setStack(mStack)
.setUid(0)
.build();
final Task task = r.getTask();
@@ -314,7 +312,7 @@ public class ActivityStackTests extends WindowTestsBase {
final RootWindowContainer.FindTaskResult result =
new RootWindowContainer.FindTaskResult();
- result.process(r, mStack);
+ result.process(r, task);
assertEquals(r, task.getTopNonFinishingActivity(false /* includeOverlays */));
assertEquals(taskOverlay, task.getTopNonFinishingActivity(true /* includeOverlays */));
@@ -355,9 +353,11 @@ public class ActivityStackTests extends WindowTestsBase {
final TaskDisplayArea taskDisplayArea = addNewDisplayContentAt(DisplayContent.POSITION_TOP)
.getDefaultTaskDisplayArea();
final Task stack1 = createStackForShouldBeVisibleTest(taskDisplayArea,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */,
+ true /* twoLevelTask */);
final Task stack2 = createStackForShouldBeVisibleTest(taskDisplayArea,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
+ WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */,
+ true /* twoLevelTask */);
// Do not move display to back because there is still another stack.
stack2.moveToBack("testMoveStackToBackIncludingParent", stack2.getTopMostTask());
@@ -377,8 +377,7 @@ public class ActivityStackTests extends WindowTestsBase {
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
// Add an activity to the pinned stack so it isn't considered empty for visibility check.
final ActivityRecord pinnedActivity = new ActivityBuilder(mAtm)
- .setCreateTask(true)
- .setStack(pinnedStack)
+ .setTask(pinnedStack)
.build();
assertTrue(homeStack.shouldBeVisible(null /* starting */));
@@ -676,8 +675,7 @@ public class ActivityStackTests extends WindowTestsBase {
translucentStack.getVisibility(null /* starting */));
// Add an activity to the pinned stack so it isn't considered empty for visibility check.
final ActivityRecord pinnedActivity = new ActivityBuilder(mAtm)
- .setCreateTask(true)
- .setStack(pinnedStack)
+ .setTask(pinnedStack)
.build();
assertEquals(STACK_VISIBILITY_VISIBLE, pinnedStack.getVisibility(null /* starting */));
}
@@ -689,8 +687,7 @@ public class ActivityStackTests extends WindowTestsBase {
ActivityRecord topRunningHomeActivity = homeStack.topRunningActivity();
if (topRunningHomeActivity == null) {
topRunningHomeActivity = new ActivityBuilder(mAtm)
- .setStack(homeStack)
- .setCreateTask(true)
+ .setTask(homeStack)
.build();
}
@@ -721,7 +718,7 @@ public class ActivityStackTests extends WindowTestsBase {
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, true /* onTop */);
final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
- .setStack(homeStack)
+ .setParentTask(homeStack)
.setCreateTask(true)
.build();
final Task task = firstActivity.getTask();
@@ -985,14 +982,29 @@ public class ActivityStackTests extends WindowTestsBase {
return stack;
}
- @SuppressWarnings("TypeParameterUnusedInFormals")
private Task createStackForShouldBeVisibleTest(
TaskDisplayArea taskDisplayArea, int windowingMode, int activityType, boolean onTop) {
+ return createStackForShouldBeVisibleTest(taskDisplayArea,
+ windowingMode, activityType, onTop, false /* twoLevelTask */);
+ }
+
+ @SuppressWarnings("TypeParameterUnusedInFormals")
+ private Task createStackForShouldBeVisibleTest(TaskDisplayArea taskDisplayArea,
+ int windowingMode, int activityType, boolean onTop, boolean twoLevelTask) {
final Task task;
if (activityType == ACTIVITY_TYPE_HOME) {
task = mDefaultTaskDisplayArea.getStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME);
mDefaultTaskDisplayArea.positionChildAt(onTop ? POSITION_TOP : POSITION_BOTTOM, task,
false /* includingParents */);
+ } else if (twoLevelTask) {
+ task = new TaskBuilder(mSupervisor)
+ .setTaskDisplayArea(taskDisplayArea)
+ .setWindowingMode(windowingMode)
+ .setActivityType(activityType)
+ .setOnTop(onTop)
+ .setCreateActivity(true)
+ .setCreateParentTask(true)
+ .build().getRootTask();
} else {
task = new TaskBuilder(mSupervisor)
.setTaskDisplayArea(taskDisplayArea)
@@ -1154,7 +1166,7 @@ public class ActivityStackTests extends WindowTestsBase {
ActivityRecord activity = homeStack.topRunningActivity();
if (activity == null) {
activity = new ActivityBuilder(mAtm)
- .setStack(homeStack)
+ .setParentTask(homeStack)
.setCreateTask(true)
.build();
}
@@ -1319,8 +1331,7 @@ public class ActivityStackTests extends WindowTestsBase {
@Test
public void testResetTaskWithFinishingActivities() {
- final ActivityRecord taskTop =
- new ActivityBuilder(mAtm).setStack(mStack).setCreateTask(true).build();
+ final ActivityRecord taskTop = new ActivityBuilder(mAtm).setTask(mStack).build();
// Make all activities in the task are finishing to simulate Task#getTopActivity
// returns null.
taskTop.finishing = true;
@@ -1334,10 +1345,8 @@ public class ActivityStackTests extends WindowTestsBase {
public void testIterateOccludedActivity() {
final ArrayList<ActivityRecord> occludedActivities = new ArrayList<>();
final Consumer<ActivityRecord> handleOccludedActivity = occludedActivities::add;
- final ActivityRecord bottomActivity =
- new ActivityBuilder(mAtm).setStack(mStack).setTask(mTask).build();
- final ActivityRecord topActivity =
- new ActivityBuilder(mAtm).setStack(mStack).setTask(mTask).build();
+ final ActivityRecord bottomActivity = new ActivityBuilder(mAtm).setTask(mTask).build();
+ final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(mTask).build();
// Top activity occludes bottom activity.
doReturn(true).when(mStack).shouldBeVisible(any());
assertTrue(topActivity.shouldBeVisible());
@@ -1355,8 +1364,7 @@ public class ActivityStackTests extends WindowTestsBase {
assertThat(occludedActivities).isEmpty();
// A finishing activity should not occlude other activities behind.
- final ActivityRecord finishingActivity =
- new ActivityBuilder(mAtm).setStack(mStack).setTask(mTask).build();
+ final ActivityRecord finishingActivity = new ActivityBuilder(mAtm).setTask(mTask).build();
finishingActivity.finishing = true;
doCallRealMethod().when(finishingActivity).occludesParent();
assertTrue(topActivity.shouldBeVisible());
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 3720e520b1b9..a7ced1df6125 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -486,7 +486,7 @@ public class ActivityStarterTests extends WindowTestsBase {
final ActivityStarter starter = prepareStarter(0);
final LockTaskController lockTaskController = mAtm.getLockTaskController();
- doReturn(true).when(lockTaskController).isLockTaskModeViolation(any());
+ doReturn(true).when(lockTaskController).isNewTaskLockTaskModeViolation(any());
final int result = starter.setReason("testTaskModeViolation").execute();
@@ -712,10 +712,10 @@ public class ActivityStarterTests extends WindowTestsBase {
// Put 2 tasks in the same stack (simulate the behavior of home stack).
final Task rootTask = new TaskBuilder(mSupervisor).build();
final ActivityRecord activity = new ActivityBuilder(mAtm)
- .setStack(rootTask)
+ .setParentTask(rootTask)
.setCreateTask(true).build();
new ActivityBuilder(mAtm)
- .setStack(activity.getRootTask())
+ .setParentTask(activity.getRootTask())
.setCreateTask(true).build();
// Create a top finishing activity.
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 0f5489575ee0..9d8710dc5cb2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AnimatingActivityRegistryTest.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyZeroInteractions;
@@ -63,8 +62,7 @@ public class AnimatingActivityRegistryTest extends WindowTestsBase {
@Test
public void testDeferring() {
- final ActivityRecord activity1 = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
final ActivityRecord activity2 = createAppWindow(activity1.getTask(), ACTIVITY_TYPE_STANDARD,
"activity2").mActivityRecord;
final AnimatingActivityRegistry registry =
@@ -87,8 +85,7 @@ public class AnimatingActivityRegistryTest extends WindowTestsBase {
@Test
public void testContainerRemoved() {
- final ActivityRecord window1 = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord window1 = createActivityRecord(mDisplayContent);
final ActivityRecord window2 = createAppWindow(window1.getTask(), ACTIVITY_TYPE_STANDARD,
"window2").mActivityRecord;
final AnimatingActivityRegistry registry =
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index 30502d8f1612..87a5985d507d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -58,7 +58,7 @@ public class AppChangeTransitionTests extends WindowTestsBase {
private ActivityRecord mActivity;
public void setUpOnDisplay(DisplayContent dc) {
- mActivity = createTestActivityRecord(dc, WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD);
+ mActivity = createActivityRecord(dc, WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD);
mTask = mActivity.getTask();
mStack = mTask.getRootTask();
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 c1212f598f67..bc4f16eccb0a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -132,13 +132,11 @@ public class AppTransitionControllerTest extends WindowTestsBase {
@Test
public void testGetAnimationTargets_visibilityAlreadyUpdated() {
- // [DisplayContent] -+- [TaskStack1] - [Task1] - [ActivityRecord1] (opening, visible)
- // +- [TaskStack2] - [Task2] - [ActivityRecord2] (closing, invisible)
- final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity1 = createTestActivityRecord(stack1);
+ // [DisplayContent] -+- [Task1] - [ActivityRecord1] (opening, visible)
+ // +- [Task2] - [ActivityRecord2] (closing, invisible)
+ final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
- final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity2 = createTestActivityRecord(stack2);
+ final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
activity2.setVisible(false);
activity2.mVisibleRequested = false;
@@ -161,16 +159,14 @@ public class AppTransitionControllerTest extends WindowTestsBase {
@Test
public void testGetAnimationTargets_visibilityAlreadyUpdated_butForcedTransitionRequested() {
- // [DisplayContent] -+- [TaskStack1] - [Task1] - [ActivityRecord1] (closing, invisible)
- // +- [TaskStack2] - [Task2] - [ActivityRecord2] (opening, visible)
- final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity1 = createTestActivityRecord(stack1);
+ // [DisplayContent] -+- [Task1] - [ActivityRecord1] (closing, invisible)
+ // +- [Task2] - [ActivityRecord2] (opening, visible)
+ final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
activity1.setVisible(true);
activity1.mVisibleRequested = true;
activity1.mRequestForceTransition = true;
- final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity2 = createTestActivityRecord(stack2);
+ final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
activity2.setVisible(false);
activity2.mVisibleRequested = false;
activity2.mRequestForceTransition = true;
@@ -195,10 +191,8 @@ public class AppTransitionControllerTest extends WindowTestsBase {
@Test
public void testGetAnimationTargets_exitingBeforeTransition() {
// Create another non-empty task so the animation target won't promote to task display area.
- createTestActivityRecord(
- mDisplayContent.getDefaultTaskDisplayArea().getOrCreateRootHomeTask());
- final Task stack = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity = createTestActivityRecord(stack);
+ createActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createActivityRecord(mDisplayContent);
activity.setVisible(false);
activity.mIsExiting = true;
@@ -208,19 +202,18 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// Animate closing apps even if it's not visible when it is exiting before we had a chance
// to play the transition animation.
assertEquals(
- new ArraySet<>(new WindowContainer[]{stack}),
+ new ArraySet<>(new WindowContainer[]{activity.getRootTask()}),
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 Task stack1 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity1 = createTestActivityRecord(stack1);
+ // [DisplayContent] -+- [Task1] - [ActivityRecord1] (opening, visible)
+ // +- [AppWindow1] (being-replaced)
+ // +- [Task2] - [ActivityRecord2] (closing, invisible)
+ // +- [AppWindow2] (being-replaced)
+ final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(
TYPE_BASE_APPLICATION);
attrs.setTitle("AppWindow1");
@@ -228,8 +221,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
appWindow1.mWillReplaceWindow = true;
activity1.addWindow(appWindow1);
- final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity2 = createTestActivityRecord(stack2);
+ final ActivityRecord activity2 = createActivityRecord(mDisplayContent);
activity2.setVisible(false);
activity2.mVisibleRequested = false;
attrs.setTitle("AppWindow2");
@@ -246,7 +238,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// Don't animate closing apps if it's already invisible even though its windows are being
// replaced.
assertEquals(
- new ArraySet<>(new WindowContainer[]{stack1}),
+ new ArraySet<>(new WindowContainer[]{activity1.getRootTask()}),
AppTransitionController.getAnimationTargets(
opening, closing, true /* visible */));
assertEquals(
@@ -257,24 +249,22 @@ public class AppTransitionControllerTest extends WindowTestsBase {
@Test
public void testGetAnimationTargets_openingClosingInDifferentTask() {
- // [DisplayContent] -+- [TaskStack1] - [Task1] -+- [ActivityRecord1] (opening, invisible)
- // | +- [ActivityRecord2] (invisible)
+ // [DisplayContent] -+- [Task1] -+- [ActivityRecord1] (opening, invisible)
+ // | +- [ActivityRecord2] (invisible)
// |
- // +- [TaskStack2] - [Task2] -+- [ActivityRecord3] (closing, visible)
- // +- [ActivityRecord4] (invisible)
- final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task1 = createTaskInStack(stack1, 0 /* userId */);
- final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task1);
+ // +- [Task2] -+- [ActivityRecord3] (closing, visible)
+ // +- [ActivityRecord4] (invisible)
+ final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
activity1.setVisible(false);
activity1.mVisibleRequested = true;
- final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task1);
+ final ActivityRecord activity2 = createActivityRecord(mDisplayContent,
+ activity1.getTask());
activity2.setVisible(false);
activity2.mVisibleRequested = false;
- final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
- final Task task2 = createTaskInStack(stack2, 0 /* userId */);
- final ActivityRecord activity3 = createActivityRecordInTask(mDisplayContent, task2);
- final ActivityRecord activity4 = createActivityRecordInTask(mDisplayContent, task2);
+ final ActivityRecord activity3 = createActivityRecord(mDisplayContent);
+ final ActivityRecord activity4 = createActivityRecord(mDisplayContent,
+ activity3.getTask());
activity4.setVisible(false);
activity4.mVisibleRequested = false;
@@ -286,25 +276,24 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// Promote animation targets to TaskStack level. Invisible ActivityRecords don't affect
// promotion decision.
assertEquals(
- new ArraySet<>(new WindowContainer[]{stack1}),
+ new ArraySet<>(new WindowContainer[]{activity1.getRootTask()}),
AppTransitionController.getAnimationTargets(
opening, closing, true /* visible */));
assertEquals(
- new ArraySet<>(new WindowContainer[]{stack2}),
+ new ArraySet<>(new WindowContainer[]{activity3.getRootTask()}),
AppTransitionController.getAnimationTargets(
opening, closing, false /* visible */));
}
@Test
public void testGetAnimationTargets_openingClosingInSameTask() {
- // [DisplayContent] - [TaskStack] - [Task] -+- [ActivityRecord1] (opening, invisible)
- // +- [ActivityRecord2] (closing, visible)
- final Task stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task);
+ // [DisplayContent] - [Task] -+- [ActivityRecord1] (opening, invisible)
+ // +- [ActivityRecord2] (closing, visible)
+ final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
activity1.setVisible(false);
activity1.mVisibleRequested = true;
- final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity2 = createActivityRecord(mDisplayContent,
+ activity1.getTask());
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -325,26 +314,24 @@ public class AppTransitionControllerTest extends WindowTestsBase {
@Test
public void testGetAnimationTargets_animateOnlyTranslucentApp() {
- // [DisplayContent] -+- [TaskStack1] - [Task1] -+- [ActivityRecord1] (opening, invisible)
- // | +- [ActivityRecord2] (visible)
+ // [DisplayContent] -+- [Task1] -+- [ActivityRecord1] (opening, invisible)
+ // | +- [ActivityRecord2] (visible)
// |
- // +- [TaskStack2] - [Task2] -+- [ActivityRecord3] (closing, visible)
- // +- [ActivityRecord4] (visible)
+ // +- [Task2] -+- [ActivityRecord3] (closing, visible)
+ // +- [ActivityRecord4] (visible)
- final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task1 = createTaskInStack(stack1, 0 /* userId */);
- final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task1);
+ final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
activity1.setVisible(false);
activity1.mVisibleRequested = true;
activity1.setOccludesParent(false);
- final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task1);
+ final ActivityRecord activity2 = createActivityRecord(mDisplayContent,
+ activity1.getTask());
- final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
- final Task task2 = createTaskInStack(stack2, 0 /* userId */);
- final ActivityRecord activity3 = createActivityRecordInTask(mDisplayContent, task2);
+ final ActivityRecord activity3 = createActivityRecord(mDisplayContent);
activity3.setOccludesParent(false);
- final ActivityRecord activity4 = createActivityRecordInTask(mDisplayContent, task2);
+ final ActivityRecord activity4 = createActivityRecord(mDisplayContent,
+ activity3.getTask());
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -365,28 +352,26 @@ public class AppTransitionControllerTest extends WindowTestsBase {
@Test
public void testGetAnimationTargets_animateTranslucentAndOpaqueApps() {
- // [DisplayContent] -+- [TaskStack1] - [Task1] -+- [ActivityRecord1] (opening, invisible)
- // | +- [ActivityRecord2] (opening, invisible)
+ // [DisplayContent] -+- [Task1] -+- [ActivityRecord1] (opening, invisible)
+ // | +- [ActivityRecord2] (opening, invisible)
// |
- // +- [TaskStack2] - [Task2] -+- [ActivityRecord3] (closing, visible)
- // +- [ActivityRecord4] (closing, visible)
+ // +- [Task2] -+- [ActivityRecord3] (closing, visible)
+ // +- [ActivityRecord4] (closing, visible)
- final Task stack1 = createTaskStackOnDisplay(mDisplayContent);
- final Task task1 = createTaskInStack(stack1, 0 /* userId */);
- final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task1);
+ final ActivityRecord activity1 = createActivityRecord(mDisplayContent);
activity1.setVisible(false);
activity1.mVisibleRequested = true;
activity1.setOccludesParent(false);
- final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task1);
+ final ActivityRecord activity2 = createActivityRecord(mDisplayContent,
+ activity1.getTask());
activity2.setVisible(false);
activity2.mVisibleRequested = true;
- final Task stack2 = createTaskStackOnDisplay(mDisplayContent);
- final Task task2 = createTaskInStack(stack2, 0 /* userId */);
- final ActivityRecord activity3 = createActivityRecordInTask(mDisplayContent, task2);
+ final ActivityRecord activity3 = createActivityRecord(mDisplayContent);
activity3.setOccludesParent(false);
- final ActivityRecord activity4 = createActivityRecordInTask(mDisplayContent, task2);
+ final ActivityRecord activity4 = createActivityRecord(mDisplayContent,
+ activity3.getTask());
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -398,26 +383,24 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// 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}),
+ new ArraySet<>(new WindowContainer[]{activity1.getRootTask()}),
AppTransitionController.getAnimationTargets(
opening, closing, true /* visible */));
assertEquals(
- new ArraySet<>(new WindowContainer[]{stack2}),
+ new ArraySet<>(new WindowContainer[]{activity3.getRootTask()}),
AppTransitionController.getAnimationTargets(
opening, closing, false /* visible */));
}
@Test
- public void testGetAnimationTargets_stackContainsMultipleTasks() {
- // [DisplayContent] - [TaskStack] -+- [Task1] - [ActivityRecord1] (opening, invisible)
- // +- [Task2] - [ActivityRecord2] (closing, visible)
- final Task stack = createTaskStackOnDisplay(mDisplayContent);
- final Task task1 = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task1);
+ public void testGetAnimationTargets_taskContainsMultipleTasks() {
+ // [DisplayContent] - [Task] -+- [Task1] - [ActivityRecord1] (opening, invisible)
+ // +- [Task2] - [ActivityRecord2] (closing, visible)
+ final Task parentTask = createTaskStackOnDisplay(mDisplayContent);
+ final ActivityRecord activity1 = createActivityRecordWithParentTask(parentTask);
activity1.setVisible(false);
activity1.mVisibleRequested = true;
- final Task task2 = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task2);
+ final ActivityRecord activity2 = createActivityRecordWithParentTask(parentTask);
final ArraySet<ActivityRecord> opening = new ArraySet<>();
opening.add(activity1);
@@ -426,11 +409,11 @@ public class AppTransitionControllerTest extends WindowTestsBase {
// Promote animation targets up to Task level, not beyond.
assertEquals(
- new ArraySet<>(new WindowContainer[]{task1}),
+ new ArraySet<>(new WindowContainer[]{activity1.getTask()}),
AppTransitionController.getAnimationTargets(
opening, closing, true /* visible */));
assertEquals(
- new ArraySet<>(new WindowContainer[]{task2}),
+ new ArraySet<>(new WindowContainer[]{activity2.getTask()}),
AppTransitionController.getAnimationTargets(
opening, closing, false /* visible */));
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 485f92f3eef3..850e72e8e94b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -16,8 +16,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.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
@@ -116,10 +114,8 @@ public class AppTransitionTests extends WindowTestsBase {
final DisplayContent dc2 = createNewDisplay(Display.STATE_ON);
// Create 2 app window tokens to represent 2 activity window.
- final ActivityRecord activity1 = createTestActivityRecord(dc1,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- final ActivityRecord activity2 = createTestActivityRecord(dc2,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord activity1 = createActivityRecord(dc1);
+ final ActivityRecord activity2 = createActivityRecord(dc2);
activity1.allDrawn = true;
activity1.startingDisplayed = true;
@@ -153,7 +149,7 @@ public class AppTransitionTests extends WindowTestsBase {
final Task stack1 = createTaskStackOnDisplay(dc1);
final Task task1 = createTaskInStack(stack1, 0 /* userId */);
- final ActivityRecord activity1 = createTestActivityRecord(dc1);
+ final ActivityRecord activity1 = createNonAttachedActivityRecord(dc1);
task1.addChild(activity1, 0);
// Simulate same app is during opening / closing transition set stage.
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
index b93a8fcc115b..fd562c3f90b2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
@@ -16,9 +16,6 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
@@ -31,7 +28,6 @@ import static org.mockito.ArgumentMatchers.intThat;
import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import org.junit.Before;
@@ -62,8 +58,7 @@ public class AppWindowTokenAnimationTests extends WindowTestsBase {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- mActivity = createTestActivityRecord(mDisplayContent, WINDOWING_MODE_FULLSCREEN,
- ACTIVITY_TYPE_STANDARD);
+ mActivity = createActivityRecord(mDisplayContent);
}
@Test
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 6837e0e9248d..28d5ffe342a0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -92,7 +92,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
public void setUp() throws Exception {
mStack = createTaskStackOnDisplay(mDisplayContent);
mTask = createTaskInStack(mStack, 0 /* userId */);
- mActivity = createTestActivityRecord(mDisplayContent);
+ mActivity = createNonAttachedActivityRecord(mDisplayContent);
mTask.addChild(mActivity, 0);
}
@@ -307,7 +307,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
assertEquals(Configuration.ORIENTATION_PORTRAIT, displayConfig.orientation);
assertEquals(Configuration.ORIENTATION_PORTRAIT, activityConfig.orientation);
- final ActivityRecord topActivity = createTestActivityRecord(mStack);
+ final ActivityRecord topActivity = createActivityRecord(mTask);
topActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
assertEquals(Configuration.ORIENTATION_LANDSCAPE, displayConfig.orientation);
@@ -490,7 +490,7 @@ public class AppWindowTokenTests extends WindowTestsBase {
}
private ActivityRecord createTestActivityRecordForGivenTask(Task task) {
- final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
task.addChild(activity, 0);
waitUntilHandlersIdle();
return activity;
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java
index 9a668b91c656..4a5a81e89cd7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaGroupTest.java
@@ -67,7 +67,7 @@ public class DisplayAreaGroupTest extends WindowTestsBase {
mDisplayAreaGroup.addChild(mTaskDisplayArea, POSITION_TOP);
mStack = mTaskDisplayArea.createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- mActivity = new ActivityBuilder(mAtm).setCreateTask(true).setStack(mStack).build();
+ mActivity = new ActivityBuilder(mAtm).setTask(mStack).build();
mDisplayContent.setLastFocusedTaskDisplayArea(mTaskDisplayArea);
}
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 f52f98389872..fbfc0e09584b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -16,7 +16,6 @@
package com.android.server.wm;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -283,8 +282,7 @@ public class DisplayContentTests extends WindowTestsBase {
@UseTestDisplay(addAllCommonWindows = true)
@Test
public void testComputeImeTarget_startingWindow() {
- ActivityRecord activity = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ ActivityRecord activity = createActivityRecord(mDisplayContent);
final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, activity,
"startingWin");
@@ -328,7 +326,7 @@ public class DisplayContentTests extends WindowTestsBase {
assertEquals(dc, stack.getDisplayContent());
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity = createTestActivityRecord(dc);
+ final ActivityRecord activity = createNonAttachedActivityRecord(dc);
task.addChild(activity, 0);
assertEquals(dc, task.getDisplayContent());
assertEquals(dc, activity.getDisplayContent());
@@ -399,14 +397,14 @@ public class DisplayContentTests extends WindowTestsBase {
// Add stack with activity.
final Task stack0 = createTaskStackOnDisplay(dc0);
final Task task0 = createTaskInStack(stack0, 0 /* userId */);
- final ActivityRecord activity = createTestActivityRecord(dc0);
+ final ActivityRecord activity = createNonAttachedActivityRecord(dc0);
task0.addChild(activity, 0);
dc0.configureDisplayPolicy();
assertNotNull(dc0.mTapDetector);
final Task stack1 = createTaskStackOnDisplay(dc1);
final Task task1 = createTaskInStack(stack1, 0 /* userId */);
- final ActivityRecord activity1 = createTestActivityRecord(dc0);
+ final ActivityRecord activity1 = createNonAttachedActivityRecord(dc0);
task1.addChild(activity1, 0);
dc1.configureDisplayPolicy();
assertNotNull(dc1.mTapDetector);
@@ -1223,7 +1221,7 @@ public class DisplayContentTests extends WindowTestsBase {
// Launch another activity before the transition is finished.
final Task task2 = new TaskBuilder(mSupervisor).setDisplay(mDisplayContent).build();
- final ActivityRecord app2 = new ActivityBuilder(mAtm).setStack(task2)
+ final ActivityRecord app2 = new ActivityBuilder(mAtm).setTask(task2)
.setUseProcess(app.app).build();
app2.setVisible(false);
mDisplayContent.mOpeningApps.add(app2);
@@ -1260,8 +1258,7 @@ public class DisplayContentTests extends WindowTestsBase {
@Test
public void testFinishFixedRotationNoAppTransitioningTask() {
unblockDisplayRotation(mDisplayContent);
- final ActivityRecord app = createActivityRecord(mDisplayContent, WINDOWING_MODE_FULLSCREEN,
- ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord app = createActivityRecord(mDisplayContent);
final Task task = app.getTask();
final ActivityRecord app2 = new ActivityBuilder(mWm.mAtmService).setTask(task).build();
mDisplayContent.setFixedRotationLaunchingApp(app2, (mDisplayContent.getRotation() + 1) % 4);
@@ -1314,8 +1311,7 @@ public class DisplayContentTests extends WindowTestsBase {
final ActivityRecord pinnedActivity = createActivityRecord(displayContent,
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
final Task pinnedTask = pinnedActivity.getRootTask();
- final ActivityRecord homeActivity = createTestActivityRecord(
- displayContent.getDefaultTaskDisplayArea().getOrCreateRootHomeTask());
+ final ActivityRecord homeActivity = createActivityRecord(displayContent);
if (displayConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
homeActivity.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
pinnedActivity.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
@@ -1378,10 +1374,8 @@ public class DisplayContentTests extends WindowTestsBase {
// Skip freezing so the unrelated conditions in updateRotationUnchecked won't disturb.
doNothing().when(mWm).startFreezingDisplay(anyInt(), anyInt(), any(), anyInt());
- final ActivityRecord activity = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- final ActivityRecord recentsActivity = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_RECENTS);
+ final ActivityRecord activity = createActivityRecord(mDisplayContent);
+ final ActivityRecord recentsActivity = createActivityRecord(mDisplayContent);
recentsActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
// Do not rotate if the recents animation is animating on top.
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java
new file mode 100644
index 000000000000..b346bb810b2e
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsProviderTests.java
@@ -0,0 +1,367 @@
+/*
+ * 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.wm;
+
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.annotation.Nullable;
+import android.platform.test.annotations.Presubmit;
+import android.util.Xml;
+import android.view.Display;
+import android.view.DisplayAddress;
+import android.view.DisplayInfo;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.server.wm.DisplayWindowSettings.SettingsProvider.SettingsEntry;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.xmlpull.v1.XmlPullParser;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Tests for the {@link DisplayWindowSettingsProvider} class.
+ *
+ * Build/Install/Run:
+ * atest WmTests:DisplayWindowSettingsProviderTests
+ */
+@SmallTest
+@Presubmit
+@WindowTestsBase.UseTestDisplay
+@RunWith(WindowTestRunner.class)
+public class DisplayWindowSettingsProviderTests extends WindowTestsBase {
+ private static final int DISPLAY_PORT = 0xFF;
+ private static final long DISPLAY_MODEL = 0xEEEEEEEEL;
+
+ private static final File TEST_FOLDER = getInstrumentation().getTargetContext().getCacheDir();
+
+ private TestStorage mBaseSettingsStorage;
+ private TestStorage mOverrideSettingsStorage;
+
+ private DisplayContent mPrimaryDisplay;
+ private DisplayContent mSecondaryDisplay;
+
+ @Before
+ public void setUp() throws Exception {
+ deleteRecursively(TEST_FOLDER);
+
+ mBaseSettingsStorage = new TestStorage();
+ mOverrideSettingsStorage = new TestStorage();
+
+ mPrimaryDisplay = mWm.getDefaultDisplayContentLocked();
+ mSecondaryDisplay = mDisplayContent;
+ assertNotEquals(Display.DEFAULT_DISPLAY, mSecondaryDisplay.getDisplayId());
+ }
+
+ @After
+ public void tearDown() {
+ deleteRecursively(TEST_FOLDER);
+ }
+
+ @Test
+ public void testReadingDisplaySettingsFromStorage() {
+ final String displayIdentifier = mSecondaryDisplay.getDisplayInfo().uniqueId;
+ prepareOverrideDisplaySettings(displayIdentifier);
+
+ SettingsEntry expectedSettings = new SettingsEntry();
+ expectedSettings.mWindowingMode = WINDOWING_MODE_PINNED;
+ readAndAssertExpectedSettings(mPrimaryDisplay, expectedSettings);
+ }
+
+ @Test
+ public void testReadingDisplaySettingsFromStorage_LegacyDisplayId() {
+ final String displayIdentifier = mPrimaryDisplay.getDisplayInfo().name;
+ prepareOverrideDisplaySettings(displayIdentifier);
+
+ SettingsEntry expectedSettings = new SettingsEntry();
+ expectedSettings.mWindowingMode = WINDOWING_MODE_PINNED;
+ readAndAssertExpectedSettings(mPrimaryDisplay, expectedSettings);
+ }
+
+ @Test
+ public void testReadingDisplaySettingsFromStorage_LegacyDisplayId_UpdateAfterAccess()
+ throws Exception {
+ // Store display settings with legacy display identifier.
+ final DisplayInfo mPrimaryDisplayInfo = mPrimaryDisplay.getDisplayInfo();
+ final String displayIdentifier = mPrimaryDisplayInfo.name;
+ prepareOverrideDisplaySettings(displayIdentifier);
+
+ // Update settings with new value, should trigger write to injector.
+ DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider(
+ mBaseSettingsStorage, mOverrideSettingsStorage);
+ SettingsEntry overrideSettings = provider.getOverrideSettings(mPrimaryDisplayInfo);
+ overrideSettings.mForcedDensity = 200;
+ provider.updateOverrideSettings(mPrimaryDisplayInfo, overrideSettings);
+ assertTrue(mOverrideSettingsStorage.wasWriteSuccessful());
+
+ // Verify that display identifier was updated.
+ final String newDisplayIdentifier = getStoredDisplayAttributeValue(
+ mOverrideSettingsStorage, "name");
+ assertEquals("Display identifier must be updated to use uniqueId",
+ mPrimaryDisplayInfo.uniqueId, newDisplayIdentifier);
+ }
+
+ @Test
+ public void testReadingDisplaySettingsFromStorage_UsePortAsId() {
+ final DisplayAddress.Physical displayAddress =
+ DisplayAddress.fromPortAndModel(DISPLAY_PORT, DISPLAY_MODEL);
+ mPrimaryDisplay.getDisplayInfo().address = displayAddress;
+
+ final String displayIdentifier = "port:" + DISPLAY_PORT;
+ prepareOverrideDisplaySettings(displayIdentifier, true /* usePortAsId */);
+
+ SettingsEntry expectedSettings = new SettingsEntry();
+ expectedSettings.mWindowingMode = WINDOWING_MODE_PINNED;
+ readAndAssertExpectedSettings(mPrimaryDisplay, expectedSettings);
+ }
+
+ @Test
+ public void testReadingDisplaySettingsFromStorage_UsePortAsId_IncorrectAddress() {
+ final String displayIdentifier = mPrimaryDisplay.getDisplayInfo().uniqueId;
+ prepareOverrideDisplaySettings(displayIdentifier, true /* usePortAsId */);
+
+ mPrimaryDisplay.getDisplayInfo().address = DisplayAddress.fromPhysicalDisplayId(123456);
+
+ // Verify that the entry is not matched and default settings are returned instead.
+ SettingsEntry expectedSettings = new SettingsEntry();
+ readAndAssertExpectedSettings(mPrimaryDisplay, expectedSettings);
+ }
+
+ @Test
+ public void testWritingDisplaySettingsToStorage() throws Exception {
+ final DisplayInfo secondaryDisplayInfo = mSecondaryDisplay.getDisplayInfo();
+
+ // Write some settings to storage.
+ DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider(
+ mBaseSettingsStorage, mOverrideSettingsStorage);
+ SettingsEntry overrideSettings = provider.getOverrideSettings(secondaryDisplayInfo);
+ overrideSettings.mShouldShowSystemDecors = true;
+ overrideSettings.mShouldShowIme = true;
+ provider.updateOverrideSettings(secondaryDisplayInfo, overrideSettings);
+ assertTrue(mOverrideSettingsStorage.wasWriteSuccessful());
+
+ // Verify that settings were stored correctly.
+ assertEquals("Attribute value must be stored", secondaryDisplayInfo.uniqueId,
+ getStoredDisplayAttributeValue(mOverrideSettingsStorage, "name"));
+ assertEquals("Attribute value must be stored", "true",
+ getStoredDisplayAttributeValue(mOverrideSettingsStorage, "shouldShowSystemDecors"));
+ assertEquals("Attribute value must be stored", "true",
+ getStoredDisplayAttributeValue(mOverrideSettingsStorage, "shouldShowIme"));
+ }
+
+ @Test
+ public void testWritingDisplaySettingsToStorage_UsePortAsId() throws Exception {
+ prepareOverrideDisplaySettings(null /* displayIdentifier */, true /* usePortAsId */);
+
+ // Store config to use port as identifier.
+ final DisplayInfo secondaryDisplayInfo = mSecondaryDisplay.getDisplayInfo();
+ final DisplayAddress.Physical displayAddress =
+ DisplayAddress.fromPortAndModel(DISPLAY_PORT, DISPLAY_MODEL);
+ secondaryDisplayInfo.address = displayAddress;
+
+ // Write some settings to storage.
+ DisplayWindowSettingsProvider provider = new DisplayWindowSettingsProvider(
+ mBaseSettingsStorage, mOverrideSettingsStorage);
+ SettingsEntry overrideSettings = provider.getOverrideSettings(secondaryDisplayInfo);
+ overrideSettings.mShouldShowSystemDecors = true;
+ overrideSettings.mShouldShowIme = true;
+ provider.updateOverrideSettings(secondaryDisplayInfo, overrideSettings);
+ assertTrue(mOverrideSettingsStorage.wasWriteSuccessful());
+
+ // Verify that settings were stored correctly.
+ assertEquals("Attribute value must be stored", "port:" + DISPLAY_PORT,
+ getStoredDisplayAttributeValue(mOverrideSettingsStorage, "name"));
+ assertEquals("Attribute value must be stored", "true",
+ getStoredDisplayAttributeValue(mOverrideSettingsStorage, "shouldShowSystemDecors"));
+ assertEquals("Attribute value must be stored", "true",
+ getStoredDisplayAttributeValue(mOverrideSettingsStorage, "shouldShowIme"));
+ }
+
+ /**
+ * Prepares display settings and stores in {@link #mOverrideSettingsStorage}. Uses provided
+ * display identifier and stores windowingMode=WINDOWING_MODE_PINNED.
+ */
+ private void prepareOverrideDisplaySettings(String displayIdentifier) {
+ prepareOverrideDisplaySettings(displayIdentifier, false /* usePortAsId */);
+ }
+
+ private void prepareOverrideDisplaySettings(String displayIdentifier, boolean usePortAsId) {
+ String contents = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ + "<display-settings>\n";
+ if (usePortAsId) {
+ contents += " <config identifier=\"1\"/>\n";
+ }
+ if (displayIdentifier != null) {
+ contents += " <display\n"
+ + " name=\"" + displayIdentifier + "\"\n"
+ + " windowingMode=\"" + WINDOWING_MODE_PINNED + "\"/>\n";
+ }
+ contents += "</display-settings>\n";
+
+ final InputStream is = new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8));
+ mOverrideSettingsStorage.setReadStream(is);
+ }
+
+ private void readAndAssertExpectedSettings(DisplayContent displayContent,
+ SettingsEntry expectedSettings) {
+ final DisplayWindowSettingsProvider provider =
+ new DisplayWindowSettingsProvider(mBaseSettingsStorage, mOverrideSettingsStorage);
+ assertEquals(expectedSettings, provider.getSettings(displayContent.getDisplayInfo()));
+ }
+
+ @Nullable
+ private String getStoredDisplayAttributeValue(TestStorage storage, String attr)
+ throws Exception {
+ try (InputStream stream = storage.openRead()) {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(stream, StandardCharsets.UTF_8.name());
+ int type;
+ while ((type = parser.next()) != XmlPullParser.START_TAG
+ && type != XmlPullParser.END_DOCUMENT) {
+ // Do nothing.
+ }
+
+ if (type != XmlPullParser.START_TAG) {
+ throw new IllegalStateException("no start tag found");
+ }
+
+ int outerDepth = parser.getDepth();
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ String tagName = parser.getName();
+ if (tagName.equals("display")) {
+ return parser.getAttributeValue(null, attr);
+ }
+ }
+ } finally {
+ storage.closeRead();
+ }
+ return null;
+ }
+
+ private static boolean deleteRecursively(File file) {
+ boolean fullyDeleted = true;
+ if (file.isFile()) {
+ return file.delete();
+ } else if (file.isDirectory()) {
+ final File[] files = file.listFiles();
+ for (File child : files) {
+ fullyDeleted &= deleteRecursively(child);
+ }
+ fullyDeleted &= file.delete();
+ }
+ return fullyDeleted;
+ }
+
+ /** In-memory storage implementation. */
+ public class TestStorage implements DisplayWindowSettingsProvider.WritableSettingsStorage {
+ private InputStream mReadStream;
+ private ByteArrayOutputStream mWriteStream;
+
+ private boolean mWasSuccessful;
+
+ /**
+ * Returns input stream for reading. By default tries forward the output stream if previous
+ * write was successful.
+ * @see #closeRead()
+ */
+ @Override
+ public InputStream openRead() throws FileNotFoundException {
+ if (mReadStream == null && mWasSuccessful) {
+ mReadStream = new ByteArrayInputStream(mWriteStream.toByteArray());
+ }
+ if (mReadStream == null) {
+ throw new FileNotFoundException();
+ }
+ if (mReadStream.markSupported()) {
+ mReadStream.mark(Integer.MAX_VALUE);
+ }
+ return mReadStream;
+ }
+
+ /** Must be called after each {@link #openRead} to reset the position in the stream. */
+ void closeRead() throws IOException {
+ if (mReadStream == null) {
+ throw new FileNotFoundException();
+ }
+ if (mReadStream.markSupported()) {
+ mReadStream.reset();
+ }
+ mReadStream = null;
+ }
+
+ /**
+ * Creates new or resets existing output stream for write. Automatically closes previous
+ * read stream, since following reads should happen based on this new write.
+ */
+ @Override
+ public OutputStream startWrite() throws IOException {
+ if (mWriteStream == null) {
+ mWriteStream = new ByteArrayOutputStream();
+ } else {
+ mWriteStream.reset();
+ }
+ if (mReadStream != null) {
+ closeRead();
+ }
+ return mWriteStream;
+ }
+
+ @Override
+ public void finishWrite(OutputStream os, boolean success) {
+ mWasSuccessful = success;
+ try {
+ os.close();
+ } catch (IOException e) {
+ // This method can't throw IOException since the super implementation doesn't, so
+ // we just wrap it in a RuntimeException so we end up crashing the test all the
+ // same.
+ throw new RuntimeException(e);
+ }
+ }
+
+ /** Overrides the read stream of the injector. By default it uses current write stream. */
+ private void setReadStream(InputStream is) {
+ mReadStream = is;
+ }
+
+ private boolean wasWriteSuccessful() {
+ return mWasSuccessful;
+ }
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index a3d3739a9015..2ca5583c48c3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -17,15 +17,12 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT;
import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_DISABLED;
import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_ENABLED;
import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY;
import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY;
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
@@ -40,12 +37,11 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Matchers.eq;
+import android.annotation.NonNull;
import android.app.WindowConfiguration;
import android.content.res.Configuration;
import android.platform.test.annotations.Presubmit;
-import android.util.Xml;
import android.view.Display;
-import android.view.DisplayAddress;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -53,21 +49,14 @@ import androidx.test.filters.SmallTest;
import com.android.server.LocalServices;
import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.wm.DisplayWindowSettings.SettingsProvider.SettingsEntry;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.xmlpull.v1.XmlPullParser;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
/**
* Tests for the {@link DisplayWindowSettings} class.
@@ -80,12 +69,8 @@ import java.nio.charset.StandardCharsets;
@WindowTestsBase.UseTestDisplay
@RunWith(WindowTestRunner.class)
public class DisplayWindowSettingsTests extends WindowTestsBase {
-
- private static final int DISPLAY_PORT = 0xFF;
- private static final long DISPLAY_MODEL = 0xEEEEEEEEL;
-
- private static final File TEST_FOLDER = getInstrumentation().getTargetContext().getCacheDir();
- private DisplayWindowSettings mTarget;
+ private TestSettingsProvider mSettingsProvider;
+ private DisplayWindowSettings mDisplayWindowSettings;
private DisplayInfo mPrivateDisplayInfo;
@@ -93,18 +78,19 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
private DisplayContent mSecondaryDisplay;
private DisplayContent mPrivateDisplay;
- private TestStorage mStorage;
-
@Before
public void setUp() throws Exception {
- deleteRecursively(TEST_FOLDER);
-
+ // TODO(b/121296525): We may want to restore other display settings (not only overscans in
+ // testPersistOverscan*test) on mPrimaryDisplay and mSecondaryDisplay back to default
+ // values after each test finishes, since we are going to reuse a singleton
+ // WindowManagerService instance among all tests that extend {@link WindowTestsBase} class
+ // (b/113239988).
mWm.mAtmService.mSupportsFreeformWindowManagement = false;
mWm.setIsPc(false);
mWm.setForceDesktopModeOnExternalDisplays(false);
- mStorage = new TestStorage();
- mTarget = new DisplayWindowSettings(mWm, mStorage);
+ mSettingsProvider = new TestSettingsProvider();
+ mDisplayWindowSettings = new DisplayWindowSettings(mWm, mSettingsProvider);
mPrimaryDisplay = mWm.getDefaultDisplayContentLocked();
mSecondaryDisplay = mDisplayContent;
@@ -117,20 +103,9 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
assertNotEquals(mSecondaryDisplay.getDisplayId(), mPrivateDisplay.getDisplayId());
}
- @After
- public void tearDown() {
- deleteRecursively(TEST_FOLDER);
-
- // TODO(b/121296525): We may want to restore other display settings (not only overscans in
- // testPersistOverscan*test) on mPrimaryDisplay and mSecondaryDisplay back to default
- // values after each test finishes, since we are going to reuse a singleton
- // WindowManagerService instance among all tests that extend {@link WindowTestsBase} class
- // (b/113239988).
- }
-
@Test
public void testPrimaryDisplayDefaultToFullscreen_NoFreeformSupport() {
- mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mPrimaryDisplay);
assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
mPrimaryDisplay.getWindowingMode());
@@ -140,7 +115,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
public void testPrimaryDisplayDefaultToFullscreen_HasFreeformSupport_NonPc_NoDesktopMode() {
mWm.mAtmService.mSupportsFreeformWindowManagement = true;
- mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mPrimaryDisplay);
assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
mPrimaryDisplay.getWindowingMode());
@@ -151,7 +126,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
mWm.mAtmService.mSupportsFreeformWindowManagement = true;
mWm.setForceDesktopModeOnExternalDisplays(true);
- mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mPrimaryDisplay);
assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
mPrimaryDisplay.getWindowingMode());
@@ -162,20 +137,19 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
mWm.mAtmService.mSupportsFreeformWindowManagement = true;
mWm.setIsPc(true);
- mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mPrimaryDisplay);
- assertEquals(WINDOWING_MODE_FREEFORM,
- mPrimaryDisplay.getWindowingMode());
+ assertEquals(WINDOWING_MODE_FREEFORM, mPrimaryDisplay.getWindowingMode());
}
@Test
public void testPrimaryDisplayUpdateToFreeform_HasFreeformSupport_IsPc() {
- mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mPrimaryDisplay);
mWm.mAtmService.mSupportsFreeformWindowManagement = true;
mWm.setIsPc(true);
- mTarget.updateSettingsForDisplay(mPrimaryDisplay);
+ mDisplayWindowSettings.updateSettingsForDisplay(mPrimaryDisplay);
assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM,
mPrimaryDisplay.getWindowingMode());
@@ -183,7 +157,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
@Test
public void testSecondaryDisplayDefaultToFullscreen_NoFreeformSupport() {
- mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay);
assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
mSecondaryDisplay.getWindowingMode());
@@ -193,7 +167,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
public void testSecondaryDisplayDefaultToFreeform_HasFreeformSupport_NonPc_NoDesktopMode() {
mWm.mAtmService.mSupportsFreeformWindowManagement = true;
- mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay);
assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
mSecondaryDisplay.getWindowingMode());
@@ -204,7 +178,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
mWm.mAtmService.mSupportsFreeformWindowManagement = true;
mWm.setForceDesktopModeOnExternalDisplays(true);
- mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay);
assertEquals(WINDOWING_MODE_FREEFORM,
mSecondaryDisplay.getWindowingMode());
@@ -215,7 +189,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
mWm.mAtmService.mSupportsFreeformWindowManagement = true;
mWm.setIsPc(true);
- mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay);
assertEquals(WINDOWING_MODE_FREEFORM,
mSecondaryDisplay.getWindowingMode());
@@ -228,7 +202,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
final int originalDensity = mSecondaryDisplay.mBaseDisplayDensity;
final boolean originalScalingDisabled = mSecondaryDisplay.mDisplayScalingDisabled;
- mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay);
assertEquals(originalWidth, mSecondaryDisplay.mBaseDisplayWidth);
assertEquals(originalHeight, mSecondaryDisplay.mBaseDisplayHeight);
@@ -245,8 +219,9 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
return null;
}).when(mWm.mDisplayManagerInternal).getNonOverrideDisplayInfo(anyInt(), any());
- mTarget.setForcedSize(mSecondaryDisplay, 1000 /* width */, 2000 /* height */);
- applySettingsToDisplayByNewInstance(mSecondaryDisplay);
+ mDisplayWindowSettings.setForcedSize(mSecondaryDisplay, 1000 /* width */,
+ 2000 /* height */);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay);
assertEquals(1000 /* width */, mSecondaryDisplay.mBaseDisplayWidth);
assertEquals(2000 /* height */, mSecondaryDisplay.mBaseDisplayHeight);
@@ -258,8 +233,9 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
@Test
public void testSetForcedDensity() {
- mTarget.setForcedDensity(mSecondaryDisplay, 600 /* density */, 0 /* userId */);
- applySettingsToDisplayByNewInstance(mSecondaryDisplay);
+ mDisplayWindowSettings.setForcedDensity(mSecondaryDisplay, 600 /* density */,
+ 0 /* userId */);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay);
assertEquals(600 /* density */, mSecondaryDisplay.mBaseDisplayDensity);
@@ -270,8 +246,9 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
@Test
public void testSetForcedScalingMode() {
- mTarget.setForcedScalingMode(mSecondaryDisplay, DisplayContent.FORCE_SCALING_MODE_DISABLED);
- applySettingsToDisplayByNewInstance(mSecondaryDisplay);
+ mDisplayWindowSettings.setForcedScalingMode(mSecondaryDisplay,
+ DisplayContent.FORCE_SCALING_MODE_DISABLED);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay);
assertTrue(mSecondaryDisplay.mDisplayScalingDisabled);
@@ -282,7 +259,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
@Test
public void testDefaultToFreeUserRotation() {
- mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay);
final DisplayRotation rotation = mSecondaryDisplay.getDisplayRotation();
assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, rotation.getUserRotationMode());
@@ -291,7 +268,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
@Test
public void testDefaultTo0DegRotation() {
- mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay);
assertEquals(Surface.ROTATION_0, mSecondaryDisplay.getDisplayRotation().getUserRotation());
}
@@ -299,70 +276,68 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
@Test
public void testPrivateDisplayDefaultToDestroyContent() {
assertEquals(REMOVE_CONTENT_MODE_DESTROY,
- mTarget.getRemoveContentModeLocked(mPrivateDisplay));
+ mDisplayWindowSettings.getRemoveContentModeLocked(mPrivateDisplay));
}
@Test
public void testPublicDisplayDefaultToMoveToPrimary() {
assertEquals(REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY,
- mTarget.getRemoveContentModeLocked(mSecondaryDisplay));
+ mDisplayWindowSettings.getRemoveContentModeLocked(mSecondaryDisplay));
}
@Test
public void testDefaultToNotShowWithInsecureKeyguard() {
- assertFalse(mTarget.shouldShowWithInsecureKeyguardLocked(mPrivateDisplay));
- assertFalse(mTarget.shouldShowWithInsecureKeyguardLocked(mSecondaryDisplay));
+ assertFalse(mDisplayWindowSettings.shouldShowWithInsecureKeyguardLocked(mPrivateDisplay));
+ assertFalse(mDisplayWindowSettings.shouldShowWithInsecureKeyguardLocked(mSecondaryDisplay));
}
- @Test
+ @Test(expected = IllegalArgumentException.class)
public void testPublicDisplayNotAllowSetShouldShowWithInsecureKeyguard() {
- mTarget.setShouldShowWithInsecureKeyguardLocked(mSecondaryDisplay, true);
-
- assertFalse(mTarget.shouldShowWithInsecureKeyguardLocked(mSecondaryDisplay));
+ mDisplayWindowSettings.setShouldShowWithInsecureKeyguardLocked(mSecondaryDisplay, true);
}
@Test
public void testPrivateDisplayAllowSetShouldShowWithInsecureKeyguard() {
- mTarget.setShouldShowWithInsecureKeyguardLocked(mPrivateDisplay, true);
+ mDisplayWindowSettings.setShouldShowWithInsecureKeyguardLocked(mPrivateDisplay, true);
- assertTrue(mTarget.shouldShowWithInsecureKeyguardLocked(mPrivateDisplay));
+ assertTrue(mDisplayWindowSettings.shouldShowWithInsecureKeyguardLocked(mPrivateDisplay));
}
@Test
public void testPrimaryDisplayShouldShowSystemDecors() {
- assertTrue(mTarget.shouldShowSystemDecorsLocked(mPrimaryDisplay));
+ assertTrue(mDisplayWindowSettings.shouldShowSystemDecorsLocked(mPrimaryDisplay));
- mTarget.setShouldShowSystemDecorsLocked(mPrimaryDisplay, false);
+ mDisplayWindowSettings.setShouldShowSystemDecorsLocked(mPrimaryDisplay, false);
// Default display should show system decors
- assertTrue(mTarget.shouldShowSystemDecorsLocked(mPrimaryDisplay));
+ assertTrue(mDisplayWindowSettings.shouldShowSystemDecorsLocked(mPrimaryDisplay));
}
@Test
public void testSecondaryDisplayDefaultToNotShowSystemDecors() {
- assertFalse(mTarget.shouldShowSystemDecorsLocked(mSecondaryDisplay));
+ assertFalse(mDisplayWindowSettings.shouldShowSystemDecorsLocked(mSecondaryDisplay));
}
@Test
public void testPrimaryDisplayShouldShowIme() {
- assertTrue(mTarget.shouldShowImeLocked(mPrimaryDisplay));
+ assertTrue(mDisplayWindowSettings.shouldShowImeLocked(mPrimaryDisplay));
- mTarget.setShouldShowImeLocked(mPrimaryDisplay, false);
+ mDisplayWindowSettings.setShouldShowImeLocked(mPrimaryDisplay, false);
- assertTrue(mTarget.shouldShowImeLocked(mPrimaryDisplay));
+ assertTrue(mDisplayWindowSettings.shouldShowImeLocked(mPrimaryDisplay));
}
@Test
public void testSecondaryDisplayDefaultToNotShowIme() {
- assertFalse(mTarget.shouldShowImeLocked(mSecondaryDisplay));
+ assertFalse(mDisplayWindowSettings.shouldShowImeLocked(mSecondaryDisplay));
}
@Test
- public void testPersistUserRotationModeInSameInstance() {
- mTarget.setUserRotation(mSecondaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
- Surface.ROTATION_90);
+ public void testSetUserRotationMode() {
+ mDisplayWindowSettings.setUserRotation(mSecondaryDisplay,
+ WindowManagerPolicy.USER_ROTATION_LOCKED, Surface.ROTATION_90);
- mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay);
final DisplayRotation rotation = mSecondaryDisplay.getDisplayRotation();
assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, rotation.getUserRotationMode());
@@ -370,48 +345,25 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
}
@Test
- public void testPersistUserRotationInSameInstance() {
- mTarget.setUserRotation(mSecondaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
- Surface.ROTATION_90);
+ public void testSetUserRotation() {
+ mDisplayWindowSettings.setUserRotation(mSecondaryDisplay,
+ WindowManagerPolicy.USER_ROTATION_LOCKED, Surface.ROTATION_90);
- mTarget.applySettingsToDisplayLocked(mSecondaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay);
assertEquals(Surface.ROTATION_90, mSecondaryDisplay.getDisplayRotation().getUserRotation());
}
@Test
- public void testPersistUserRotationModeAcrossInstances() {
- mTarget.setUserRotation(mSecondaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
- Surface.ROTATION_270);
-
- applySettingsToDisplayByNewInstance(mSecondaryDisplay);
-
- final DisplayRotation rotation = mSecondaryDisplay.getDisplayRotation();
- assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, rotation.getUserRotationMode());
- assertTrue(rotation.isRotationFrozen());
- }
-
- @Test
- public void testPersistUserRotationAcrossInstances() {
- mTarget.setUserRotation(mSecondaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
- Surface.ROTATION_270);
-
- applySettingsToDisplayByNewInstance(mSecondaryDisplay);
-
- assertEquals(Surface.ROTATION_270,
- mSecondaryDisplay.getDisplayRotation().getUserRotation());
- }
-
- @Test
public void testFixedToUserRotationDefault() {
- mTarget.setUserRotation(mPrimaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
- Surface.ROTATION_0);
+ mDisplayWindowSettings.setUserRotation(mPrimaryDisplay,
+ WindowManagerPolicy.USER_ROTATION_LOCKED, Surface.ROTATION_0);
final DisplayRotation displayRotation = mock(DisplayRotation.class);
spyOn(mPrimaryDisplay);
doReturn(displayRotation).when(mPrimaryDisplay).getDisplayRotation();
- mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mPrimaryDisplay);
verify(displayRotation).restoreSettings(anyInt(), anyInt(),
eq(FIXED_TO_USER_ROTATION_DEFAULT));
@@ -419,13 +371,14 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
@Test
public void testSetFixedToUserRotationDisabled() {
- mTarget.setFixedToUserRotation(mPrimaryDisplay, FIXED_TO_USER_ROTATION_DISABLED);
+ mDisplayWindowSettings.setFixedToUserRotation(mPrimaryDisplay,
+ FIXED_TO_USER_ROTATION_DISABLED);
final DisplayRotation displayRotation = mock(DisplayRotation.class);
spyOn(mPrimaryDisplay);
doReturn(displayRotation).when(mPrimaryDisplay).getDisplayRotation();
- applySettingsToDisplayByNewInstance(mPrimaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mPrimaryDisplay);
verify(displayRotation).restoreSettings(anyInt(), anyInt(),
eq(FIXED_TO_USER_ROTATION_DISABLED));
@@ -433,120 +386,20 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
@Test
public void testSetFixedToUserRotationEnabled() {
- mTarget.setFixedToUserRotation(mPrimaryDisplay, FIXED_TO_USER_ROTATION_ENABLED);
+ mDisplayWindowSettings.setFixedToUserRotation(mPrimaryDisplay,
+ FIXED_TO_USER_ROTATION_ENABLED);
final DisplayRotation displayRotation = mock(DisplayRotation.class);
spyOn(mPrimaryDisplay);
doReturn(displayRotation).when(mPrimaryDisplay).getDisplayRotation();
- applySettingsToDisplayByNewInstance(mPrimaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mPrimaryDisplay);
verify(displayRotation).restoreSettings(anyInt(), anyInt(),
eq(FIXED_TO_USER_ROTATION_ENABLED));
}
@Test
- public void testReadingDisplaySettingsFromStorage() {
- final String displayIdentifier = mSecondaryDisplay.getDisplayInfo().uniqueId;
- prepareDisplaySettings(displayIdentifier);
-
- readAndAssertDisplaySettings(mPrimaryDisplay);
- }
-
- @Test
- public void testReadingDisplaySettingsFromStorage_LegacyDisplayId() {
- final String displayIdentifier = mPrimaryDisplay.getDisplayInfo().name;
- prepareDisplaySettings(displayIdentifier);
-
- readAndAssertDisplaySettings(mPrimaryDisplay);
- }
-
- @Test
- public void testReadingDisplaySettingsFromStorage_LegacyDisplayId_UpdateAfterAccess()
- throws Exception {
- // Store display settings with legacy display identifier.
- final String displayIdentifier = mPrimaryDisplay.getDisplayInfo().name;
- prepareDisplaySettings(displayIdentifier);
-
- // Update settings with new value, should trigger write to injector.
- final DisplayWindowSettings settings = new DisplayWindowSettings(mWm, mStorage);
- settings.setRemoveContentModeLocked(mPrimaryDisplay, REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY);
- assertEquals("Settings value must be updated", REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY,
- settings.getRemoveContentModeLocked(mPrimaryDisplay));
- assertTrue(mStorage.wasWriteSuccessful());
-
- // Verify that display identifier was updated.
- final String newDisplayIdentifier = getStoredDisplayAttributeValue("name");
- assertEquals("Display identifier must be updated to use uniqueId",
- mPrimaryDisplay.getDisplayInfo().uniqueId, newDisplayIdentifier);
- }
-
- @Test
- public void testReadingDisplaySettingsFromStorage_UsePortAsId() {
- final DisplayAddress.Physical displayAddress =
- DisplayAddress.fromPortAndModel(DISPLAY_PORT, DISPLAY_MODEL);
- mPrimaryDisplay.getDisplayInfo().address = displayAddress;
-
- final String displayIdentifier = "port:" + DISPLAY_PORT;
- prepareDisplaySettings(displayIdentifier, true /* usePortAsId */);
-
- readAndAssertDisplaySettings(mPrimaryDisplay);
- }
-
- @Test
- public void testReadingDisplaySettingsFromStorage_UsePortAsId_IncorrectAddress() {
- final String displayIdentifier = mPrimaryDisplay.getDisplayInfo().uniqueId;
- prepareDisplaySettings(displayIdentifier, true /* usePortAsId */);
-
- mPrimaryDisplay.getDisplayInfo().address = DisplayAddress.fromPhysicalDisplayId(123456);
-
- // Verify that the entry is not matched and default settings are returned instead.
- final DisplayWindowSettings settings = new DisplayWindowSettings(mWm);
- assertNotEquals("Default setting must be returned for new entry",
- WINDOWING_MODE_PINNED, settings.getWindowingModeLocked(mPrimaryDisplay));
- }
-
- @Test
- public void testWritingDisplaySettingsToStorage() throws Exception {
- // Write some settings to storage.
- final DisplayWindowSettings settings = new DisplayWindowSettings(mWm, mStorage);
- settings.setShouldShowSystemDecorsLocked(mSecondaryDisplay, true);
- settings.setShouldShowImeLocked(mSecondaryDisplay, true);
- assertTrue(mStorage.wasWriteSuccessful());
-
- // Verify that settings were stored correctly.
- assertEquals("Attribute value must be stored", mSecondaryDisplay.getDisplayInfo().uniqueId,
- getStoredDisplayAttributeValue("name"));
- assertEquals("Attribute value must be stored", "true",
- getStoredDisplayAttributeValue("shouldShowSystemDecors"));
- assertEquals("Attribute value must be stored", "true",
- getStoredDisplayAttributeValue("shouldShowIme"));
- }
-
- @Test
- public void testWritingDisplaySettingsToStorage_UsePortAsId() throws Exception {
- // Store config to use port as identifier.
- final DisplayAddress.Physical displayAddress =
- DisplayAddress.fromPortAndModel(DISPLAY_PORT, DISPLAY_MODEL);
- mSecondaryDisplay.getDisplayInfo().address = displayAddress;
- prepareDisplaySettings(null /* displayIdentifier */, true /* usePortAsId */);
-
- // Write some settings.
- final DisplayWindowSettings settings = new DisplayWindowSettings(mWm, mStorage);
- settings.setShouldShowSystemDecorsLocked(mSecondaryDisplay, true);
- settings.setShouldShowImeLocked(mSecondaryDisplay, true);
- assertTrue(mStorage.wasWriteSuccessful());
-
- // Verify that settings were stored correctly.
- assertEquals("Attribute value must be stored", "port:" + DISPLAY_PORT,
- getStoredDisplayAttributeValue("name"));
- assertEquals("Attribute value must be stored", "true",
- getStoredDisplayAttributeValue("shouldShowSystemDecors"));
- assertEquals("Attribute value must be stored", "true",
- getStoredDisplayAttributeValue("shouldShowIme"));
- }
-
- @Test
public void testShouldShowImeWithinForceDesktopMode() {
try {
// Presume display enabled force desktop mode from developer options.
@@ -567,14 +420,13 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
public void testDisplayWindowSettingsAppliedOnDisplayReady() {
// Set forced densities for two displays in DisplayWindowSettings
final DisplayContent dc = createMockSimulatedDisplay();
- final DisplayWindowSettings settings = new DisplayWindowSettings(mWm, mStorage);
- settings.setForcedDensity(mPrimaryDisplay, 123, 0 /* userId */);
- settings.setForcedDensity(dc, 456, 0 /* userId */);
+ mDisplayWindowSettings.setForcedDensity(mPrimaryDisplay, 123, 0 /* userId */);
+ mDisplayWindowSettings.setForcedDensity(dc, 456, 0 /* userId */);
// Apply settings to displays - the settings will be stored, but config will not be
// recalculated immediately.
- settings.applySettingsToDisplayLocked(mPrimaryDisplay);
- settings.applySettingsToDisplayLocked(dc);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(mPrimaryDisplay);
+ mDisplayWindowSettings.applySettingsToDisplayLocked(dc);
assertFalse(mPrimaryDisplay.mWaitingForConfig);
assertFalse(dc.mWaitingForConfig);
@@ -589,173 +441,34 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
assertEquals(456, config.densityDpi);
}
- /**
- * Prepares display settings and stores in {@link #mStorage}. Uses provided display identifier
- * and stores windowingMode=WINDOWING_MODE_PINNED.
- */
- private void prepareDisplaySettings(String displayIdentifier) {
- prepareDisplaySettings(displayIdentifier, false /* usePortAsId */);
- }
-
- private void prepareDisplaySettings(String displayIdentifier, boolean usePortAsId) {
- String contents = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
- + "<display-settings>\n";
- if (usePortAsId) {
- contents += " <config identifier=\"1\"/>\n";
- }
- if (displayIdentifier != null) {
- contents += " <display\n"
- + " name=\"" + displayIdentifier + "\"\n"
- + " windowingMode=\"" + WINDOWING_MODE_PINNED + "\"/>\n";
- }
- contents += "</display-settings>\n";
-
- final InputStream is = new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8));
- mStorage.setReadStream(is);
- }
-
- private void readAndAssertDisplaySettings(DisplayContent displayContent) {
- final DisplayWindowSettings settings = new DisplayWindowSettings(mWm, mStorage);
- assertEquals("Stored setting must be read",
- WINDOWING_MODE_PINNED, settings.getWindowingModeLocked(displayContent));
- assertEquals("Not stored setting must be set to default value",
- REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY,
- settings.getRemoveContentModeLocked(displayContent));
- }
-
- private String getStoredDisplayAttributeValue(String attr) throws Exception {
- try (InputStream stream = mStorage.openRead()) {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(stream, StandardCharsets.UTF_8.name());
- int type;
- while ((type = parser.next()) != XmlPullParser.START_TAG
- && type != XmlPullParser.END_DOCUMENT) {
- // Do nothing.
- }
-
- if (type != XmlPullParser.START_TAG) {
- throw new IllegalStateException("no start tag found");
- }
-
- int outerDepth = parser.getDepth();
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
-
- String tagName = parser.getName();
- if (tagName.equals("display")) {
- return parser.getAttributeValue(null, attr);
- }
- }
- } finally {
- mStorage.closeRead();
- }
- return null;
- }
-
- /**
- * This method helps to ensure read and write persistent settings successfully because the
- * constructor of {@link DisplayWindowSettings} should read the persistent file from the given
- * path that also means the previous state must be written correctly.
- */
- private void applySettingsToDisplayByNewInstance(DisplayContent display) {
- // Assert that prior write completed successfully.
- assertTrue(mStorage.wasWriteSuccessful());
-
- // Read and apply settings.
- new DisplayWindowSettings(mWm, mStorage).applySettingsToDisplayLocked(display);
- }
-
- private static boolean deleteRecursively(File file) {
- boolean fullyDeleted = true;
- if (file.isFile()) {
- return file.delete();
- } else if (file.isDirectory()) {
- final File[] files = file.listFiles();
- for (File child : files) {
- fullyDeleted &= deleteRecursively(child);
- }
- fullyDeleted &= file.delete();
- }
- return fullyDeleted;
- }
-
- /** In-memory storage implementation. */
- public class TestStorage implements DisplayWindowSettings.SettingPersister {
- private InputStream mReadStream;
- private ByteArrayOutputStream mWriteStream;
+ public final class TestSettingsProvider implements DisplayWindowSettings.SettingsProvider {
+ Map<DisplayInfo, SettingsEntry> mOverrideSettingsCache = new HashMap<>();
- private boolean mWasSuccessful;
-
- /**
- * Returns input stream for reading. By default tries forward the output stream if previous
- * write was successful.
- * @see #closeRead()
- */
@Override
- public InputStream openRead() throws FileNotFoundException {
- if (mReadStream == null && mWasSuccessful) {
- mReadStream = new ByteArrayInputStream(mWriteStream.toByteArray());
- }
- if (mReadStream == null) {
- throw new FileNotFoundException();
- }
- if (mReadStream.markSupported()) {
- mReadStream.mark(Integer.MAX_VALUE);
- }
- return mReadStream;
- }
-
- /** Must be called after each {@link #openRead} to reset the position in the stream. */
- void closeRead() throws IOException {
- if (mReadStream == null) {
- throw new FileNotFoundException();
- }
- if (mReadStream.markSupported()) {
- mReadStream.reset();
- }
- mReadStream = null;
+ public SettingsEntry getSettings(@NonNull DisplayInfo info) {
+ return getOverrideSettings(info);
}
- /**
- * Creates new or resets existing output stream for write. Automatically closes previous
- * read stream, since following reads should happen based on this new write.
- */
@Override
- public OutputStream startWrite() throws IOException {
- if (mWriteStream == null) {
- mWriteStream = new ByteArrayOutputStream();
- } else {
- mWriteStream.reset();
- }
- if (mReadStream != null) {
- closeRead();
+ public SettingsEntry getOverrideSettings(@NonNull DisplayInfo info) {
+ SettingsEntry result = new SettingsEntry();
+ SettingsEntry overrideSettings = mOverrideSettingsCache.get(info);
+ if (overrideSettings != null) {
+ result.setTo(overrideSettings);
}
- return mWriteStream;
+ return result;
}
@Override
- public void finishWrite(OutputStream os, boolean success) {
- mWasSuccessful = success;
- try {
- os.close();
- } catch (IOException e) {
- // This method can't throw IOException since the super implementation doesn't, so
- // we just wrap it in a RuntimeException so we end up crashing the test all the
- // same.
- throw new RuntimeException(e);
+ public void updateOverrideSettings(@NonNull DisplayInfo info,
+ @NonNull SettingsEntry settings) {
+ SettingsEntry overrideSettings = mOverrideSettingsCache.get(info);
+ if (overrideSettings == null) {
+ overrideSettings = new SettingsEntry();
+ mOverrideSettingsCache.put(info, overrideSettings);
}
- }
-
- /** Override the read stream of the injector. By default it uses current write stream. */
- private void setReadStream(InputStream is) {
- mReadStream = is;
- }
- private boolean wasWriteSuccessful() {
- return mWasSuccessful;
+ overrideSettings.setTo(settings);
}
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index 823aef095831..5cb3ac1d3dd5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -118,7 +118,7 @@ public class DragDropControllerTests extends WindowTestsBase {
* Creates a window state which can be used as a drop target.
*/
private WindowState createDropTargetWindow(String name, int ownerId) {
- final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
final Task stack = createTaskStackOnDisplay(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent);
final Task task = createTaskInStack(stack, ownerId);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index a1606d3502ad..02d9c4251767 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -82,7 +82,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
addWindow(TYPE_STATUS_BAR, "statusBar");
addWindow(TYPE_NAVIGATION_BAR, "navBar");
- final WindowState win = createWindowOnStack(null, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
+ final WindowState win = createWindow(null, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app");
final InsetsSourceControl[] controls = addWindowAndGetControlsForDispatch(win);
@@ -95,7 +95,7 @@ public class InsetsPolicyTest extends WindowTestsBase {
addWindow(TYPE_STATUS_BAR, "statusBar");
addWindow(TYPE_NAVIGATION_BAR, "navBar");
- final WindowState win = createWindowOnStack(null, WINDOWING_MODE_FREEFORM,
+ final WindowState win = createWindow(null, WINDOWING_MODE_FREEFORM,
ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app");
final InsetsSourceControl[] controls = addWindowAndGetControlsForDispatch(win);
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 044f81986517..bf718a7c4528 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
@@ -50,6 +50,11 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_ALLOWLISTED;
+import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_DONT_LOCK;
+import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE;
+import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
+import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_PINNABLE;
import static com.android.server.wm.LockTaskController.STATUS_BAR_MASK_LOCKED;
import static com.android.server.wm.LockTaskController.STATUS_BAR_MASK_PINNED;
@@ -169,7 +174,7 @@ public class LockTaskControllerTest {
@Test
public void testStartLockTaskMode_once() throws Exception {
// GIVEN a task record with allowlisted auth
- Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
// WHEN calling setLockTaskMode for LOCKED mode without resuming
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
@@ -186,8 +191,8 @@ public class LockTaskControllerTest {
@Test
public void testStartLockTaskMode_twice() throws Exception {
// GIVEN two task records with allowlisted auth
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
- Task tr2 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr2 = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
// WHEN calling setLockTaskMode for LOCKED mode on both tasks
mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
@@ -206,7 +211,7 @@ public class LockTaskControllerTest {
@Test
public void testStartLockTaskMode_pinningRequest() {
// GIVEN a task record that is not allowlisted, i.e. with pinned auth
- Task tr = getTask(Task.LOCK_TASK_AUTH_PINNABLE);
+ Task tr = getTask(LOCK_TASK_AUTH_PINNABLE);
// WHEN calling startLockTaskMode
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
@@ -218,7 +223,7 @@ public class LockTaskControllerTest {
@Test
public void testStartLockTaskMode_pinnedBySystem() throws Exception {
// GIVEN a task record with pinned auth
- Task tr = getTask(Task.LOCK_TASK_AUTH_PINNABLE);
+ Task tr = getTask(LOCK_TASK_AUTH_PINNABLE);
// WHEN the system calls startLockTaskMode
mLockTaskController.startLockTaskMode(tr, true, SYSTEM_UID);
@@ -237,41 +242,39 @@ public class LockTaskControllerTest {
@Test
public void testLockTaskViolation() {
// GIVEN one task record with allowlisted auth that is in lock task mode
- Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// THEN it's not a lock task violation to try and launch this task without clearing
assertFalse(mLockTaskController.isLockTaskModeViolation(tr, false));
// THEN it's a lock task violation to launch another task that is not allowlisted
- assertTrue(mLockTaskController.isLockTaskModeViolation(getTask(
- Task.LOCK_TASK_AUTH_PINNABLE)));
+ assertTrue(mLockTaskController.isLockTaskModeViolation(getTask(LOCK_TASK_AUTH_PINNABLE)));
// THEN it's a lock task violation to launch another task that is disallowed from lock task
- assertTrue(mLockTaskController.isLockTaskModeViolation(getTask(
- Task.LOCK_TASK_AUTH_DONT_LOCK)));
+ assertTrue(mLockTaskController.isLockTaskModeViolation(getTask(LOCK_TASK_AUTH_DONT_LOCK)));
// THEN it's no a lock task violation to launch another task that is allowlisted
assertFalse(mLockTaskController.isLockTaskModeViolation(getTask(
- Task.LOCK_TASK_AUTH_ALLOWLISTED)));
+ LOCK_TASK_AUTH_ALLOWLISTED)));
assertFalse(mLockTaskController.isLockTaskModeViolation(getTask(
- Task.LOCK_TASK_AUTH_LAUNCHABLE)));
+ LOCK_TASK_AUTH_LAUNCHABLE)));
// THEN it's not a lock task violation to launch another task that is priv launchable
assertFalse(mLockTaskController.isLockTaskModeViolation(getTask(
- Task.LOCK_TASK_AUTH_LAUNCHABLE_PRIV)));
+ LOCK_TASK_AUTH_LAUNCHABLE_PRIV)));
}
@Test
public void testLockTaskViolation_emergencyCall() {
// GIVEN one task record with allowlisted auth that is in lock task mode
- Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// GIVEN tasks necessary for emergency calling
Task keypad = getTask(new Intent().setComponent(EMERGENCY_DIALER_COMPONENT),
- Task.LOCK_TASK_AUTH_PINNABLE);
+ LOCK_TASK_AUTH_PINNABLE);
Task callAction = getTask(new Intent(Intent.ACTION_CALL_EMERGENCY),
- Task.LOCK_TASK_AUTH_PINNABLE);
- Task dialer = getTask("com.example.dialer", Task.LOCK_TASK_AUTH_PINNABLE);
+ LOCK_TASK_AUTH_PINNABLE);
+ Task dialer = getTask("com.example.dialer", LOCK_TASK_AUTH_PINNABLE);
when(mTelecomManager.getSystemDialerPackage())
.thenReturn(dialer.intent.getComponent().getPackageName());
@@ -295,7 +298,7 @@ public class LockTaskControllerTest {
@Test
public void testStopLockTaskMode() throws Exception {
// GIVEN one task record with allowlisted auth that is in lock task mode
- Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// WHEN the same caller calls stopLockTaskMode
@@ -312,7 +315,7 @@ public class LockTaskControllerTest {
@Test(expected = SecurityException.class)
public void testStopLockTaskMode_differentCaller() {
// GIVEN one task record with allowlisted auth that is in lock task mode
- Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// WHEN a different caller calls stopLockTaskMode
@@ -324,7 +327,7 @@ public class LockTaskControllerTest {
@Test
public void testStopLockTaskMode_systemCaller() {
// GIVEN one task record with allowlisted auth that is in lock task mode
- Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// WHEN system calls stopLockTaskMode
@@ -337,8 +340,8 @@ public class LockTaskControllerTest {
@Test
public void testStopLockTaskMode_twoTasks() throws Exception {
// GIVEN two task records with allowlisted auth that is in lock task mode
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
- Task tr2 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr2 = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);
@@ -358,8 +361,8 @@ public class LockTaskControllerTest {
@Test
public void testStopLockTaskMode_rootTask() throws Exception {
// GIVEN two task records with allowlisted auth that is in lock task mode
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
- Task tr2 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr2 = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);
@@ -379,7 +382,7 @@ public class LockTaskControllerTest {
@Test
public void testStopLockTaskMode_pinned() throws Exception {
// GIVEN one task records that is in pinned mode
- Task tr = getTask(Task.LOCK_TASK_AUTH_PINNABLE);
+ Task tr = getTask(LOCK_TASK_AUTH_PINNABLE);
mLockTaskController.startLockTaskMode(tr, true, SYSTEM_UID);
// GIVEN that the keyguard is required to show after unlocking
Settings.Secure.putInt(mContext.getContentResolver(),
@@ -406,8 +409,8 @@ public class LockTaskControllerTest {
@Test
public void testClearLockedTasks() throws Exception {
// GIVEN two task records with allowlisted auth that is in lock task mode
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
- Task tr2 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr2 = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);
@@ -434,7 +437,7 @@ public class LockTaskControllerTest {
.thenReturn(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
// AND there is a task record
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr1, true, TEST_UID);
// WHEN calling clearLockedTasks on the root task
@@ -454,7 +457,7 @@ public class LockTaskControllerTest {
.thenReturn(true);
// AND there is a task record
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr1, true, TEST_UID);
// WHEN calling clearLockedTasks on the root task
@@ -471,7 +474,7 @@ public class LockTaskControllerTest {
Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, 1, mContext.getUserId());
// AND there is a task record
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr1, true, TEST_UID);
// WHEN calling clearLockedTasks on the root task
@@ -488,7 +491,7 @@ public class LockTaskControllerTest {
Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, 0, mContext.getUserId());
// AND there is a task record
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr1 = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr1, true, TEST_UID);
// WHEN calling clearLockedTasks on the root task
@@ -574,7 +577,7 @@ public class LockTaskControllerTest {
@Test
public void testUpdateLockTaskFeatures() throws Exception {
// GIVEN a locked task
- Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// THEN lock task mode should be started with default status bar masks
@@ -616,7 +619,7 @@ public class LockTaskControllerTest {
@Test
public void testUpdateLockTaskFeatures_differentUser() throws Exception {
// GIVEN a locked task
- Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// THEN lock task mode should be started with default status bar masks
@@ -638,7 +641,7 @@ public class LockTaskControllerTest {
@Test
public void testUpdateLockTaskFeatures_keyguard() {
// GIVEN a locked task
- Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// THEN keyguard should be disabled
@@ -704,7 +707,7 @@ public class LockTaskControllerTest {
TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT));
// Start lock task mode
- Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr = getTask(LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// WHEN LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK is not enabled
@@ -758,14 +761,13 @@ public class LockTaskControllerTest {
* @param isAppAware {@code true} if the app has marked if allowlisted in its manifest
*/
private Task getTaskForUpdate(String pkg, boolean isAppAware) {
- final int authIfAllowlisted = isAppAware
- ? Task.LOCK_TASK_AUTH_LAUNCHABLE
- : Task.LOCK_TASK_AUTH_ALLOWLISTED;
+ final int authIfAllowlisted =
+ isAppAware ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_ALLOWLISTED;
Task tr = getTask(pkg, authIfAllowlisted);
doAnswer((invocation) -> {
boolean isAllowlisted =
mLockTaskController.isPackageAllowlisted(TEST_USER_ID, pkg);
- tr.mLockTaskAuth = isAllowlisted ? authIfAllowlisted : Task.LOCK_TASK_AUTH_PINNABLE;
+ tr.mLockTaskAuth = isAllowlisted ? authIfAllowlisted : LOCK_TASK_AUTH_PINNABLE;
return null;
}).when(tr).setLockTaskAuth();
return tr;
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 bea0d8e60c40..d348389a44b1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -474,6 +474,28 @@ public class RecentTasksTest extends WindowTestsBase {
}
@Test
+ public void testAppendOrganizedChildTaskInfo() {
+ final Task root = createTaskBuilder(".CreatedByOrganizerRoot").build();
+ root.mCreatedByOrganizer = true;
+ // Add organized and non-organized child.
+ final Task child1 = createTaskBuilder(".Task1").setParentTask(root).build();
+ final Task child2 = createTaskBuilder(".Task2").setParentTask(root).build();
+ doReturn(true).when(child1).isOrganized();
+ doReturn(false).when(child2).isOrganized();
+ mRecentTasks.add(root);
+
+ doNothing().when(mRecentTasks).loadUserRecentsLocked(anyInt());
+ doReturn(true).when(mRecentTasks).isUserRunning(anyInt(), anyInt());
+ final List<RecentTaskInfo> infos = mRecentTasks.getRecentTasks(MAX_VALUE, 0 /* flags */,
+ true /* getTasksAllowed */, TEST_USER_0_ID, 0 /* callingUid */).getList();
+
+ // Make sure only organized child will be appended.
+ final List<RecentTaskInfo> childrenTaskInfos = infos.get(0).childrenTaskInfos;
+ assertEquals(childrenTaskInfos.size(), 1);
+ assertEquals(childrenTaskInfos.get(0).taskId, child1.mTaskId);
+ }
+
+ @Test
public void testAddTasksHomeClearUntrackedTasks_expectFinish() {
// There may be multiple tasks with the same base intent by flags (FLAG_ACTIVITY_NEW_TASK |
// FLAG_ACTIVITY_MULTIPLE_TASK). If the previous task is still active, it should be removed
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 8094c9767b39..cc92dddb6de1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -16,8 +16,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.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
@@ -107,8 +105,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
@Test
public void testRemovedBeforeStarted_expectCanceled() throws Exception {
- final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord activity = createActivityRecord(mDefaultDisplay);
AnimationAdapter adapter = mController.addAnimation(activity.getTask(),
false /* isRecentTaskInvisible */);
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_RECENTS,
@@ -127,8 +124,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
@Test
public void testCancelAfterRemove_expectIgnored() {
- final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord activity = createActivityRecord(mDefaultDisplay);
AnimationAdapter adapter = mController.addAnimation(activity.getTask(),
false /* isRecentTaskInvisible */);
adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_RECENTS,
@@ -149,10 +145,8 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
public void testIncludedApps_expectTargetAndVisible() {
mWm.setRecentsAnimationController(mController);
final ActivityRecord homeActivity = createHomeActivity();
- final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
- final ActivityRecord hiddenActivity = createActivityRecord(mDefaultDisplay,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord activity = createActivityRecord(mDefaultDisplay);
+ final ActivityRecord hiddenActivity = createActivityRecord(mDefaultDisplay);
hiddenActivity.setVisible(false);
mDefaultDisplay.getConfiguration().windowConfiguration.setRotation(
mDefaultDisplay.getRotation());
@@ -168,8 +162,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
public void testWallpaperIncluded_expectTarget() throws Exception {
mWm.setRecentsAnimationController(mController);
final ActivityRecord homeActivity = createHomeActivity();
- final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord activity = createActivityRecord(mDefaultDisplay);
final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
activity.addWindow(win1);
final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
@@ -191,8 +184,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
public void testWallpaperAnimatorCanceled_expectAnimationKeepsRunning() throws Exception {
mWm.setRecentsAnimationController(mController);
final ActivityRecord homeActivity = createHomeActivity();
- final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord activity = createActivityRecord(mDefaultDisplay);
final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
activity.addWindow(win1);
final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
@@ -218,8 +210,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
final ActivityRecord homeActivity = createHomeActivity();
final WindowState hwin1 = createWindow(null, TYPE_BASE_APPLICATION, homeActivity, "hwin1");
homeActivity.addWindow(hwin1);
- final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord activity = createActivityRecord(mDefaultDisplay);
final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
activity.addWindow(win1);
final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
@@ -246,8 +237,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
@Test
public void testDeferCancelAnimation() throws Exception {
mWm.setRecentsAnimationController(mController);
- final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord activity = createActivityRecord(mDefaultDisplay);
final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
activity.addWindow(win1);
assertEquals(activity.getTask().getTopVisibleActivity(), activity);
@@ -269,8 +259,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
@Test
public void testDeferCancelAnimationWithScreenShot() throws Exception {
mWm.setRecentsAnimationController(mController);
- final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord activity = createActivityRecord(mDefaultDisplay);
final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
activity.addWindow(win1);
assertEquals(activity.getTask().getTopVisibleActivity(), activity);
@@ -301,8 +290,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
@Test
public void testShouldAnimateWhenNoCancelWithDeferredScreenshot() {
mWm.setRecentsAnimationController(mController);
- final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord activity = createActivityRecord(mDefaultDisplay);
final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
activity.addWindow(win1);
assertEquals(activity.getTask().getTopVisibleActivity(), activity);
@@ -325,8 +313,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
final ActivityRecord homeActivity = createHomeActivity();
homeActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
- final ActivityRecord landActivity = createActivityRecord(mDefaultDisplay,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord landActivity = createActivityRecord(mDefaultDisplay);
landActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, landActivity, "win1");
landActivity.addWindow(win1);
@@ -365,8 +352,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
private ActivityRecord prepareFixedRotationLaunchingAppWithRecentsAnim() {
final ActivityRecord homeActivity = createHomeActivity();
homeActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
- final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord activity = createActivityRecord(mDefaultDisplay);
// Add a window so it can be animated by the recents.
final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, activity, "win");
activity.addWindow(win);
@@ -441,8 +427,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
homeWindow.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
// Landscape application
- final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord activity = createActivityRecord(mDefaultDisplay);
final WindowState applicationWindow = createWindow(null, TYPE_BASE_APPLICATION, activity,
"applicationWindow");
activity.addWindow(applicationWindow);
@@ -513,7 +498,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
private ActivityRecord createHomeActivity() {
final ActivityRecord homeActivity = new ActivityBuilder(mWm.mAtmService)
- .setStack(mRootHomeTask)
+ .setParentTask(mRootHomeTask)
.setCreateTask(true)
.build();
// Avoid {@link RecentsAnimationController.TaskAnimationAdapter#createRemoteAnimationTarget}
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 c10d4fa7f189..137cedde11cf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationTest.java
@@ -93,8 +93,7 @@ public class RecentsAnimationTest extends WindowTestsBase {
ACTIVITY_TYPE_RECENTS, true /* onTop */);
ActivityRecord recentActivity = new ActivityBuilder(mAtm)
.setComponent(mRecentsComponent)
- .setCreateTask(true)
- .setStack(recentsStack)
+ .setTask(recentsStack)
.build();
ActivityRecord topActivity = new ActivityBuilder(mAtm).setCreateTask(true).build();
topActivity.getRootTask().moveToFront("testRecentsActivityVisiblility");
@@ -124,7 +123,7 @@ public class RecentsAnimationTest extends WindowTestsBase {
ActivityRecord topRunningHomeActivity = homeStack.topRunningActivity();
if (topRunningHomeActivity == null) {
topRunningHomeActivity = new ActivityBuilder(mAtm)
- .setStack(homeStack)
+ .setParentTask(homeStack)
.setCreateTask(true)
.build();
}
@@ -182,7 +181,7 @@ public class RecentsAnimationTest extends WindowTestsBase {
Task recentsStack = defaultTaskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_RECENTS, true /* onTop */);
ActivityRecord recentActivity = new ActivityBuilder(mAtm).setComponent(
- mRecentsComponent).setCreateTask(true).setStack(recentsStack).build();
+ mRecentsComponent).setCreateTask(true).setParentTask(recentsStack).build();
WindowProcessController app = recentActivity.app;
recentActivity.app = null;
@@ -214,7 +213,7 @@ public class RecentsAnimationTest extends WindowTestsBase {
if (targetActivity == null) {
targetActivity = new ActivityBuilder(mAtm)
.setCreateTask(true)
- .setStack(homeStack)
+ .setParentTask(homeStack)
.build();
}
@@ -222,7 +221,7 @@ public class RecentsAnimationTest extends WindowTestsBase {
ActivityRecord anotherHomeActivity = new ActivityBuilder(mAtm)
.setComponent(new ComponentName(mContext.getPackageName(), "Home2"))
.setCreateTask(true)
- .setStack(homeStack)
+ .setParentTask(homeStack)
.build();
// Start an activity on top so the recents activity can be started.
new ActivityBuilder(mAtm)
@@ -255,21 +254,21 @@ public class RecentsAnimationTest extends WindowTestsBase {
new ActivityBuilder(mAtm)
.setComponent(new ComponentName(mContext.getPackageName(), "App1"))
.setCreateTask(true)
- .setStack(fullscreenStack)
+ .setParentTask(fullscreenStack)
.build();
Task recentsStack = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_RECENTS, true /* onTop */);
new ActivityBuilder(mAtm)
.setComponent(mRecentsComponent)
.setCreateTask(true)
- .setStack(recentsStack)
+ .setParentTask(recentsStack)
.build();
Task fullscreenStack2 = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, true /* onTop */);
new ActivityBuilder(mAtm)
.setComponent(new ComponentName(mContext.getPackageName(), "App2"))
.setCreateTask(true)
- .setStack(fullscreenStack2)
+ .setParentTask(fullscreenStack2)
.build();
// Start the recents animation
@@ -296,21 +295,21 @@ public class RecentsAnimationTest extends WindowTestsBase {
new ActivityBuilder(mAtm)
.setComponent(new ComponentName(mContext.getPackageName(), "App1"))
.setCreateTask(true)
- .setStack(fullscreenStack)
+ .setParentTask(fullscreenStack)
.build();
Task recentsStack = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_RECENTS, true /* onTop */);
new ActivityBuilder(mAtm)
.setComponent(mRecentsComponent)
.setCreateTask(true)
- .setStack(recentsStack)
+ .setParentTask(recentsStack)
.build();
Task fullscreenStack2 = taskDisplayArea.createStack(WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, true /* onTop */);
new ActivityBuilder(mAtm)
.setComponent(new ComponentName(mContext.getPackageName(), "App2"))
.setCreateTask(true)
- .setStack(fullscreenStack2)
+ .setParentTask(fullscreenStack2)
.build();
// Start the recents animation
@@ -331,7 +330,7 @@ public class RecentsAnimationTest extends WindowTestsBase {
Task homeStack = taskDisplayArea.getStack(WINDOWING_MODE_UNDEFINED,
ACTIVITY_TYPE_HOME);
ActivityRecord otherUserHomeActivity = new ActivityBuilder(mAtm)
- .setStack(homeStack)
+ .setParentTask(homeStack)
.setCreateTask(true)
.setComponent(new ComponentName(mContext.getPackageName(), "Home2"))
.build();
@@ -342,7 +341,7 @@ public class RecentsAnimationTest extends WindowTestsBase {
new ActivityBuilder(mAtm)
.setComponent(new ComponentName(mContext.getPackageName(), "App1"))
.setCreateTask(true)
- .setStack(fullscreenStack)
+ .setParentTask(fullscreenStack)
.build();
doReturn(TEST_USER_ID).when(mAtm).getCurrentUserId();
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 901ed36254ea..1879e9e88822 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -117,12 +117,10 @@ public class RootActivityContainerTests extends WindowTestsBase {
*/
@Test
public void testReplacingTaskInPinnedStack() {
- final ActivityRecord firstActivity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(mFullscreenStack).build();
- final Task task = firstActivity.getTask();
-
- final ActivityRecord secondActivity = new ActivityBuilder(mAtm).setTask(task)
- .setStack(mFullscreenStack).build();
+ final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
+ .setTask(mFullscreenStack).build();
+ final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
+ .setTask(mFullscreenStack).build();
mFullscreenStack.moveToFront("testReplacingTaskInPinnedStack");
@@ -152,12 +150,12 @@ public class RootActivityContainerTests extends WindowTestsBase {
@Test
public void testMovingBottomMostStackActivityToPinnedStack() {
- final ActivityRecord firstActivity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(mFullscreenStack).build();
+ final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
+ .setTask(mFullscreenStack).build();
final Task task = firstActivity.getTask();
- final ActivityRecord secondActivity = new ActivityBuilder(mAtm).setTask(task)
- .setStack(mFullscreenStack).build();
+ final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
+ .setTask(mFullscreenStack).build();
mFullscreenStack.moveTaskToBack(task);
@@ -287,8 +285,7 @@ public class RootActivityContainerTests extends WindowTestsBase {
final int originalStackCount = defaultTaskDisplayArea.getStackCount();
final Task stack = defaultTaskDisplayArea.createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
- final ActivityRecord firstActivity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(stack).build();
+ final ActivityRecord firstActivity = new ActivityBuilder(mAtm).setTask(stack).build();
assertEquals(originalStackCount + 1, defaultTaskDisplayArea.getStackCount());
@@ -311,17 +308,15 @@ public class RootActivityContainerTests extends WindowTestsBase {
final int originalStackCount = defaultTaskDisplayArea.getStackCount();
final Task stack = defaultTaskDisplayArea.createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
- final ActivityRecord firstActivity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(stack).build();
+ final ActivityRecord firstActivity = new ActivityBuilder(mAtm).setTask(stack).build();
assertEquals(originalStackCount + 1, defaultTaskDisplayArea.getStackCount());
final DisplayContent dc = defaultTaskDisplayArea.getDisplayContent();
- final TaskDisplayArea secondTaskDisplayArea = WindowTestsBase.createTaskDisplayArea(
+ final TaskDisplayArea secondTaskDisplayArea = createTaskDisplayArea(
dc, mRootWindowContainer.mWmService, "TestTaskDisplayArea", FEATURE_VENDOR_FIRST);
final Task secondStack = secondTaskDisplayArea.createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
- new ActivityBuilder(mAtm).setCreateTask(true).setStack(secondStack)
- .setUseProcess(firstActivity.app).build();
+ new ActivityBuilder(mAtm).setTask(secondStack).setUseProcess(firstActivity.app).build();
assertEquals(1, secondTaskDisplayArea.getStackCount());
// Let's pretend that the app has crashed.
@@ -339,8 +334,7 @@ public class RootActivityContainerTests extends WindowTestsBase {
.getDefaultTaskDisplayArea();
final Task stack = defaultTaskDisplayArea.createStack(
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(stack).build();
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(stack).build();
// Created stacks are focusable by default.
assertTrue(stack.isTopActivityFocusable());
@@ -353,8 +347,8 @@ public class RootActivityContainerTests extends WindowTestsBase {
final Task pinnedStack = defaultTaskDisplayArea.createStack(
WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final ActivityRecord pinnedActivity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(pinnedStack).build();
+ final ActivityRecord pinnedActivity = new ActivityBuilder(mAtm)
+ .setTask(pinnedStack).build();
// We should not be focusable when in pinned mode
assertFalse(pinnedStack.isTopActivityFocusable());
@@ -363,13 +357,9 @@ public class RootActivityContainerTests extends WindowTestsBase {
// Add flag forcing focusability.
pinnedActivity.info.flags |= FLAG_ALWAYS_FOCUSABLE;
- // We should not be focusable when in pinned mode
+ // Task with FLAG_ALWAYS_FOCUSABLE should be focusable.
assertTrue(pinnedStack.isTopActivityFocusable());
assertTrue(pinnedActivity.isFocusable());
-
- // Without the overridding activity, stack should not be focusable.
- pinnedStack.removeChild(pinnedActivity.getTask(), "testFocusability");
- assertFalse(pinnedStack.isTopActivityFocusable());
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index cc8b2a1bb392..62aa02f609ad 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -16,8 +16,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.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
@@ -152,8 +150,7 @@ public class RootWindowContainerTests extends WindowTestsBase {
DisplayContent displayContent = mWm.mRoot.getDisplayContent(DEFAULT_DISPLAY);
TaskDisplayArea taskDisplayArea = displayContent.getDefaultTaskDisplayArea();
Task stack = taskDisplayArea.getStackAt(0);
- ActivityRecord activity = createActivityRecord(displayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ ActivityRecord activity = createActivityRecord(displayContent);
stack.mPausingActivity = activity;
activity.setState(PAUSING, "test PAUSING");
@@ -176,7 +173,7 @@ public class RootWindowContainerTests extends WindowTestsBase {
public void testTaskLayerRank() {
final Task rootTask = new TaskBuilder(mSupervisor).build();
final Task task1 = new TaskBuilder(mSupervisor).setParentTask(rootTask).build();
- new ActivityBuilder(mAtm).setStack(task1).build().mVisibleRequested = true;
+ new ActivityBuilder(mAtm).setTask(task1).build().mVisibleRequested = true;
// RootWindowContainer#invalidateTaskLayers should post to update.
waitHandlerIdle(mWm.mH);
@@ -185,7 +182,7 @@ public class RootWindowContainerTests extends WindowTestsBase {
assertEquals(Task.LAYER_RANK_INVISIBLE, rootTask.mLayerRank);
final Task task2 = new TaskBuilder(mSupervisor).build();
- new ActivityBuilder(mAtm).setStack(task2).build().mVisibleRequested = true;
+ new ActivityBuilder(mAtm).setTask(task2).build().mVisibleRequested = true;
waitHandlerIdle(mWm.mH);
// Note that ensureActivitiesVisible is disabled in SystemServicesTestRule, so both the
@@ -208,8 +205,8 @@ public class RootWindowContainerTests extends WindowTestsBase {
final WindowProcessController wpc = activity.app;
final ActivityRecord[] activities = {
activity,
- new ActivityBuilder(mWm.mAtmService).setStack(task).setUseProcess(wpc).build(),
- new ActivityBuilder(mWm.mAtmService).setStack(task).setUseProcess(wpc).build()
+ new ActivityBuilder(mWm.mAtmService).setTask(task).setUseProcess(wpc).build(),
+ new ActivityBuilder(mWm.mAtmService).setTask(task).setUseProcess(wpc).build()
};
activities[0].detachFromProcess();
activities[1].finishing = true;
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 d68dde5734ca..4300971be689 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -768,7 +768,7 @@ public class SizeCompatTests extends WindowTestsBase {
params.setFitInsetsTypes(0);
final TestWindowState w = new TestWindowState(
activity.mWmService, mock(Session.class), new TestIWindow(), params, activity);
- WindowTestsBase.makeWindowVisible(w);
+ makeWindowVisible(w);
w.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
activity.addWindow(w);
return w;
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 6f5389ddacce..740f605d4393 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -296,6 +296,7 @@ public class SystemServicesTestRule implements TestRule {
// Called when moving activity to pinned stack.
doNothing().when(mWmService.mRoot).ensureActivitiesVisible(any(),
anyInt(), anyBoolean(), anyBoolean());
+ spyOn(mWmService.mDisplayWindowSettings);
// Setup factory classes to prevent calls to native code.
mTransaction = spy(StubTransaction.class);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
index 8b025e34401a..c5c947bf21d8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
@@ -79,7 +79,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase {
// Stack should contain visible app window to be considered visible.
final Task pinnedTask = createTaskInStack(mPinnedStack, 0 /* userId */);
assertFalse(mPinnedStack.isVisible());
- final ActivityRecord pinnedApp = createTestActivityRecord(mDisplayContent);
+ final ActivityRecord pinnedApp = createNonAttachedActivityRecord(mDisplayContent);
pinnedTask.addChild(pinnedApp, 0 /* addPos */);
assertTrue(mPinnedStack.isVisible());
}
@@ -94,7 +94,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase {
final Task stack = createTaskStackOnDisplay(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
task.addChild(activity, 0 /* addPos */);
final TaskDisplayArea taskDisplayArea = activity.getDisplayArea();
activity.mNeedsAnimationBoundsLayer = true;
@@ -236,7 +236,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase {
ActivityRecord homeActivity = rootHomeTask.getTopNonFinishingActivity();
if (homeActivity == null) {
homeActivity = new ActivityBuilder(mWm.mAtmService)
- .setStack(rootHomeTask).setCreateTask(true).build();
+ .setParentTask(rootHomeTask).setCreateTask(true).build();
}
homeActivity.setVisible(false);
homeActivity.mVisibleRequested = true;
@@ -255,10 +255,10 @@ public class TaskDisplayAreaTests extends WindowTestsBase {
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
final Task secondStack = secondTaskDisplayArea.createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
- final ActivityRecord firstActivity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(firstStack).build();
- final ActivityRecord secondActivity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(secondStack).build();
+ final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
+ .setTask(firstStack).build();
+ final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
+ .setTask(secondStack).build();
// Activity on TDA1 is focused
mDisplayContent.setFocusedApp(firstActivity);
@@ -284,8 +284,7 @@ public class TaskDisplayAreaTests extends WindowTestsBase {
final TaskDisplayArea taskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
final Task stack = taskDisplayArea.createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
- final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(stack).build();
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(stack).build();
mDisplayContent.setFocusedApp(activity);
activity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
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 1d32e17dd5e1..a1097d26fbbb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java
@@ -1351,7 +1351,7 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase {
private ActivityRecord createSourceActivity(TestDisplayContent display) {
final Task stack = display.getDefaultTaskDisplayArea()
.createStack(display.getWindowingMode(), ACTIVITY_TYPE_STANDARD, true);
- return new ActivityBuilder(mAtm).setStack(stack).setCreateTask(true).build();
+ return new ActivityBuilder(mAtm).setTask(stack).build();
}
private void addFreeformTaskTo(TestDisplayContent display, Rect bounds) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
index 27cae2fc1a4c..7abe3698a99c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskPositionerTests.java
@@ -76,11 +76,8 @@ public class TaskPositionerTests extends WindowTestsBase {
mMinVisibleHeight = dipToPixel(MINIMUM_VISIBLE_HEIGHT_IN_DP, dm);
removeGlobalMinSizeRestriction();
- final Task stack = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity = new ActivityBuilder(stack.mAtmService)
- .setStack(stack)
- // In real case, there is no additional level for freeform mode.
- .setCreateTask(false)
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setCreateTask(true)
.build();
final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, activity, "window");
mPositioner = new TaskPositioner(mWm);
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 2fa7589ed719..f7e68ce9fe65 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -269,7 +269,8 @@ public class TaskRecordTests extends WindowTestsBase {
assertEquals(fullScreenBounds.height(), task.getBounds().height());
// Top activity gets used
- final ActivityRecord top = new ActivityBuilder(mAtm).setTask(task).setStack(stack).build();
+ final ActivityRecord top = new ActivityBuilder(mAtm).setTask(task).setParentTask(stack)
+ .build();
assertEquals(top, task.getTopNonFinishingActivity());
top.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
assertThat(task.getBounds().width()).isGreaterThan(task.getBounds().height());
@@ -1001,7 +1002,8 @@ public class TaskRecordTests extends WindowTestsBase {
@Test
public void testNotSpecifyOrientationByFloatingTask() {
- final Task task = getTestTask();
+ final Task task = new TaskBuilder(mSupervisor)
+ .setCreateActivity(true).setCreateParentTask(true).build();
final ActivityRecord activity = task.getTopMostActivity();
final WindowContainer<?> parentContainer = task.getParent();
final TaskDisplayArea taskDisplayArea = task.getDisplayArea();
@@ -1027,10 +1029,10 @@ public class TaskRecordTests extends WindowTestsBase {
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
final Task secondStack = secondTaskDisplayArea.createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
- final ActivityRecord firstActivity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(firstStack).build();
- final ActivityRecord secondActivity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(secondStack).build();
+ final ActivityRecord firstActivity = new ActivityBuilder(mAtm)
+ .setTask(firstStack).build();
+ final ActivityRecord secondActivity = new ActivityBuilder(mAtm)
+ .setTask(secondStack).build();
firstActivity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
secondActivity.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
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 7cf30c0c9f35..404141211646 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -85,12 +85,12 @@ public class TaskStackTests extends WindowTestsBase {
public void testClosingAppDifferentStackOrientation() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack, 0 /* userId */);
- ActivityRecord activity1 = createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity1 = createNonAttachedActivityRecord(mDisplayContent);
task1.addChild(activity1, 0);
activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
final Task task2 = createTaskInStack(stack, 1 /* userId */);
- ActivityRecord activity2 = createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity2 = createNonAttachedActivityRecord(mDisplayContent);
task2.addChild(activity2, 0);
activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
@@ -103,12 +103,12 @@ public class TaskStackTests extends WindowTestsBase {
public void testMoveTaskToBackDifferentStackOrientation() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack, 0 /* userId */);
- ActivityRecord activity1 = createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity1 = createNonAttachedActivityRecord(mDisplayContent);
task1.addChild(activity1, 0);
activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
final Task task2 = createTaskInStack(stack, 1 /* userId */);
- ActivityRecord activity2 = createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity2 = createNonAttachedActivityRecord(mDisplayContent);
task2.addChild(activity2, 0);
activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
assertEquals(SCREEN_ORIENTATION_PORTRAIT, stack.getOrientation());
@@ -217,7 +217,7 @@ public class TaskStackTests extends WindowTestsBase {
public void testActivityAndTaskGetsProperType() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task1 = createTaskInStack(stack, 0 /* userId */);
- ActivityRecord activity1 = createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity1 = createNonAttachedActivityRecord(mDisplayContent);
// First activity should become standard
task1.addChild(activity1, 0);
@@ -225,7 +225,7 @@ public class TaskStackTests extends WindowTestsBase {
assertEquals(WindowConfiguration.ACTIVITY_TYPE_STANDARD, task1.getActivityType());
// Second activity should also become standard
- ActivityRecord activity2 = createTestActivityRecord(mDisplayContent);
+ ActivityRecord activity2 = createNonAttachedActivityRecord(mDisplayContent);
task1.addChild(activity2, WindowContainer.POSITION_TOP);
assertEquals(WindowConfiguration.ACTIVITY_TYPE_STANDARD, activity2.getActivityType());
assertEquals(WindowConfiguration.ACTIVITY_TYPE_STANDARD, task1.getActivityType());
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 b6b3d66d9c04..0b257ee87620 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -63,7 +63,7 @@ public class TaskTests extends WindowTestsBase {
public void testRemoveContainer() {
final Task stackController1 = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stackController1, 0 /* userId */);
- final ActivityRecord activity = createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
task.removeIfPossible();
// Assert that the container was removed.
@@ -76,7 +76,7 @@ public class TaskTests extends WindowTestsBase {
public void testRemoveContainer_deferRemoval() {
final Task stackController1 = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stackController1, 0 /* userId */);
- final ActivityRecord activity = createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
doReturn(true).when(task).shouldDeferRemoval();
@@ -158,8 +158,8 @@ public class TaskTests extends WindowTestsBase {
public void testIsInStack() {
final Task task1 = createTaskStackOnDisplay(mDisplayContent);
final Task task2 = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task1);
- final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task2);
+ final ActivityRecord activity1 = createActivityRecord(mDisplayContent, task1);
+ final ActivityRecord activity2 = createActivityRecord(mDisplayContent, task2);
assertEquals(activity1, task1.isInTask(activity1));
assertNull(task1.isInTask(activity2));
}
@@ -168,9 +168,9 @@ public class TaskTests extends WindowTestsBase {
public void testRemoveChildForOverlayTask() {
final Task task = createTaskStackOnDisplay(mDisplayContent);
final int taskId = task.mTaskId;
- final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task);
- final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task);
- final ActivityRecord activity3 = createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity1 = createActivityRecord(mDisplayContent, task);
+ final ActivityRecord activity2 = createActivityRecord(mDisplayContent, task);
+ final ActivityRecord activity3 = createActivityRecord(mDisplayContent, task);
activity1.setTaskOverlay(true);
activity2.setTaskOverlay(true);
activity3.setTaskOverlay(true);
@@ -207,8 +207,8 @@ public class TaskTests extends WindowTestsBase {
final Task rootTask = createTaskStackOnDisplay(mDisplayContent);
final Task leafTask1 = createTaskInStack(rootTask, 0 /* userId */);
final Task leafTask2 = createTaskInStack(rootTask, 0 /* userId */);
- final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, leafTask1);
- final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, leafTask2);
+ final ActivityRecord activity1 = createActivityRecord(mDisplayContent, leafTask1);
+ final ActivityRecord activity2 = createActivityRecord(mDisplayContent, leafTask2);
// Check visibility of occluded tasks
doReturn(false).when(leafTask1).shouldBeVisible(any());
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index feb509c63ae9..ef56c139e9ff 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -51,8 +51,8 @@ public class TransitionTests extends WindowTestsBase {
ACTIVITY_TYPE_STANDARD, mDisplayContent);
newTask.setHasBeenVisible(true);
oldTask.setHasBeenVisible(false);
- final ActivityRecord closing = createActivityRecordInTask(oldTask);
- final ActivityRecord opening = createActivityRecordInTask(newTask);
+ final ActivityRecord closing = createActivityRecord(oldTask);
+ final ActivityRecord opening = createActivityRecord(newTask);
closing.setVisible(true);
closing.mVisibleRequested = false;
opening.setVisible(false);
@@ -102,9 +102,9 @@ public class TransitionTests extends WindowTestsBase {
ACTIVITY_TYPE_STANDARD, mDisplayContent);
newTask.setHasBeenVisible(true);
oldTask.setHasBeenVisible(false);
- final ActivityRecord closing = createActivityRecordInTask(oldTask);
- final ActivityRecord opening = createActivityRecordInTask(newNestedTask);
- final ActivityRecord opening2 = createActivityRecordInTask(newNestedTask2);
+ final ActivityRecord closing = createActivityRecord(oldTask);
+ final ActivityRecord opening = createActivityRecord(newNestedTask);
+ final ActivityRecord opening2 = createActivityRecord(newNestedTask2);
closing.setVisible(true);
closing.mVisibleRequested = false;
opening.setVisible(false);
@@ -144,8 +144,8 @@ public class TransitionTests extends WindowTestsBase {
final DisplayArea tda = showTask.getDisplayArea();
showTask.setHasBeenVisible(true);
showTask2.setHasBeenVisible(true);
- final ActivityRecord showing = createActivityRecordInTask(showNestedTask);
- final ActivityRecord showing2 = createActivityRecordInTask(showTask2);
+ final ActivityRecord showing = createActivityRecord(showNestedTask);
+ final ActivityRecord showing2 = createActivityRecord(showTask2);
showing.setVisible(false);
showing.mVisibleRequested = true;
showing2.setVisible(false);
diff --git a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
index 78dfd407ff4e..45e114130420 100644
--- a/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -44,7 +44,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testFlow() {
- final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(activity);
mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(activity);
@@ -56,7 +56,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testSkipResume() {
- final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
activity.mLaunchTaskBehind = true;
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
mDisplayContent.mUnknownAppVisibilityController.notifyRelayouted(activity);
@@ -68,8 +68,8 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testMultiple() {
- final ActivityRecord activity1 = createTestActivityRecord(mDisplayContent);
- final ActivityRecord activity2 = createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity1 = createNonAttachedActivityRecord(mDisplayContent);
+ final ActivityRecord activity2 = createNonAttachedActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity1);
mDisplayContent.mUnknownAppVisibilityController.notifyAppResumedFinished(activity1);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity2);
@@ -84,7 +84,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testClear() {
- final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
mDisplayContent.mUnknownAppVisibilityController.clear();
assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
@@ -92,7 +92,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testRemoveFinishingInvisibleActivityFromUnknown() {
- final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
activity.finishing = true;
activity.mVisibleRequested = true;
@@ -102,7 +102,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
@Test
public void testAppRemoved() {
- final ActivityRecord activity = createTestActivityRecord(mDisplayContent);
+ final ActivityRecord activity = createNonAttachedActivityRecord(mDisplayContent);
mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(activity);
mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(activity);
assertTrue(mDisplayContent.mUnknownAppVisibilityController.allResolved());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index 63367ac2badf..a91a137ae29f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -296,8 +296,7 @@ public class WallpaperControllerTests extends WindowTestsBase {
private WindowState createWallpaperTargetWindow(DisplayContent dc) {
final ActivityRecord homeActivity = new ActivityBuilder(mWm.mAtmService)
- .setStack(dc.getDefaultTaskDisplayArea().getRootHomeTask())
- .setCreateTask(true)
+ .setTask(dc.getDefaultTaskDisplayArea().getRootHomeTask())
.build();
homeActivity.setVisibility(true);
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 f5d68894cc4f..e0c72fb00060 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -810,7 +810,7 @@ public class WindowContainerTests extends WindowTestsBase {
public void testOnDisplayChanged() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity = createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
final DisplayContent newDc = createNewDisplay();
stack.getDisplayArea().removeStack(stack);
@@ -853,17 +853,17 @@ public class WindowContainerTests extends WindowTestsBase {
public void testTaskCanApplyAnimation() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
final Task task = createTaskInStack(stack, 0 /* userId */);
- final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent, task);
- final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent, task);
+ final ActivityRecord activity2 = createActivityRecord(mDisplayContent, task);
+ final ActivityRecord activity1 = createActivityRecord(mDisplayContent, task);
verifyWindowContainerApplyAnimation(task, activity1, activity2);
}
@Test
public void testStackCanApplyAnimation() {
final Task stack = createTaskStackOnDisplay(mDisplayContent);
- final ActivityRecord activity2 = createActivityRecordInTask(mDisplayContent,
+ final ActivityRecord activity2 = createActivityRecord(mDisplayContent,
createTaskInStack(stack, 0 /* userId */));
- final ActivityRecord activity1 = createActivityRecordInTask(mDisplayContent,
+ final ActivityRecord activity1 = createActivityRecord(mDisplayContent,
createTaskInStack(stack, 0 /* userId */));
verifyWindowContainerApplyAnimation(stack, activity1, activity2);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
index 47e4559cbb13..78e873e2b0a3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTraversalTests.java
@@ -49,10 +49,10 @@ public class WindowContainerTraversalTests extends WindowTestsBase {
@UseTestDisplay(addWindows = { W_DOCK_DIVIDER, W_INPUT_METHOD })
@Test
public void testDockedDividerPosition() {
- final WindowState splitScreenWindow = createWindowOnStack(null,
+ final WindowState splitScreenWindow = createWindow(null,
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION,
mDisplayContent, "splitScreenWindow");
- final WindowState splitScreenSecondaryWindow = createWindowOnStack(null,
+ final WindowState splitScreenSecondaryWindow = createWindow(null,
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
TYPE_BASE_APPLICATION, mDisplayContent, "splitScreenSecondaryWindow");
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java
index 8d5363c89570..ba144dd367d9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerSettingsTests.java
@@ -20,12 +20,16 @@ import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDO
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_SIZECOMPAT_FREEFORM;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
+import static android.provider.Settings.Global.DEVELOPMENT_IGNORE_VENDOR_DISPLAY_SETTINGS;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.content.ContentResolver;
@@ -37,6 +41,9 @@ import androidx.test.filters.SmallTest;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+import java.util.List;
/**
* Test for {@link WindowManagerService.SettingsObserver}.
@@ -124,6 +131,36 @@ public class WindowManagerSettingsTests extends WindowTestsBase {
}
}
+ @Test
+ public void testEnabledIgnoreVendorDisplaySettings() {
+ try (SettingsSession ignoreVendorDisplaySettingsSession = new
+ SettingsSession(DEVELOPMENT_IGNORE_VENDOR_DISPLAY_SETTINGS)) {
+ final boolean ignoreVendorDisplaySettings =
+ !ignoreVendorDisplaySettingsSession.getSetting();
+ final Uri ignoreVendorDisplaySettingUri =
+ ignoreVendorDisplaySettingsSession.setSetting(ignoreVendorDisplaySettings);
+
+ clearInvocations(mWm.mRoot);
+ clearInvocations(mWm.mDisplayWindowSettings);
+
+ mWm.mSettingsObserver.onChange(false /* selfChange */, ignoreVendorDisplaySettingUri);
+
+ assertEquals(mWm.mDisplayWindowSettingsProvider.getVendorSettingsIgnored(),
+ ignoreVendorDisplaySettings);
+
+ ArgumentCaptor<DisplayContent> captor =
+ ArgumentCaptor.forClass(DisplayContent.class);
+ verify(mWm.mDisplayWindowSettings, times(mWm.mRoot.mChildren.size()))
+ .applySettingsToDisplayLocked(captor.capture());
+ List<DisplayContent> configuredDisplays = captor.getAllValues();
+ for (DisplayContent dc : mWm.mRoot.mChildren) {
+ assertTrue(configuredDisplays.contains(dc));
+ }
+
+ verify(mWm.mRoot, atLeastOnce()).performSurfacePlacement();
+ }
+ }
+
private class SettingsSession implements AutoCloseable {
private static final int SETTING_VALUE_OFF = 0;
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index b4480aea3ce4..7a41c02de3b6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -389,8 +389,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
final TaskDisplayArea taskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
final Task stack = taskDisplayArea.createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
- final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(stack).build();
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(stack).build();
taskDisplayArea.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mDisplayContent.setFocusedApp(activity);
activity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
@@ -428,8 +427,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
final TaskDisplayArea taskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea();
final Task stack = taskDisplayArea.createStack(
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, false /* onTop */);
- final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true)
- .setStack(stack).build();
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(stack).build();
mDisplayContent.setFocusedApp(activity);
activity.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
@@ -780,7 +778,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
};
private ActivityRecord makePipableActivity() {
- final ActivityRecord record = createActivityRecord(mDisplayContent,
+ final ActivityRecord record = createActivityRecordWithParentTask(mDisplayContent,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
record.info.flags |= ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
spyOn(record);
@@ -849,7 +847,7 @@ public class WindowOrganizerTests extends WindowTestsBase {
final Task stack = createStack();
final Task task = createTask(stack);
- final ActivityRecord record = createActivityRecordInTask(stack.mDisplayContent, task);
+ final ActivityRecord record = createActivityRecord(stack.mDisplayContent, task);
stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
record.setTaskDescription(new ActivityManager.TaskDescription("TestDescription"));
@@ -885,10 +883,10 @@ public class WindowOrganizerTests extends WindowTestsBase {
final ITaskOrganizer organizer = registerMockOrganizer();
final Task stack = createStack();
final Task task = createTask(stack);
- final ActivityRecord activity = createActivityRecordInTask(stack.mDisplayContent, task);
+ final ActivityRecord activity = createActivityRecord(stack.mDisplayContent, task);
final Task stack2 = createStack();
final Task task2 = createTask(stack2);
- final ActivityRecord activity2 = createActivityRecordInTask(stack.mDisplayContent, task2);
+ final ActivityRecord activity2 = createActivityRecord(stack.mDisplayContent, task2);
assertTrue(stack.isOrganized());
assertTrue(stack2.isOrganized());
@@ -976,6 +974,21 @@ public class WindowOrganizerTests extends WindowTestsBase {
});
}
+ @Test
+ public void testReparentToOrganizedTask() {
+ final ITaskOrganizer organizer = registerMockOrganizer();
+ Task rootTask = mWm.mAtmService.mTaskOrganizerController.createRootTask(
+ mDisplayContent, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, null);
+ final Task task1 = createStack();
+ final Task task2 = createTask(rootTask, false /* fakeDraw */);
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.reparent(task1.mRemoteToken.toWindowContainerToken(),
+ rootTask.mRemoteToken.toWindowContainerToken(), true /* onTop */);
+ mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
+ assertTrue(task1.isOrganized());
+ assertTrue(task2.isOrganized());
+ }
+
/**
* Verifies that task vanished is called for a specific task.
*/
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 94bbfca012b0..21be6ef2e897 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -291,25 +291,19 @@ public class WindowProcessControllerTests extends WindowTestsBase {
assertEquals(1 /* minTaskLayer */, mWpc.computeOomAdjFromActivities(callback));
assertEquals(visible, callbackResult[0]);
- // The oom state will be updated in handler from activity state change.
callbackResult[0] = 0;
activity.mVisibleRequested = false;
activity.setState(Task.ActivityState.PAUSED, "test");
- waitHandlerIdle(mAtm.mH);
mWpc.computeOomAdjFromActivities(callback);
assertEquals(paused, callbackResult[0]);
- // updateProcessInfo with updateOomAdj=true should refresh the state immediately.
callbackResult[0] = 0;
activity.setState(Task.ActivityState.STOPPING, "test");
- mWpc.updateProcessInfo(false /* updateServiceConnectionActivities */,
- true /* activityChange */, true /* updateOomAdj */, false /* addPendingTopUid */);
mWpc.computeOomAdjFromActivities(callback);
assertEquals(stopping, callbackResult[0]);
callbackResult[0] = 0;
activity.setState(Task.ActivityState.STOPPED, "test");
- waitHandlerIdle(mAtm.mH);
mWpc.computeOomAdjFromActivities(callback);
assertEquals(other, callbackResult[0]);
}
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 2691ae84db28..9304dc53c819 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -17,7 +17,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_SPLIT_SCREEN_PRIMARY;
import static android.hardware.camera2.params.OutputConfiguration.ROTATION_90;
@@ -318,8 +317,7 @@ public class WindowStateTests extends WindowTestsBase {
public void testPrepareWindowToDisplayDuringRelayout() {
// Call prepareWindowToDisplayDuringRelayout for a window without FLAG_TURN_SCREEN_ON before
// calling setCurrentLaunchCanTurnScreenOn for windows with flag in the same activity.
- final ActivityRecord activity = createActivityRecord(mDisplayContent,
- WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ final ActivityRecord activity = createActivityRecord(mDisplayContent);
final WindowState first = createWindow(null, TYPE_APPLICATION, activity, "first");
final WindowState second = createWindow(null, TYPE_APPLICATION, activity, "second");
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 62f04a1c830a..d5fb3c5f5e3d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -47,7 +47,6 @@ 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.spyOn;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
-import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -82,7 +81,6 @@ import android.view.SurfaceControl.Transaction;
import android.view.View;
import android.view.WindowManager;
import android.window.ITaskOrganizer;
-import android.window.WindowContainerToken;
import com.android.internal.util.ArrayUtils;
import com.android.server.AttributeCache;
@@ -248,48 +246,19 @@ class WindowTestsBase extends SystemServiceTestsBase {
return createActivityRecord(dc, windowingMode, activityType);
}
- ActivityRecord createActivityRecord(DisplayContent dc, int windowingMode, int activityType) {
- return createTestActivityRecord(dc, windowingMode, activityType);
- }
-
- ActivityRecord createTestActivityRecord(DisplayContent dc, int windowingMode,
- int activityType) {
- final Task stack = createTaskStackOnDisplay(windowingMode, activityType, dc);
- return createTestActivityRecord(stack);
- }
-
- /** Creates an {@link ActivityRecord} and adds it to the specified {@link Task}. */
- static ActivityRecord createActivityRecordInTask(DisplayContent dc, Task task) {
- final ActivityRecord activity = createTestActivityRecord(dc);
- task.addChild(activity, POSITION_TOP);
- return activity;
- }
-
- /** Creates an {@link ActivityRecord} and adds it to the specified {@link Task}. */
- static ActivityRecord createActivityRecordInTask(Task task) {
- return createActivityRecordInTask(task.getDisplayContent(), task);
- }
-
- static ActivityRecord createTestActivityRecord(DisplayContent dc) {
- final ActivityRecord activity = new ActivityBuilder(dc.mWmService.mAtmService).build();
- postCreateActivitySetup(activity, dc);
- return activity;
- }
-
- static ActivityRecord createTestActivityRecord(Task stack) {
- final ActivityRecord activity = new ActivityBuilder(stack.mAtmService)
- .setStack(stack)
- .setCreateTask(true)
- .build();
- postCreateActivitySetup(activity, stack.getDisplayContent());
- return activity;
+ WindowState createAppWindow(Task task, int type, String name) {
+ final ActivityRecord activity = createNonAttachedActivityRecord(task.getDisplayContent());
+ task.addChild(activity, 0);
+ return createWindow(null, type, activity, name);
}
- private static void postCreateActivitySetup(ActivityRecord activity, DisplayContent dc) {
- activity.onDisplayChanged(dc);
- activity.setOccludesParent(true);
- activity.setVisible(true);
- activity.mVisibleRequested = true;
+ // TODO: Move these calls to a builder?
+ WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name,
+ IWindow iwindow) {
+ final WindowToken token = createWindowToken(
+ dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type);
+ return createWindow(parent, type, token, name, 0 /* ownerId */,
+ false /* ownerCanAddInternalSystemWindow */, iwindow);
}
WindowState createWindow(WindowState parent, int type, String name) {
@@ -304,31 +273,15 @@ class WindowTestsBase extends SystemServiceTestsBase {
: createWindow(parent, type, parent.mToken, name, ownerId);
}
- WindowState createWindowOnStack(WindowState parent, int windowingMode, int activityType,
+ WindowState createWindow(WindowState parent, int windowingMode, int activityType,
int type, DisplayContent dc, String name) {
final WindowToken token = createWindowToken(dc, windowingMode, activityType, type);
return createWindow(parent, type, token, name);
}
- WindowState createAppWindow(Task task, int type, String name) {
- final ActivityRecord activity = createTestActivityRecord(task.getDisplayContent());
- task.addChild(activity, 0);
- return createWindow(null, type, activity, name);
- }
-
- // TODO: Move these calls to a builder?
- WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name,
- IWindow iwindow) {
- final WindowToken token = createWindowToken(
- dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type);
- return createWindow(parent, type, token, name, 0 /* ownerId */,
- false /* ownerCanAddInternalSystemWindow */, iwindow);
- }
-
WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name) {
- final WindowToken token = createWindowToken(
- dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type);
- return createWindow(parent, type, token, name, 0 /* ownerId */);
+ return createWindow(
+ parent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, type, dc, name);
}
WindowState createWindow(WindowState parent, int type, DisplayContent dc, String name,
@@ -446,6 +399,87 @@ class WindowTestsBase extends SystemServiceTestsBase {
return task;
}
+ /** Creates an {@link ActivityRecord}. */
+ static ActivityRecord createNonAttachedActivityRecord(DisplayContent dc) {
+ final ActivityRecord activity = new ActivityBuilder(dc.mWmService.mAtmService)
+ .setOnTop(true)
+ .build();
+ postCreateActivitySetup(activity, dc);
+ return activity;
+ }
+
+ /**
+ * Creates an {@link ActivityRecord} and adds it to a new created {@link Task}.
+ * [Task] - [ActivityRecord]
+ */
+ ActivityRecord createActivityRecord(DisplayContent dc) {
+ return createActivityRecord(dc, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ }
+
+ /**
+ * Creates an {@link ActivityRecord} and adds it to a new created {@link Task}.
+ * [Task] - [ActivityRecord]
+ */
+ ActivityRecord createActivityRecord(DisplayContent dc, int windowingMode,
+ int activityType) {
+ final Task task = createTaskStackOnDisplay(windowingMode, activityType, dc);
+ return createActivityRecord(dc, task);
+ }
+
+ /**
+ * Creates an {@link ActivityRecord} and adds it to the specified {@link Task}.
+ * [Task] - [ActivityRecord]
+ */
+ static ActivityRecord createActivityRecord(Task task) {
+ return createActivityRecord(task.getDisplayContent(), task);
+ }
+
+ /**
+ * Creates an {@link ActivityRecord} and adds it to the specified {@link Task}.
+ * [Task] - [ActivityRecord]
+ */
+ static ActivityRecord createActivityRecord(DisplayContent dc, Task task) {
+ final ActivityRecord activity = new ActivityBuilder(dc.mWmService.mAtmService)
+ .setTask(task)
+ .setOnTop(true)
+ .build();
+ postCreateActivitySetup(activity, dc);
+ return activity;
+ }
+
+ /**
+ * Creates an {@link ActivityRecord} and adds it to a new created {@link Task}.
+ * Then adds the new created {@link Task} to a new created parent {@link Task}
+ * [Task1] - [Task2] - [ActivityRecord]
+ */
+ ActivityRecord createActivityRecordWithParentTask(DisplayContent dc, int windowingMode,
+ int activityType) {
+ final Task task = createTaskStackOnDisplay(windowingMode, activityType, dc);
+ return createActivityRecordWithParentTask(task);
+ }
+
+ /**
+ * Creates an {@link ActivityRecord} and adds it to a new created {@link Task}.
+ * Then adds the new created {@link Task} to the specified parent {@link Task}
+ * [Task1] - [Task2] - [ActivityRecord]
+ */
+ static ActivityRecord createActivityRecordWithParentTask(Task parentTask) {
+ final ActivityRecord activity = new ActivityBuilder(parentTask.mAtmService)
+ .setParentTask(parentTask)
+ .setCreateTask(true)
+ .setOnTop(true)
+ .build();
+ postCreateActivitySetup(activity, parentTask.getDisplayContent());
+ return activity;
+ }
+
+ private static void postCreateActivitySetup(ActivityRecord activity, DisplayContent dc) {
+ activity.onDisplayChanged(dc);
+ activity.setOccludesParent(true);
+ activity.setVisible(true);
+ activity.mVisibleRequested = true;
+ }
+
/** Creates a {@link DisplayContent} that supports IME and adds it to the system. */
DisplayContent createNewDisplay() {
return createNewDisplay(true /* supportIme */);
@@ -614,19 +648,20 @@ class WindowTestsBase extends SystemServiceTestsBase {
private String mProcessName = "name";
private String mAffinity;
private int mUid = 12345;
- private boolean mCreateTask;
- private Task mStack;
+ private boolean mCreateTask = false;
+ private Task mParentTask;
private int mActivityFlags;
private int mLaunchMode;
private int mResizeMode = RESIZE_MODE_RESIZEABLE;
private float mMaxAspectRatio;
private int mScreenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
- private boolean mLaunchTaskBehind;
+ private boolean mLaunchTaskBehind = false;
private int mConfigChanges;
private int mLaunchedFromPid;
private int mLaunchedFromUid;
private WindowProcessController mWpc;
private Bundle mIntentExtras;
+ private boolean mOnTop = false;
ActivityBuilder(ActivityTaskManagerService service) {
mService = service;
@@ -667,8 +702,8 @@ class WindowTestsBase extends SystemServiceTestsBase {
return this;
}
- ActivityBuilder setStack(Task stack) {
- mStack = stack;
+ ActivityBuilder setParentTask(Task parentTask) {
+ mParentTask = parentTask;
return this;
}
@@ -732,6 +767,11 @@ class WindowTestsBase extends SystemServiceTestsBase {
return this;
}
+ ActivityBuilder setOnTop(boolean onTop) {
+ mOnTop = onTop;
+ return this;
+ }
+
ActivityRecord build() {
SystemServicesTestRule.checkHoldsLock(mService.mGlobalLock);
try {
@@ -752,11 +792,11 @@ class WindowTestsBase extends SystemServiceTestsBase {
if (mCreateTask) {
mTask = new TaskBuilder(mService.mStackSupervisor)
.setComponent(mComponent)
- .setParentTask(mStack).build();
- } else if (mTask == null && mStack != null && DisplayContent.alwaysCreateStack(
- mStack.getWindowingMode(), mStack.getActivityType())) {
+ .setParentTask(mParentTask).build();
+ } else if (mTask == null && mParentTask != null && DisplayContent.alwaysCreateStack(
+ mParentTask.getWindowingMode(), mParentTask.getActivityType())) {
// The stack can be the task root.
- mTask = mStack;
+ mTask = mParentTask;
}
Intent intent = new Intent();
@@ -800,6 +840,9 @@ class WindowTestsBase extends SystemServiceTestsBase {
// to set it somewhere else since we can't mock resources.
doReturn(true).when(activity).occludesParent();
doReturn(true).when(activity).fillsParent();
+ if (mOnTop) {
+ mTask.moveToFront("createActivity");
+ }
mTask.addChild(activity);
// Make visible by default...
activity.setVisible(true);
@@ -992,8 +1035,7 @@ class WindowTestsBase extends SystemServiceTestsBase {
// Create child task with activity.
if (mCreateActivity) {
new ActivityBuilder(mSupervisor.mService)
- .setCreateTask(true)
- .setStack(task)
+ .setTask(task)
.build();
if (mOnTop) {
// We move the task to front again in order to regain focus after activity
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index dfb7280e7e54..e44d47a59fe5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -345,16 +345,16 @@ public class ZOrderingTests extends WindowTestsBase {
@Test
public void testStackLayers() {
final WindowState anyWindow1 = createWindow("anyWindow");
- final WindowState pinnedStackWindow = createWindowOnStack(null, WINDOWING_MODE_PINNED,
+ final WindowState pinnedStackWindow = createWindow(null, WINDOWING_MODE_PINNED,
ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent,
"pinnedStackWindow");
- final WindowState dockedStackWindow = createWindowOnStack(null,
+ final WindowState dockedStackWindow = createWindow(null,
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION,
mDisplayContent, "dockedStackWindow");
- final WindowState assistantStackWindow = createWindowOnStack(null,
+ final WindowState assistantStackWindow = createWindow(null,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, TYPE_BASE_APPLICATION,
mDisplayContent, "assistantStackWindow");
- final WindowState homeActivityWindow = createWindowOnStack(null, WINDOWING_MODE_FULLSCREEN,
+ final WindowState homeActivityWindow = createWindow(null, WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_HOME, TYPE_BASE_APPLICATION,
mDisplayContent, "homeActivityWindow");
final WindowState anyWindow2 = createWindow("anyWindow2");
@@ -432,16 +432,16 @@ public class ZOrderingTests extends WindowTestsBase {
@Test
public void testDockedDividerPosition() {
- final WindowState pinnedStackWindow = createWindowOnStack(null, WINDOWING_MODE_PINNED,
+ final WindowState pinnedStackWindow = createWindow(null, WINDOWING_MODE_PINNED,
ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent,
"pinnedStackWindow");
- final WindowState splitScreenWindow = createWindowOnStack(null,
+ final WindowState splitScreenWindow = createWindow(null,
WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION,
mDisplayContent, "splitScreenWindow");
- final WindowState splitScreenSecondaryWindow = createWindowOnStack(null,
+ final WindowState splitScreenSecondaryWindow = createWindow(null,
WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
TYPE_BASE_APPLICATION, mDisplayContent, "splitScreenSecondaryWindow");
- final WindowState assistantStackWindow = createWindowOnStack(null,
+ final WindowState assistantStackWindow = createWindow(null,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, TYPE_BASE_APPLICATION,
mDisplayContent, "assistantStackWindow");
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index a85eb53605d6..1238e7b69a87 100755
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -1468,8 +1468,11 @@ public final class Call {
/**
* Writes the string {@param input} into the outgoing text stream for this RTT call. Since
- * RTT transmits text in real-time, this method should be called once for each character
- * the user enters into the device.
+ * RTT transmits text in real-time, this method should be called once for each user action.
+ * For example, when the user enters text as discrete characters using the keyboard, this
+ * method should be called once for each character. However, if the user enters text by
+ * pasting or autocomplete, the entire contents of the pasted or autocompleted text should
+ * be sent in one call to this method.
*
* This method is not thread-safe -- calling it from multiple threads simultaneously may
* lead to interleaved text.
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c982f490e0fd..425addc70dae 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -12015,12 +12015,13 @@ public class TelephonyManager {
* @hide
*/
@SystemApi
+ @TestApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @NetworkTypeBitMask long getSupportedRadioAccessFamily() {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return (long) telephony.getRadioAccessFamily(getSlotIndex(), getOpPackageName());
+ return telephony.getRadioAccessFamily(getSlotIndex(), getOpPackageName());
} else {
// This can happen when the ITelephony interface is not up yet.
return NETWORK_TYPE_BITMASK_UNKNOWN;
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index a7586ec4ec18..5a32075f6aa8 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -29,12 +29,10 @@ import android.os.RemoteException;
import android.provider.Settings;
import android.telephony.AccessNetworkConstants;
import android.telephony.CarrierConfigManager;
-import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsRcsController;
import android.telephony.ims.feature.ImsFeature;
-import android.telephony.ims.feature.RcsFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Log;
@@ -77,7 +75,7 @@ public class ImsRcsManager {
"android.telephony.ims.action.SHOW_CAPABILITY_DISCOVERY_OPT_IN";
/**
- * Receives RCS availability status updates from the ImsService.
+ * Receives RCS Feature availability status updates from the ImsService.
*
* @see #isAvailable(int)
* @see #registerRcsAvailabilityCallback(Executor, AvailabilityCallback)
@@ -101,8 +99,7 @@ public class ImsRcsManager {
final long callingIdentity = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged(
- new RcsFeature.RcsImsCapabilities(config)));
+ mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged(config));
} finally {
restoreCallingIdentity(callingIdentity);
}
@@ -137,7 +134,7 @@ public class ImsRcsManager {
*
* @param capabilities The new availability of the capabilities.
*/
- public void onAvailabilityChanged(@NonNull RcsFeature.RcsImsCapabilities capabilities) {
+ public void onAvailabilityChanged(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
}
/**@hide*/
@@ -394,7 +391,7 @@ public class ImsRcsManager {
* @hide
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public boolean isCapable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+ public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int radioTech) throws ImsException {
IImsRcsController imsRcsController = getIImsRcsController();
if (imsRcsController == null) {
@@ -428,7 +425,7 @@ public class ImsRcsManager {
* @hide
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public boolean isAvailable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability)
+ public boolean isAvailable(@RcsUceAdapter.RcsImsCapabilityFlag int capability)
throws ImsException {
IImsRcsController imsRcsController = getIImsRcsController();
if (imsRcsController == null) {
diff --git a/core/tests/coretests/src/android/app/appsearch/external/app/SearchResultsTest.java b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.aidl
index acbf11ae8669..cd1ee8400d3e 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/SearchResultsTest.java
+++ b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * 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.
@@ -14,17 +14,7 @@
* limitations under the License.
*/
-package android.app.appsearch;
-import static org.testng.Assert.expectThrows;
+package android.telephony.ims;
-import org.junit.Test;
-
-public class SearchResultsTest {
- @Test
- public void buildSearchSpecWithoutTermMatchType() {
- expectThrows(RuntimeException.class, () -> new SearchSpec.Builder()
- .setSchemaTypes("testSchemaType")
- .build());
- }
-}
+parcelable RcsContactTerminatedReason;
diff --git a/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java
new file mode 100644
index 000000000000..ee02564267c0
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java
@@ -0,0 +1,75 @@
+/*
+ * 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 android.telephony.ims;
+
+import android.annotation.NonNull;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * When the resource for the presence subscribe event has been terminated, the method
+ * SubscribeResponseCallback#onResourceTerminated wil be called with a list of
+ * RcsContactTerminatedReason.
+ * @hide
+ */
+public final class RcsContactTerminatedReason implements Parcelable {
+ private final Uri mContactUri;
+ private final String mReason;
+
+ public RcsContactTerminatedReason(Uri contact, String reason) {
+ mContactUri = contact;
+ mReason = reason;
+ }
+
+ private RcsContactTerminatedReason(Parcel in) {
+ mContactUri = in.readParcelable(Uri.class.getClassLoader());
+ mReason = in.readString();
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeParcelable(mContactUri, flags);
+ out.writeString(mReason);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final @NonNull Creator<RcsContactTerminatedReason> CREATOR =
+ new Creator<RcsContactTerminatedReason>() {
+ @Override
+ public RcsContactTerminatedReason createFromParcel(Parcel in) {
+ return new RcsContactTerminatedReason(in);
+ }
+
+ @Override
+ public RcsContactTerminatedReason[] newArray(int size) {
+ return new RcsContactTerminatedReason[size];
+ }
+ };
+
+ public Uri getContactUri() {
+ return mContactUri;
+ }
+
+ public String getReason() {
+ return mReason;
+ }
+}
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index c2ddcea3dbd3..0aeaecc2af5e 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -47,6 +47,30 @@ public class RcsUceAdapter {
private static final String TAG = "RcsUceAdapter";
/**
+ * This carrier supports User Capability Exchange as, defined by the framework using
+ * SIP OPTIONS. If set, the RcsFeature should support capability exchange. If not set, this
+ * RcsFeature should not publish capabilities or service capability requests.
+ * @hide
+ */
+ public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1 << 0;
+
+ /**
+ * This carrier supports User Capability Exchange as, defined by the framework using a
+ * presence server. If set, the RcsFeature should support capability exchange. If not set, this
+ * RcsFeature should not publish capabilities or service capability requests.
+ * @hide
+ */
+ public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1;
+
+ /**@hide*/
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "CAPABILITY_TYPE_", value = {
+ CAPABILITY_TYPE_OPTIONS_UCE,
+ CAPABILITY_TYPE_PRESENCE_UCE
+ })
+ public @interface RcsImsCapabilityFlag {}
+
+ /**
* An unknown error has caused the request to fail.
* @hide
*/
@@ -106,11 +130,6 @@ public class RcsUceAdapter {
* @hide
*/
public static final int ERROR_LOST_NETWORK = 12;
- /**
- * The request has failed because the same request has already been added to the queue.
- * @hide
- */
- public static final int ERROR_ALREADY_IN_QUEUE = 13;
/**@hide*/
@Retention(RetentionPolicy.SOURCE)
@@ -125,12 +144,90 @@ public class RcsUceAdapter {
ERROR_REQUEST_TOO_LARGE,
ERROR_REQUEST_TIMEOUT,
ERROR_INSUFFICIENT_MEMORY,
- ERROR_LOST_NETWORK,
- ERROR_ALREADY_IN_QUEUE
+ ERROR_LOST_NETWORK
})
public @interface ErrorCode {}
/**
+ * A capability update has been requested due to the Entity Tag (ETag) expiring.
+ * @hide
+ */
+ public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 0;
+ /**
+ * A capability update has been requested due to moving to LTE with VoPS disabled.
+ * @hide
+ */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 1;
+ /**
+ * A capability update has been requested due to moving to LTE with VoPS enabled.
+ * @hide
+ */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 2;
+ /**
+ * A capability update has been requested due to moving to eHRPD.
+ * @hide
+ */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 3;
+ /**
+ * A capability update has been requested due to moving to HSPA+.
+ * @hide
+ */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 4;
+ /**
+ * A capability update has been requested due to moving to 3G.
+ * @hide
+ */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 5;
+ /**
+ * A capability update has been requested due to moving to 2G.
+ * @hide
+ */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 6;
+ /**
+ * A capability update has been requested due to moving to WLAN
+ * @hide
+ */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 7;
+ /**
+ * A capability update has been requested due to moving to IWLAN
+ * @hide
+ */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 8;
+ /**
+ * A capability update has been requested but the reason is unknown.
+ * @hide
+ */
+ public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 9;
+ /**
+ * A capability update has been requested due to moving to 5G NR with VoPS disabled.
+ * @hide
+ */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10;
+ /**
+ * A capability update has been requested due to moving to 5G NR with VoPS enabled.
+ * @hide
+ */
+ public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11;
+
+ /**@hide*/
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "ERROR_", value = {
+ CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN,
+ CAPABILITY_UPDATE_TRIGGER_UNKNOWN,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED,
+ CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED
+ })
+ public @interface StackPublishTriggerType {}
+
+ /**
* The last publish has resulted in a "200 OK" response or the device is using SIP OPTIONS for
* UCE.
* @hide
@@ -238,38 +335,49 @@ public class RcsUceAdapter {
}
/**
- * Provides a one-time callback for the response to a UCE request. After this callback is called
- * by the framework, the reference to this callback will be discarded on the service side.
+ * A callback for the response to a UCE request. The method
+ * {@link CapabilitiesCallback#onCapabilitiesReceived} will be called zero or more times as the
+ * capabilities are received for each requested contact.
+ * <p>
+ * This request will take a varying amount of time depending on if the contacts requested are
+ * cached or if it requires a network query. The timeout time of these requests can vary
+ * depending on the network, however in poor cases it could take up to a minute for a request
+ * to timeout. In that time only a subset of capabilities may have been retrieved.
+ * <p>
+ * After {@link CapabilitiesCallback#onComplete} or {@link CapabilitiesCallback#onError} has
+ * been called, the reference to this callback will be discarded on the service side.
* @see #requestCapabilities(Executor, List, CapabilitiesCallback)
* @hide
*/
- public static class CapabilitiesCallback {
+ public interface CapabilitiesCallback {
/**
- * Notify this application that the pending capability request has returned successfully.
+ * Notify this application that the pending capability request has returned successfully
+ * for one or more of the requested contacts.
* @param contactCapabilities List of capabilities associated with each contact requested.
*/
- public void onCapabilitiesReceived(
- @NonNull List<RcsContactUceCapability> contactCapabilities) {
+ void onCapabilitiesReceived(@NonNull List<RcsContactUceCapability> contactCapabilities);
- }
+ /**
+ * The pending request has completed successfully due to all requested contacts information
+ * being delivered.
+ */
+ void onComplete();
/**
* The pending request has resulted in an error and may need to be retried, depending on the
* error code.
* @param errorCode The reason for the framework being unable to process the request.
*/
- public void onError(@ErrorCode int errorCode) {
-
- }
+ void onError(@ErrorCode int errorCode);
}
private final Context mContext;
private final int mSubId;
/**
- * Not to be instantiated directly, use
- * {@link ImsRcsManager#getUceAdapter()} to instantiate this manager class.
+ * Not to be instantiated directly, use {@link ImsRcsManager#getUceAdapter()} to instantiate
+ * this manager class.
* @hide
*/
RcsUceAdapter(Context context, int subId) {
@@ -280,6 +388,9 @@ public class RcsUceAdapter {
/**
* Request the User Capability Exchange capabilities for one or more contacts.
* <p>
+ * This will return the cached capabilities of the contact and will not perform a capability
+ * poll on the network unless there are contacts being queried with stale information.
+ * <p>
* Be sure to check the availability of this feature using
* {@link ImsRcsManager#isAvailable(int)} and ensuring
* {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or
@@ -302,7 +413,7 @@ public class RcsUceAdapter {
@NonNull List<Uri> contactNumbers,
@NonNull CapabilitiesCallback c) throws ImsException {
if (c == null) {
- throw new IllegalArgumentException("Must include a non-null AvailabilityCallback.");
+ throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback.");
}
if (executor == null) {
throw new IllegalArgumentException("Must include a non-null Executor.");
@@ -330,6 +441,15 @@ public class RcsUceAdapter {
}
}
@Override
+ public void onComplete() {
+ final long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> c.onComplete());
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
+ }
+ @Override
public void onError(int errorCode) {
final long callingIdentity = Binder.clearCallingIdentity();
try {
@@ -351,6 +471,88 @@ public class RcsUceAdapter {
}
/**
+ * Ignore the device cache and perform a capability discovery for one contact, also called
+ * "availability fetch."
+ * <p>
+ * This will always perform a query to the network as long as requests are over the carrier
+ * availability fetch throttling threshold. If too many network requests are sent too quickly,
+ * #ERROR_TOO_MANY_REQUESTS will be returned.
+ *
+ * <p>
+ * Be sure to check the availability of this feature using
+ * {@link ImsRcsManager#isAvailable(int)} and ensuring
+ * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or
+ * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} is
+ * enabled or else this operation will fail with
+ * {@link #ERROR_NOT_AVAILABLE} or {@link #ERROR_NOT_ENABLED}.
+ *
+ * @param contactNumber The contact of the capabilities is being requested for.
+ * @param c A one-time callback for when the request for capabilities completes or there is
+ * an error processing the request.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public void requestNetworkAvailability(@NonNull @CallbackExecutor Executor executor,
+ @NonNull Uri contactNumber, @NonNull CapabilitiesCallback c) throws ImsException {
+ if (executor == null) {
+ throw new IllegalArgumentException("Must include a non-null Executor.");
+ }
+ if (contactNumber == null) {
+ throw new IllegalArgumentException("Must include non-null contact number.");
+ }
+ if (c == null) {
+ throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback.");
+ }
+
+ IImsRcsController imsRcsController = getIImsRcsController();
+ if (imsRcsController == null) {
+ Log.e(TAG, "requestNetworkAvailability: IImsRcsController is null");
+ throw new ImsException("Cannot find remote IMS service",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+
+ IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() {
+ @Override
+ public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) {
+ final long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() ->
+ c.onCapabilitiesReceived(contactCapabilities));
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
+ }
+ @Override
+ public void onComplete() {
+ final long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> c.onComplete());
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
+ }
+ @Override
+ public void onError(int errorCode) {
+ final long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> c.onError(errorCode));
+ } finally {
+ restoreCallingIdentity(callingIdentity);
+ }
+ }
+ };
+
+ try {
+ imsRcsController.requestNetworkAvailability(mSubId, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), contactNumber, internalCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling IImsRcsController#requestNetworkAvailability", e);
+ throw new ImsException("Remote IMS Service is not available",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ }
+
+ /**
* Gets the last publish result from the UCE service if the device is using an RCS presence
* server.
* @return The last publish result from the UCE service. If the device is using SIP OPTIONS,
diff --git a/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl b/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl
new file mode 100644
index 000000000000..a4ffbef9fa84
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl
@@ -0,0 +1,75 @@
+/*
+ * 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 android.telephony.ims.aidl;
+
+import android.net.Uri;
+import android.telephony.ims.aidl.IOptionsRequestCallback;
+
+import java.util.List;
+
+/**
+ * Listener interface for the ImsService to use to notify the framework of UCE events.
+ * {@hide}
+ */
+oneway interface ICapabilityExchangeEventListener {
+ /**
+ * Trigger the framework to provide a capability update using
+ * {@link RcsCapabilityExchangeImplBase#publishCapabilities}.
+ * <p>
+ * This is typically used when trying to generate an initial PUBLISH for a new
+ * subscription to the network. The device will cache all presence publications
+ * after boot until this method is called the first time.
+ * @param publishTriggerType {@link StackPublishTriggerType} The reason for the
+ * capability update request.
+ * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is
+ * not currently connected to the framework. This can happen if the
+ * {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the
+ * {@link RcsFeature} has not received the
+ * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare
+ * cases when the Telephony stack has crashed.
+ */
+ void onRequestPublishCapabilities(int publishTriggerType);
+
+ /**
+ * Notify the framework that the device's capabilities have been unpublished from the network.
+ *
+ * @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is not currently
+ * connected to the framework. This can happen if the {@link RcsFeature} is not
+ * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the
+ * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the
+ * Telephony stack has crashed.
+ */
+ void onUnpublish();
+
+ /**
+ * Inform the framework of a query for this device's UCE capabilities.
+ * <p>
+ * The framework will respond via the
+ * {@link IOptionsRequestCallback#respondToCapabilityRequest} or
+ * {@link IOptionsRequestCallback#respondToCapabilityRequestWithError} method.
+ * @param contactUri The URI associated with the remote contact that is requesting capabilities.
+ * @param remoteCapabilities The remote contact's capability information.
+ * @throws ImsException If this {@link RcsSipOptionsImplBase} instance is not currently
+ * connected to the framework. This can happen if the {@link RcsFeature} is not
+ * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received
+ * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when
+ * the Telephony stack has crashed.
+ */
+ void onRemoteCapabilityRequest(in Uri contactUri,
+ in List<String> remoteCapabilities,
+ IOptionsRequestCallback cb);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
index 6d25a09e079f..8e84e9373f65 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
@@ -47,6 +47,9 @@ interface IImsRcsController {
// ImsUceAdapter specific
void requestCapabilities(int subId, String callingPackage, String callingFeatureId,
in List<Uri> contactNumbers, IRcsUceControllerCallback c);
+ void requestNetworkAvailability(int subId, String callingPackage,
+ String callingFeatureId, in Uri contactNumber,
+ IRcsUceControllerCallback c);
int getUcePublishState(int subId);
boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId);
void setUceSettingEnabled(int subId, boolean isEnabled);
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl
index 4b98b79f1095..b47e3c75b558 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl
@@ -18,8 +18,12 @@ package android.telephony.ims.aidl;
import android.net.Uri;
import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.aidl.ICapabilityExchangeEventListener;
import android.telephony.ims.aidl.IImsCapabilityCallback;
+import android.telephony.ims.aidl.IOptionsResponseCallback;
+import android.telephony.ims.aidl.IPublishResponseCallback;
import android.telephony.ims.aidl.IRcsFeatureListener;
+import android.telephony.ims.aidl.ISubscribeResponseCallback;
import android.telephony.ims.feature.CapabilityChangeRequest;
import java.util.List;
@@ -40,6 +44,12 @@ interface IImsRcsFeature {
IImsCapabilityCallback c);
oneway void queryCapabilityConfiguration(int capability, int radioTech,
IImsCapabilityCallback c);
+ // RcsCapabilityExchangeImplBase specific api
+ oneway void setCapabilityExchangeEventListener(ICapabilityExchangeEventListener listener);
+ oneway void publishCapabilities(in String pidfXml, IPublishResponseCallback cb);
+ oneway void subscribeForCapabilities(in List<Uri> uris, ISubscribeResponseCallback cb);
+ oneway void sendOptionsCapabilityRequest(in Uri contactUri,
+ in List<String> myCapabilities, IOptionsResponseCallback cb);
// RcsPresenceExchangeImplBase specific api
oneway void requestCapabilities(in List<Uri> uris, int operationToken);
oneway void updateCapabilities(in RcsContactUceCapability capabilities, int operationToken);
@@ -50,4 +60,4 @@ interface IImsRcsFeature {
in RcsContactUceCapability ownCapabilities, int operationToken);
oneway void respondToCapabilityRequestWithError(in Uri contactUri, int code, in String reason,
int operationToken);
-} \ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl b/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl
new file mode 100644
index 000000000000..d55670dd313b
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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 android.telephony.ims.aidl;
+
+import android.telephony.ims.RcsContactUceCapability;
+
+/**
+ * Interface used by the framework to respond to OPTIONS requests.
+ * {@hide}
+ */
+oneway interface IOptionsRequestCallback {
+ /**
+ * Respond to a remote capability request from the contact specified with the capabilities
+ * of this device.
+ * @param ownCapabilities The capabilities of this device.
+ */
+ void respondToCapabilityRequest(in RcsContactUceCapability ownCapabilities);
+
+ /**
+ * Respond to a remote capability request from the contact specified with the
+ * specified error.
+ * @param contactUri A URI containing the remote contact.
+ * @param code The SIP response code to respond with.
+ * @param reason A non-null String containing the reason associated with the SIP code.
+ */
+ void respondToCapabilityRequestWithError(int code, String reason);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IOptionsResponseCallback.aidl b/telephony/java/android/telephony/ims/aidl/IOptionsResponseCallback.aidl
new file mode 100644
index 000000000000..a8c8329fe55e
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/IOptionsResponseCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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 android.telephony.ims.aidl;
+
+import java.util.List;
+
+/**
+ * Interface used by the framework to receive the response from the remote user
+ * through {@link RcsCapabilityExchangeImplBase#sendOptionsCapabilityRequest}
+ * {@hide}
+ */
+oneway interface IOptionsResponseCallback {
+ void onCommandError(int code);
+ void onNetworkResponse(int code, String reason, in List<String> theirCaps);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl b/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl
new file mode 100644
index 000000000000..481e7f8b37b9
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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 android.telephony.ims.aidl;
+
+import java.util.List;
+
+/**
+ * Interface used by the framework to receive the response of the publish
+ * request through {@link RcsCapabilityExchangeImplBase#publishCapabilities}
+ * {@hide}
+ */
+oneway interface IPublishResponseCallback {
+ void onCommandError(int code);
+ void onNetworkResponse(int code, String reason);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl b/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl
index 5975930d5cfa..0bd3e5ed354e 100644
--- a/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl
@@ -25,5 +25,6 @@ import android.telephony.ims.RcsContactUceCapability;
*/
oneway interface IRcsUceControllerCallback {
void onCapabilitiesReceived(in List<RcsContactUceCapability> contactCapabilities);
+ void onComplete();
void onError(int errorCode);
}
diff --git a/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl
new file mode 100644
index 000000000000..4deaba1b7a49
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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 android.telephony.ims.aidl;
+
+import android.net.Uri;
+import android.telephony.ims.RcsContactTerminatedReason;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Interface used by the framework to receive the response of the subscribe
+ * request through {@link RcsCapabilityExchangeImplBase#subscribeForCapabilities}
+ * {@hide}
+ */
+oneway interface ISubscribeResponseCallback {
+ void onCommandError(int code);
+ void onNetworkResponse(int code, in String reason);
+ void onNotifyCapabilitiesUpdate(in List<String> pidfXmls);
+ void onResourceTerminated(in List<RcsContactTerminatedReason> uriTerminatedReason);
+ void onTerminated(in String reason, in String retryAfter);
+}
diff --git a/telephony/java/android/telephony/ims/aidl/RcsOptionsResponseAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/RcsOptionsResponseAidlWrapper.java
new file mode 100644
index 000000000000..47a96af1cba1
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/RcsOptionsResponseAidlWrapper.java
@@ -0,0 +1,54 @@
+/*
+ * 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 android.telephony.ims.aidl;
+
+import android.os.RemoteException;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback;
+
+import java.util.List;
+
+/**
+ * Implementation of the callback OptionsResponseCallback by wrapping the internal AIDL from
+ * telephony.
+ * @hide
+ */
+public class RcsOptionsResponseAidlWrapper implements OptionsResponseCallback {
+
+ private final IOptionsResponseCallback mResponseBinder;
+
+ public RcsOptionsResponseAidlWrapper(IOptionsResponseCallback responseBinder) {
+ mResponseBinder = responseBinder;
+ }
+
+ @Override
+ public void onCommandError(int code) {
+ try {
+ mResponseBinder.onCommandError(code);
+ } catch (RemoteException e) {
+ }
+ }
+
+ @Override
+ public void onNetworkResponse(int code, String reason, List<String> theirCaps)
+ throws ImsException {
+ try {
+ mResponseBinder.onNetworkResponse(code, reason, theirCaps);
+ } catch (RemoteException e) {
+ }
+ }
+}
diff --git a/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java
new file mode 100644
index 000000000000..22985d0cf85c
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java
@@ -0,0 +1,51 @@
+/*
+ * 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 android.telephony.ims.aidl;
+
+import android.os.RemoteException;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback;
+
+/**
+ * Implementation of the callback PublishResponseCallback by wrapping the internal AIDL from
+ * telephony.
+ * @hide
+ */
+public class RcsPublishResponseAidlWrapper implements PublishResponseCallback {
+
+ private final IPublishResponseCallback mResponseBinder;
+
+ public RcsPublishResponseAidlWrapper(IPublishResponseCallback responseBinder) {
+ mResponseBinder = responseBinder;
+ }
+
+ @Override
+ public void onCommandError(int code) {
+ try {
+ mResponseBinder.onCommandError(code);
+ } catch (RemoteException e) {
+ }
+ }
+
+ @Override
+ public void onNetworkResponse(int code, String reason) throws ImsException {
+ try {
+ mResponseBinder.onNetworkResponse(code, reason);
+ } catch (RemoteException e) {
+ }
+ }
+}
diff --git a/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java
new file mode 100644
index 000000000000..37588ed98585
--- /dev/null
+++ b/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java
@@ -0,0 +1,95 @@
+/*
+ * 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 android.telephony.ims.aidl;
+
+import android.net.Uri;
+import android.os.RemoteException;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.RcsContactTerminatedReason;
+import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback;
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Implementation of the callback OptionsResponseCallback by wrapping the internal AIDL from
+ * telephony.
+ * @hide
+ */
+public class RcsSubscribeResponseAidlWrapper implements SubscribeResponseCallback {
+
+ private final ISubscribeResponseCallback mResponseBinder;
+
+ public RcsSubscribeResponseAidlWrapper(ISubscribeResponseCallback responseBinder) {
+ mResponseBinder = responseBinder;
+ }
+
+ @Override
+ public void onCommandError(int code) {
+ try {
+ mResponseBinder.onCommandError(code);
+ } catch (RemoteException e) {
+ }
+ }
+
+ @Override
+ public void onNetworkResponse(int code, String reason) throws ImsException {
+ try {
+ mResponseBinder.onNetworkResponse(code, reason);
+ } catch (RemoteException e) {
+ }
+ }
+
+ @Override
+ public void onNotifyCapabilitiesUpdate(List<String> pidfXmls) throws ImsException {
+ try {
+ mResponseBinder.onNotifyCapabilitiesUpdate(pidfXmls);
+ } catch (RemoteException e) {
+ }
+ }
+
+ @Override
+ public void onResourceTerminated(List<Pair<Uri, String>> uriTerminatedReason)
+ throws ImsException {
+ try {
+ mResponseBinder.onResourceTerminated(getTerminatedReasonList(uriTerminatedReason));
+ } catch (RemoteException e) {
+ }
+ }
+
+ private List<RcsContactTerminatedReason> getTerminatedReasonList(
+ List<Pair<Uri, String>> uriTerminatedReason) {
+ List<RcsContactTerminatedReason> uriTerminatedReasonList = new ArrayList<>();
+ if (uriTerminatedReason != null) {
+ for (Pair<Uri, String> pair : uriTerminatedReason) {
+ RcsContactTerminatedReason reason =
+ new RcsContactTerminatedReason(pair.first, pair.second);
+ uriTerminatedReasonList.add(reason);
+ }
+ }
+ return uriTerminatedReasonList;
+ }
+
+ @Override
+ public void onTerminated(String reason, String retryAfter) throws ImsException {
+ try {
+ mResponseBinder.onTerminated(reason, retryAfter);
+ } catch (RemoteException e) {
+ }
+ }
+}
diff --git a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
index 87a5094a95f3..87a6873d00b2 100644
--- a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
+++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
@@ -28,8 +28,8 @@ import java.util.List;
import java.util.Set;
/**
- * Request to send to IMS provider, which will try to enable/disable capabilities that are added to
- * the request.
+ * Used by the framework to enable and disable MMTEL and RCS capabilities. See
+ * MmTelFeature#changeEnabledCapabilities and RcsFeature#changeEnabledCapabilities.
* {@hide}
*/
@SystemApi
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index b8ae146784d4..5de2ddc578a1 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -23,12 +23,22 @@ import android.annotation.SystemApi;
import android.net.Uri;
import android.os.RemoteException;
import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.RcsUceAdapter;
+import android.telephony.ims.aidl.ICapabilityExchangeEventListener;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsRcsFeature;
+import android.telephony.ims.aidl.IOptionsResponseCallback;
+import android.telephony.ims.aidl.IPublishResponseCallback;
import android.telephony.ims.aidl.IRcsFeatureListener;
+import android.telephony.ims.aidl.ISubscribeResponseCallback;
+import android.telephony.ims.aidl.RcsOptionsResponseAidlWrapper;
+import android.telephony.ims.aidl.RcsPublishResponseAidlWrapper;
+import android.telephony.ims.aidl.RcsSubscribeResponseAidlWrapper;
import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.telephony.ims.stub.RcsPresenceExchangeImplBase;
-import android.telephony.ims.stub.RcsSipOptionsImplBase;
+import android.telephony.ims.stub.RcsCapabilityExchangeImplBase;
+import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback;
+import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback;
+import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback;
import android.util.Log;
import com.android.internal.telephony.util.TelephonyUtils;
@@ -64,9 +74,14 @@ public class RcsFeature extends ImsFeature {
mExecutor = executor;
}
+ /**
+ * @deprecated This method is deprecated. Please call the method
+ * setCapabilityExchangeEventListener instead.
+ */
@Override
+ @Deprecated
public void setListener(IRcsFeatureListener listener) {
- mReference.setListener(listener);
+ Log.w(LOG_TAG, "The method setListener is deprecated");
}
@Override
@@ -106,44 +121,66 @@ public class RcsFeature extends ImsFeature {
return executeMethodAsyncForResult(mReference::getFeatureState, "getFeatureState");
}
+ // RcsCapabilityExchangeImplBase specific APIs
+ @Override
+ public void setCapabilityExchangeEventListener(
+ @NonNull ICapabilityExchangeEventListener listener) throws RemoteException {
+ executeMethodAsync(() -> mReference.setCapabilityExchangeEventListener(listener),
+ "setCapabilityExchangeEventListener");
+ }
+
+ @Override
+ public void publishCapabilities(@NonNull String pidfXml,
+ @NonNull IPublishResponseCallback callback) throws RemoteException {
+ PublishResponseCallback callbackWrapper = new RcsPublishResponseAidlWrapper(callback);
+ executeMethodAsync(() -> mReference.getCapabilityExchangeImplBaseInternal()
+ .publishCapabilities(pidfXml, callbackWrapper), "publishCapabilities");
+ }
+
+ @Override
+ public void subscribeForCapabilities(@NonNull List<Uri> uris,
+ @NonNull ISubscribeResponseCallback callback) throws RemoteException {
+ SubscribeResponseCallback wrapper = new RcsSubscribeResponseAidlWrapper(callback);
+ executeMethodAsync(() -> mReference.getCapabilityExchangeImplBaseInternal()
+ .subscribeForCapabilities(uris, wrapper), "subscribeForCapabilities");
+ }
+
+ @Override
+ public void sendOptionsCapabilityRequest(@NonNull Uri contactUri,
+ @NonNull List<String> myCapabilities, @NonNull IOptionsResponseCallback callback)
+ throws RemoteException {
+ OptionsResponseCallback callbackWrapper = new RcsOptionsResponseAidlWrapper(callback);
+ executeMethodAsync(() -> mReference.getCapabilityExchangeImplBaseInternal()
+ .sendOptionsCapabilityRequest(contactUri, myCapabilities, callbackWrapper),
+ "sendOptionsCapabilityRequest");
+ }
+
// RcsPresenceExchangeImplBase specific APIS
@Override
public void requestCapabilities(List<Uri> uris, int operationToken) throws RemoteException {
- executeMethodAsync(() -> mReference.getPresenceExchangeInternal()
- .requestCapabilities(uris, operationToken), "requestCapabilities");
+ throw new RemoteException("Unsupported operation: requestCapabilities");
}
@Override
public void updateCapabilities(RcsContactUceCapability capabilities, int operationToken)
throws RemoteException {
- executeMethodAsync(() -> mReference.getPresenceExchangeInternal()
- .updateCapabilities(capabilities, operationToken),
- "updateCapabilities");
-
+ throw new RemoteException("Unsupported operation: updateCapabilities");
}
// RcsSipOptionsImplBase specific APIS
@Override
public void sendCapabilityRequest(Uri contactUri, RcsContactUceCapability capabilities,
int operationToken) throws RemoteException {
- executeMethodAsync(() -> mReference.getOptionsExchangeInternal()
- .sendCapabilityRequest(contactUri, capabilities, operationToken),
- "sendCapabilityRequest");
-
+ throw new RemoteException("Unsupported operation: sendCapabilityRequest");
}
@Override
public void respondToCapabilityRequest(String contactUri,
RcsContactUceCapability ownCapabilities, int operationToken)
throws RemoteException {
- executeMethodAsync(() -> mReference.getOptionsExchangeInternal()
- .respondToCapabilityRequest(contactUri, ownCapabilities,
- operationToken), "respondToCapabilityRequest");
-
+ throw new RemoteException("Unsupported operation: respondToCapabilityRequest");
}
@Override
public void respondToCapabilityRequestWithError(Uri contactUri, int code, String reason,
int operationToken) throws RemoteException {
- executeMethodAsync(() -> mReference.getOptionsExchangeInternal()
- .respondToCapabilityRequestWithError(contactUri, code, reason,
- operationToken), "respondToCapabilityRequestWithError");
+ throw new RemoteException("Unsupported operation: respondToCapabilityRequestWithError");
}
// Call the methods with a clean calling identity on the executor and wait indefinitely for
@@ -182,8 +219,8 @@ public class RcsFeature extends ImsFeature {
* Contains the capabilities defined and supported by a {@link RcsFeature} in the
* form of a bitmask. The capabilities that are used in the RcsFeature are
* defined as:
- * {@link RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE}
- * {@link RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE}
+ * {@link RcsUceAdatper.RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE}
+ * {@link RceUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE}
*
* The enabled capabilities of this RcsFeature will be set by the framework
* using {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}.
@@ -223,7 +260,7 @@ public class RcsFeature extends ImsFeature {
*/
public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1;
- public RcsImsCapabilities(@RcsImsCapabilityFlag int capabilities) {
+ public RcsImsCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
super(capabilities);
}
@@ -232,25 +269,24 @@ public class RcsFeature extends ImsFeature {
}
@Override
- public void addCapabilities(@RcsImsCapabilityFlag int capabilities) {
+ public void addCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
super.addCapabilities(capabilities);
}
@Override
- public void removeCapabilities(@RcsImsCapabilityFlag int capabilities) {
+ public void removeCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
super.removeCapabilities(capabilities);
}
@Override
- public boolean isCapable(@RcsImsCapabilityFlag int capabilities) {
+ public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
return super.isCapable(capabilities);
}
}
private final RcsFeatureBinder mImsRcsBinder;
- private IRcsFeatureListener mListenerBinder;
- private RcsPresenceExchangeImplBase mPresExchange;
- private RcsSipOptionsImplBase mSipOptions;
+ private RcsCapabilityExchangeImplBase mCapabilityExchangeImpl;
+ private ICapabilityExchangeEventListener mCapExchangeEventListener;
/**
* Create a new RcsFeature.
@@ -314,7 +350,7 @@ public class RcsFeature extends ImsFeature {
* @hide
*/
public boolean queryCapabilityConfiguration(
- @RcsImsCapabilities.RcsImsCapabilityFlag int capability,
+ @RcsUceAdapter.RcsImsCapabilityFlag int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
// Base Implementation - Override to provide functionality
return false;
@@ -342,37 +378,22 @@ public class RcsFeature extends ImsFeature {
}
/**
- * Retrieve the implementation of SIP OPTIONS for this {@link RcsFeature}.
- * <p>
- * Will only be requested by the framework if capability exchange via SIP OPTIONS is
- * configured as capable during a
- * {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}
- * operation and the RcsFeature sets the status of the capability to true using
- * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}.
+ * Retrieve the implementation of UCE for this {@link RcsFeature}, which can use either
+ * presence or OPTIONS for capability exchange.
*
- * @return An instance of {@link RcsSipOptionsImplBase} that implements SIP options exchange if
- * it is supported by the device.
- * @hide
- */
- public @NonNull RcsSipOptionsImplBase getOptionsExchangeImpl() {
- // Base Implementation, override to implement functionality
- return new RcsSipOptionsImplBase();
- }
-
- /**
- * Retrieve the implementation of UCE presence for this {@link RcsFeature}.
- * Will only be requested by the framework if presence exchang is configured as capable during
- * a {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}
+ * Will only be requested by the framework if capability exchange is configured
+ * as capable during a
+ * {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}
* operation and the RcsFeature sets the status of the capability to true using
* {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}.
*
- * @return An instance of {@link RcsPresenceExchangeImplBase} that implements presence
+ * @return An instance of {@link RcsCapabilityExchangeImplBase} that implements presence
* exchange if it is supported by the device.
* @hide
*/
- public @NonNull RcsPresenceExchangeImplBase getPresenceExchangeImpl() {
- // Base Implementation, override to implement functionality.
- return new RcsPresenceExchangeImplBase();
+ public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl() {
+ // Base Implementation, override to implement functionality
+ return new RcsCapabilityExchangeImplBase();
}
/**{@inheritDoc}*/
@@ -395,39 +416,20 @@ public class RcsFeature extends ImsFeature {
return mImsRcsBinder;
}
- /**@hide*/
- public IRcsFeatureListener getListener() {
- synchronized (mLock) {
- return mListenerBinder;
- }
- }
-
- private void setListener(IRcsFeatureListener listener) {
- synchronized (mLock) {
- mListenerBinder = listener;
- if (mListenerBinder != null) {
- onFeatureReady();
- }
- }
- }
-
- private RcsPresenceExchangeImplBase getPresenceExchangeInternal() {
- synchronized (mLock) {
- if (mPresExchange == null) {
- mPresExchange = getPresenceExchangeImpl();
- mPresExchange.initialize(this);
- }
- return mPresExchange;
+ private void setCapabilityExchangeEventListener(ICapabilityExchangeEventListener listener) {
+ mCapExchangeEventListener = listener;
+ if (mCapExchangeEventListener != null) {
+ onFeatureReady();
}
}
- private RcsSipOptionsImplBase getOptionsExchangeInternal() {
+ private RcsCapabilityExchangeImplBase getCapabilityExchangeImplBaseInternal() {
synchronized (mLock) {
- if (mSipOptions == null) {
- mSipOptions = getOptionsExchangeImpl();
- mSipOptions.initialize(this);
+ if (mCapabilityExchangeImpl == null) {
+ mCapabilityExchangeImpl = createCapabilityExchangeImpl();
+ mCapabilityExchangeImpl.setEventListener(mCapExchangeEventListener);
}
- return mSipOptions;
+ return mCapabilityExchangeImpl;
}
}
}
diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java
index fda295a27111..0b13efb7b4b4 100644
--- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java
+++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java
@@ -87,12 +87,8 @@ public class RcsCapabilityExchange {
/** @hide */
protected final IRcsFeatureListener getListener() throws ImsException {
- IRcsFeatureListener listener = mFeature.getListener();
- if (listener == null) {
- throw new ImsException("Connection to Framework has not been established, wait for "
- + "onFeatureReady().", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
- }
- return mFeature.getListener();
+ throw new ImsException("This method is deprecated.",
+ ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
}
/**
diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
new file mode 100644
index 000000000000..b5704bfb3569
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
@@ -0,0 +1,338 @@
+/*
+ * 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 android.telephony.ims.stub;
+
+import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.Uri;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.aidl.ICapabilityExchangeEventListener;
+import android.util.Log;
+import android.util.Pair;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+
+/**
+ * Base class for different types of Capability exchange.
+ * @hide
+ */
+public class RcsCapabilityExchangeImplBase {
+
+ private static final String LOG_TAG = "RcsCapExchangeImplBase";
+
+ /**
+ * Service is unknown.
+ */
+ public static final int COMMAND_CODE_SERVICE_UNKNOWN = 0;
+
+ /**
+ * The command failed with an unknown error.
+ */
+ public static final int COMMAND_CODE_GENERIC_FAILURE = 1;
+
+ /**
+ * Invalid parameter(s).
+ */
+ public static final int COMMAND_CODE_INVALID_PARAM = 2;
+
+ /**
+ * Fetch error.
+ */
+ public static final int COMMAND_CODE_FETCH_ERROR = 3;
+
+ /**
+ * Request timed out.
+ */
+ public static final int COMMAND_CODE_REQUEST_TIMEOUT = 4;
+
+ /**
+ * Failure due to insufficient memory available.
+ */
+ public static final int COMMAND_CODE_INSUFFICIENT_MEMORY = 5;
+
+ /**
+ * Network connection is lost.
+ * @hide
+ */
+ public static final int COMMAND_CODE_LOST_NETWORK_CONNECTION = 6;
+
+ /**
+ * Requested feature/resource is not supported.
+ * @hide
+ */
+ public static final int COMMAND_CODE_NOT_SUPPORTED = 7;
+
+ /**
+ * Contact or resource is not found.
+ */
+ public static final int COMMAND_CODE_NOT_FOUND = 8;
+
+ /**
+ * Service is not available.
+ */
+ public static final int COMMAND_CODE_SERVICE_UNAVAILABLE = 9;
+
+ /**
+ * Command resulted in no change in state, ignoring.
+ */
+ public static final int COMMAND_CODE_NO_CHANGE = 10;
+
+ /**@hide*/
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "COMMAND_CODE_", value = {
+ COMMAND_CODE_SERVICE_UNKNOWN,
+ COMMAND_CODE_GENERIC_FAILURE,
+ COMMAND_CODE_INVALID_PARAM,
+ COMMAND_CODE_FETCH_ERROR,
+ COMMAND_CODE_REQUEST_TIMEOUT,
+ COMMAND_CODE_INSUFFICIENT_MEMORY,
+ COMMAND_CODE_LOST_NETWORK_CONNECTION,
+ COMMAND_CODE_NOT_SUPPORTED,
+ COMMAND_CODE_NOT_FOUND,
+ COMMAND_CODE_SERVICE_UNAVAILABLE,
+ COMMAND_CODE_NO_CHANGE
+ })
+ public @interface CommandCode {}
+
+ /**
+ * Interface used by the framework to receive the response of the publish request.
+ */
+ public interface PublishResponseCallback {
+ /**
+ * Notify the framework that the command associated with this callback has failed.
+ *
+ * @param code The reason why the associated command has failed.
+ * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is
+ * not currently connected to the framework. This can happen if the {@link RcsFeature}
+ * is not {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received
+ * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases
+ * when the Telephony stack has crashed.
+ */
+ void onCommandError(@CommandCode int code) throws ImsException;
+
+
+ /**
+ * Provide the framework with a subsequent network response update to
+ * {@link #publishCapabilities(String, PublishResponseCallback)}.
+ *
+ * @param code The SIP response code sent from the network for the operation
+ * token specified.
+ * @param reason The optional reason response from the network. If the network
+ * provided no reason with the code, the string should be empty.
+ * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is
+ * not currently connected to the framework. This can happen if the {@link RcsFeature}
+ * is not {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received
+ * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases
+ * when the Telephony stack has crashed.
+ */
+ void onNetworkResponse(@IntRange(from = 100, to = 699) int code,
+ @NonNull String reason) throws ImsException;
+ }
+
+ /**
+ * Interface used by the framework to respond to OPTIONS requests.
+ */
+ public interface OptionsResponseCallback {
+ /**
+ * Notify the framework that the command associated with this callback has failed.
+ *
+ * @param code The reason why the associated command has failed.
+ * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is
+ * not currently connected to the framework. This can happen if the
+ * {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the {@link RcsFeature}
+ * has not received the {@link ImsFeature#onFeatureReady()} callback. This may also happen
+ * in rare cases when the Telephony stack has crashed.
+ */
+ void onCommandError(@CommandCode int code) throws ImsException;
+
+ /**
+ * Send the response of a SIP OPTIONS capability exchange to the framework.
+ * @param code The SIP response code that was sent by the network in response
+ * to the request sent by {@link #sendOptionsCapabilityRequest}.
+ * @param reason The optional SIP response reason sent by the network.
+ * If none was sent, this should be an empty string.
+ * @param theirCaps the contact's UCE capabilities associated with the
+ * capability request.
+ * @throws ImsException If this {@link RcsSipOptionsImplBase} instance is not
+ * currently connected to the framework. This can happen if the
+ * {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the
+ * {@link RcsFeature} has not received the
+ * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare
+ * cases when the Telephony stack has crashed.
+ */
+ void onNetworkResponse(int code, @NonNull String reason,
+ @Nullable List<String> theirCaps) throws ImsException;
+ }
+
+ /**
+ * Interface used by the framework to receive the response of the subscribe request.
+ */
+ public interface SubscribeResponseCallback {
+ /**
+ * Notify the framework that the command associated with this callback has failed.
+ *
+ * @param code The reason why the associated command has failed.
+ * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is
+ * not currently connected to the framework. This can happen if the
+ * {@link RcsFeature} is not
+ * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received
+ * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in
+ * rare cases when the Telephony stack has crashed.
+ */
+ void onCommandError(@CommandCode int code) throws ImsException;
+
+ /**
+ * Notify the framework of the response to the SUBSCRIBE request from
+ * {@link #subscribeForCapabilities(List<Uri>, SubscribeResponseCallback)}.
+ *
+ * @param code The SIP response code sent from the network for the operation
+ * token specified.
+ * @param reason The optional reason response from the network. If the network
+ * provided no reason with the code, the string should be empty.
+ * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is
+ * not currently connected to the framework. This can happen if the
+ * {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the
+ * {@link RcsFeature} has not received the {@link ImsFeature#onFeatureReady()} callback.
+ * This may also happen in rare cases when the Telephony stack has crashed.
+ */
+ void onNetworkResponse(@IntRange(from = 100, to = 699) int code,
+ @NonNull String reason) throws ImsException;
+
+ /**
+ * Provides the framework with latest XML PIDF documents included in the
+ * network response for the requested contacts' capabilities requested by the
+ * Framework using {@link #requestCapabilities(List, int)}. This should be
+ * called every time a new NOTIFY event is received with new capability
+ * information.
+ *
+ * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is
+ * not currently
+ * connected to the framework. This can happen if the {@link RcsFeature} is not
+ * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received
+ * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in
+ * rare cases when the
+ * Telephony stack has crashed.
+ */
+ void onNotifyCapabilitiesUpdate(@NonNull List<String> pidfXmls) throws ImsException;
+
+ /**
+ * A resource in the resource list for the presence subscribe event has been terminated.
+ * <p>
+ * This allows the framework to know that there will not be any capability information for
+ * a specific contact URI that they subscribed for.
+ */
+ void onResourceTerminated(
+ @NonNull List<Pair<Uri, String>> uriTerminatedReason) throws ImsException;
+
+ /**
+ * The subscription associated with a previous #requestCapabilities operation
+ * has been terminated. This will mostly be due to the subscription expiring,
+ * but may also happen due to an error.
+ * <p>
+ * This allows the framework to know that there will no longer be any
+ * capability updates for the requested operationToken.
+ */
+ void onTerminated(String reason, String retryAfter) throws ImsException;
+ }
+
+
+ private ICapabilityExchangeEventListener mListener;
+
+ /**
+ * Set the event listener to send the request to Framework.
+ */
+ public void setEventListener(ICapabilityExchangeEventListener listener) {
+ mListener = listener;
+ }
+
+ /**
+ * Get the event listener.
+ */
+ public ICapabilityExchangeEventListener getEventListener() {
+ return mListener;
+ }
+
+ /**
+ * The user capabilities of one or multiple contacts have been requested by the framework.
+ * <p>
+ * The response from the network to the SUBSCRIBE request must be sent back to the framework
+ * using {@link #onSubscribeNetworkResponse(int, String, int)}. As NOTIFY requests come in from
+ * the network, the requested contact’s capabilities should be sent back to the framework using
+ * {@link #onSubscribeNotifyRequest} and {@link onSubscribeResourceTerminated}
+ * should be called with the presence information for the contacts specified.
+ * <p>
+ * Once the subscription is terminated, {@link #onSubscriptionTerminated} must be called for
+ * the framework to finish listening for NOTIFY responses.
+ * @param uris A {@link List} of the {@link Uri}s that the framework is requesting the UCE
+ * capabilities for.
+ * @param cb The callback of the subscribe request.
+ */
+ public void subscribeForCapabilities(@NonNull List<Uri> uris,
+ @NonNull SubscribeResponseCallback cb) {
+ // Stub - to be implemented by service
+ Log.w(LOG_TAG, "subscribeForCapabilities called with no implementation.");
+ try {
+ cb.onCommandError(COMMAND_CODE_NOT_SUPPORTED);
+ } catch (ImsException e) {
+ // Do not do anything, this is a stub implementation.
+ }
+ }
+
+ /**
+ * The capabilities of this device have been updated and should be published to the network.
+ * <p>
+ * If this operation succeeds, network response updates should be sent to the framework using
+ * {@link #onNetworkResponse(int, String)}.
+ * @param pidfXml The XML PIDF document containing the capabilities of this device to be sent
+ * to the carrier’s presence server.
+ * @param cb The callback of the publish request
+ */
+ public void publishCapabilities(@NonNull String pidfXml, @NonNull PublishResponseCallback cb) {
+ // Stub - to be implemented by service
+ Log.w(LOG_TAG, "publishCapabilities called with no implementation.");
+ try {
+ cb.onCommandError(COMMAND_CODE_NOT_SUPPORTED);
+ } catch (ImsException e) {
+ // Do not do anything, this is a stub implementation.
+ }
+ }
+
+ /**
+ * Push one's own capabilities to a remote user via the SIP OPTIONS presence exchange mechanism
+ * in order to receive the capabilities of the remote user in response.
+ * <p>
+ * The implementer must call {@link #onNetworkResponse} to send the response of this
+ * query back to the framework.
+ * @param contactUri The URI of the remote user that we wish to get the capabilities of.
+ * @param myCapabilities The capabilities of this device to send to the remote user.
+ * @param callback The callback of this request which is sent from the remote user.
+ */
+ public void sendOptionsCapabilityRequest(@NonNull Uri contactUri,
+ @NonNull List<String> myCapabilities, @NonNull OptionsResponseCallback callback) {
+ // Stub - to be implemented by service
+ Log.w(LOG_TAG, "sendOptionsCapabilityRequest called with no implementation.");
+ try {
+ callback.onCommandError(COMMAND_CODE_NOT_SUPPORTED);
+ } catch (ImsException e) {
+ // Do not do anything, this is a stub implementation.
+ }
+ }
+}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index b1700a10a288..d3c27dc4f255 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -30,77 +30,96 @@ public interface RILConstants {
// from RIL_Errno
int SUCCESS = 0;
- int RADIO_NOT_AVAILABLE = 1; /* If radio did not start or is resetting */
+ int RADIO_NOT_AVAILABLE = 1; /* If radio did not start or is resetting */
int GENERIC_FAILURE = 2;
- int PASSWORD_INCORRECT = 3; /* for PIN/PIN2 methods only! */
- int SIM_PIN2 = 4; /* Operation requires SIM PIN2 to be entered */
- int SIM_PUK2 = 5; /* Operation requires SIM PIN2 to be entered */
+ int PASSWORD_INCORRECT = 3; /* for PIN/PIN2 methods only! */
+ int SIM_PIN2 = 4; /* Operation requires SIM PIN2 to be entered */
+ int SIM_PUK2 = 5; /* Operation requires SIM PIN2 to be entered */
int REQUEST_NOT_SUPPORTED = 6;
int REQUEST_CANCELLED = 7;
- int OP_NOT_ALLOWED_DURING_VOICE_CALL = 8; /* data operation is not allowed during voice call in
- class C */
- int OP_NOT_ALLOWED_BEFORE_REG_NW = 9; /* request is not allowed before device registers to
- network */
- int SMS_SEND_FAIL_RETRY = 10; /* send sms fail and need retry */
- int SIM_ABSENT = 11; /* ICC card is absent */
- int SUBSCRIPTION_NOT_AVAILABLE = 12; /* fail to find CDMA subscription from specified
- location */
- int MODE_NOT_SUPPORTED = 13; /* HW does not support preferred network type */
- int FDN_CHECK_FAILURE = 14; /* send operation barred error when FDN is enabled */
- int ILLEGAL_SIM_OR_ME = 15; /* network selection failure due
- to wrong SIM/ME and no
- retries needed */
- int MISSING_RESOURCE = 16; /* no logical channel available */
- int NO_SUCH_ELEMENT = 17; /* application not found on SIM */
- int DIAL_MODIFIED_TO_USSD = 18; /* DIAL request modified to USSD */
- int DIAL_MODIFIED_TO_SS = 19; /* DIAL request modified to SS */
- int DIAL_MODIFIED_TO_DIAL = 20; /* DIAL request modified to DIAL with different data*/
- int USSD_MODIFIED_TO_DIAL = 21; /* USSD request modified to DIAL */
- int USSD_MODIFIED_TO_SS = 22; /* USSD request modified to SS */
- int USSD_MODIFIED_TO_USSD = 23; /* USSD request modified to different USSD request */
- int SS_MODIFIED_TO_DIAL = 24; /* SS request modified to DIAL */
- int SS_MODIFIED_TO_USSD = 25; /* SS request modified to USSD */
- int SUBSCRIPTION_NOT_SUPPORTED = 26; /* Subscription not supported */
- int SS_MODIFIED_TO_SS = 27; /* SS request modified to different SS request */
- int SIM_ALREADY_POWERED_OFF = 29; /* SAP: 0x03, Error card aleready powered off */
- int SIM_ALREADY_POWERED_ON = 30; /* SAP: 0x05, Error card already powered on */
- int SIM_DATA_NOT_AVAILABLE = 31; /* SAP: 0x06, Error data not available */
+ int OP_NOT_ALLOWED_DURING_VOICE_CALL = 8; /* data operation is not allowed during voice
+ call in class C */
+ int OP_NOT_ALLOWED_BEFORE_REG_NW = 9; /* request is not allowed before device
+ registers to network */
+ int SMS_SEND_FAIL_RETRY = 10; /* send sms fail and need retry */
+ int SIM_ABSENT = 11; /* ICC card is absent */
+ int SUBSCRIPTION_NOT_AVAILABLE = 12; /* fail to find CDMA subscription from specified
+ location */
+ int MODE_NOT_SUPPORTED = 13; /* HW does not support preferred network type */
+ int FDN_CHECK_FAILURE = 14; /* send operation barred error when FDN is
+ enabled */
+ int ILLEGAL_SIM_OR_ME = 15; /* network selection failure due to wrong
+ SIM/ME and no retries needed */
+ int MISSING_RESOURCE = 16; /* no logical channel available */
+ int NO_SUCH_ELEMENT = 17; /* application not found on SIM */
+ int DIAL_MODIFIED_TO_USSD = 18; /* DIAL request modified to USSD */
+ int DIAL_MODIFIED_TO_SS = 19; /* DIAL request modified to SS */
+ int DIAL_MODIFIED_TO_DIAL = 20; /* DIAL request modified to DIAL with
+ different data*/
+ int USSD_MODIFIED_TO_DIAL = 21; /* USSD request modified to DIAL */
+ int USSD_MODIFIED_TO_SS = 22; /* USSD request modified to SS */
+ int USSD_MODIFIED_TO_USSD = 23; /* USSD request modified to different USSD
+ request */
+ int SS_MODIFIED_TO_DIAL = 24; /* SS request modified to DIAL */
+ int SS_MODIFIED_TO_USSD = 25; /* SS request modified to USSD */
+ int SUBSCRIPTION_NOT_SUPPORTED = 26; /* Subscription not supported */
+ int SS_MODIFIED_TO_SS = 27; /* SS request modified to different SS
+ request */
+ int SIM_ALREADY_POWERED_OFF = 29; /* SAP: 0x03, Error card aleready powered off */
+ int SIM_ALREADY_POWERED_ON = 30; /* SAP: 0x05, Error card already powered on */
+ int SIM_DATA_NOT_AVAILABLE = 31; /* SAP: 0x06, Error data not available */
int SIM_SAP_CONNECT_FAILURE = 32;
int SIM_SAP_MSG_SIZE_TOO_LARGE = 33;
int SIM_SAP_MSG_SIZE_TOO_SMALL = 34;
int SIM_SAP_CONNECT_OK_CALL_ONGOING = 35;
- int LCE_NOT_SUPPORTED = 36; /* Link Capacity Estimation (LCE) not supported */
- int NO_MEMORY = 37; /* Not sufficient memory to process the request */
- int INTERNAL_ERR = 38; /* Hit unexpected vendor internal error scenario */
- int SYSTEM_ERR = 39; /* Hit platform or system error */
- int MODEM_ERR = 40; /* Hit unexpected modem error */
- int INVALID_STATE = 41; /* Unexpected request for the current state */
- int NO_RESOURCES = 42; /* Not sufficient resource to process the request */
- int SIM_ERR = 43; /* Received error from SIM card */
- int INVALID_ARGUMENTS = 44; /* Received invalid arguments in request */
- int INVALID_SIM_STATE = 45; /* Can not process the request in current SIM state */
- int INVALID_MODEM_STATE = 46; /* Can not process the request in current Modem state */
- int INVALID_CALL_ID = 47; /* Received invalid call id in request */
- int NO_SMS_TO_ACK = 48; /* ACK received when there is no SMS to ack */
- int NETWORK_ERR = 49; /* Received error from network */
- int REQUEST_RATE_LIMITED = 50; /* Operation denied due to overly-frequent requests */
- int SIM_BUSY = 51; /* SIM is busy */
- int SIM_FULL = 52; /* The target EF is full */
- int NETWORK_REJECT = 53; /* Request is rejected by network */
- int OPERATION_NOT_ALLOWED = 54; /* Not allowed the request now */
- int EMPTY_RECORD = 55; /* The request record is empty */
- int INVALID_SMS_FORMAT = 56; /* Invalid sms format */
- int ENCODING_ERR = 57; /* Message not encoded properly */
- int INVALID_SMSC_ADDRESS = 58; /* SMSC address specified is invalid */
- int NO_SUCH_ENTRY = 59; /* No such entry present to perform the request */
- int NETWORK_NOT_READY = 60; /* Network is not ready to perform the request */
- int NOT_PROVISIONED = 61; /* Device doesnot have this value provisioned */
- int NO_SUBSCRIPTION = 62; /* Device doesnot have subscription */
- int NO_NETWORK_FOUND = 63; /* Network cannot be found */
- int DEVICE_IN_USE = 64; /* Operation cannot be performed because the device
- is currently in use */
- int ABORTED = 65; /* Operation aborted */
- int INVALID_RESPONSE = 66; /* Invalid response sent by vendor code */
+ int LCE_NOT_SUPPORTED = 36; /* Link Capacity Estimation (LCE) not
+ supported */
+ int NO_MEMORY = 37; /* Not sufficient memory to process the
+ request */
+ int INTERNAL_ERR = 38; /* Hit unexpected vendor internal error
+ scenario */
+ int SYSTEM_ERR = 39; /* Hit platform or system error */
+ int MODEM_ERR = 40; /* Hit unexpected modem error */
+ int INVALID_STATE = 41; /* Unexpected request for the current state */
+ int NO_RESOURCES = 42; /* Not sufficient resource to process the
+ request */
+ int SIM_ERR = 43; /* Received error from SIM card */
+ int INVALID_ARGUMENTS = 44; /* Received invalid arguments in request */
+ int INVALID_SIM_STATE = 45; /* Can not process the request in current SIM
+ state */
+ int INVALID_MODEM_STATE = 46; /* Can not process the request in current Modem
+ state */
+ int INVALID_CALL_ID = 47; /* Received invalid call id in request */
+ int NO_SMS_TO_ACK = 48; /* ACK received when there is no SMS to ack */
+ int NETWORK_ERR = 49; /* Received error from network */
+ int REQUEST_RATE_LIMITED = 50; /* Operation denied due to overly-frequent
+ requests */
+ int SIM_BUSY = 51; /* SIM is busy */
+ int SIM_FULL = 52; /* The target EF is full */
+ int NETWORK_REJECT = 53; /* Request is rejected by network */
+ int OPERATION_NOT_ALLOWED = 54; /* Not allowed the request now */
+ int EMPTY_RECORD = 55; /* The request record is empty */
+ int INVALID_SMS_FORMAT = 56; /* Invalid sms format */
+ int ENCODING_ERR = 57; /* Message not encoded properly */
+ int INVALID_SMSC_ADDRESS = 58; /* SMSC address specified is invalid */
+ int NO_SUCH_ENTRY = 59; /* No such entry present to perform the
+ request */
+ int NETWORK_NOT_READY = 60; /* Network is not ready to perform the
+ request */
+ int NOT_PROVISIONED = 61; /* Device doesnot have this value
+ provisioned */
+ int NO_SUBSCRIPTION = 62; /* Device doesnot have subscription */
+ int NO_NETWORK_FOUND = 63; /* Network cannot be found */
+ int DEVICE_IN_USE = 64; /* Operation cannot be performed because the
+ device is currently in use */
+ int ABORTED = 65; /* Operation aborted */
+ int INVALID_RESPONSE = 66; /* Invalid response sent by vendor code */
+ int SIMULTANEOUS_SMS_AND_CALL_NOT_ALLOWED = 67; /* 1X voice and SMS are not allowed
+ simulteneously */
+ int ACCESS_BARRED = 68; /* SMS access is barred */
+ int BLOCKED_DUE_TO_CALL = 69; /* SMS is blocked due to call control */
+ int RF_HARDWARE_ISSUE = 70; /* RF HW issue is detected */
+ int NO_RF_CALIBRATION_INFO = 71; /* No RF calibration in device */
// Below is list of OEM specific error codes which can by used by OEMs in case they don't want to
// reveal particular replacement for Generic failure
diff --git a/tests/RollbackTest/NetworkStagedRollbackTest/src/com/android/tests/rollback/host/NetworkStagedRollbackTest.java b/tests/RollbackTest/NetworkStagedRollbackTest/src/com/android/tests/rollback/host/NetworkStagedRollbackTest.java
index b7d72dbe22ae..c769a6f8c018 100644
--- a/tests/RollbackTest/NetworkStagedRollbackTest/src/com/android/tests/rollback/host/NetworkStagedRollbackTest.java
+++ b/tests/RollbackTest/NetworkStagedRollbackTest/src/com/android/tests/rollback/host/NetworkStagedRollbackTest.java
@@ -16,8 +16,6 @@
package com.android.tests.rollback.host;
-import static com.android.tests.rollback.host.WatchdogEventLogger.watchdogEventOccurred;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -31,7 +29,6 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.List;
import java.util.concurrent.TimeUnit;
/**
@@ -98,12 +95,11 @@ public class NetworkStagedRollbackTest extends BaseHostJUnit4Test {
// Verify rollback was executed after health check deadline
runPhase("testNetworkFailedRollback_Phase3");
- List<String> watchdogEvents = mLogger.getWatchdogLoggingEvents();
- assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_INITIATE, null,
+ assertTrue(mLogger.watchdogEventOccurred(ROLLBACK_INITIATE, null,
REASON_EXPLICIT_HEALTH_CHECK, null));
- assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_BOOT_TRIGGERED, null,
+ assertTrue(mLogger.watchdogEventOccurred(ROLLBACK_BOOT_TRIGGERED, null,
null, null));
- assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_SUCCESS, null, null, null));
+ assertTrue(mLogger.watchdogEventOccurred(ROLLBACK_SUCCESS, null, null, null));
} finally {
// Reconnect internet again so we won't break tests which assume internet available
getDevice().executeShellCommand("svc wifi enable");
@@ -134,8 +130,7 @@ public class NetworkStagedRollbackTest extends BaseHostJUnit4Test {
// Verify rollback was not executed after health check deadline
runPhase("testNetworkPassedDoesNotRollback_Phase3");
- List<String> watchdogEvents = mLogger.getWatchdogLoggingEvents();
- assertEquals(watchdogEventOccurred(watchdogEvents, null, null,
+ assertEquals(mLogger.watchdogEventOccurred(null, null,
REASON_EXPLICIT_HEALTH_CHECK, null), false);
}
}
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 725bfa95166a..2ebb9c13a016 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
@@ -16,8 +16,6 @@
package com.android.tests.rollback.host;
-import static com.android.tests.rollback.host.WatchdogEventLogger.watchdogEventOccurred;
-
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
@@ -158,12 +156,11 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
runPhase("testBadApkOnly_Phase4");
- List<String> watchdogEvents = mLogger.getWatchdogLoggingEvents();
- assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_INITIATE, null,
+ assertTrue(mLogger.watchdogEventOccurred(ROLLBACK_INITIATE, null,
REASON_APP_CRASH, TESTAPP_A));
- assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_BOOT_TRIGGERED, null,
+ assertTrue(mLogger.watchdogEventOccurred(ROLLBACK_BOOT_TRIGGERED, null,
null, null));
- assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_SUCCESS, null, null, null));
+ assertTrue(mLogger.watchdogEventOccurred(ROLLBACK_SUCCESS, null, null, null));
}
@Test
@@ -192,12 +189,11 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
// verify rollback committed
runPhase("testNativeWatchdogTriggersRollback_Phase3");
- List<String> watchdogEvents = mLogger.getWatchdogLoggingEvents();
- assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_INITIATE, null,
+ assertTrue(mLogger.watchdogEventOccurred(ROLLBACK_INITIATE, null,
REASON_NATIVE_CRASH, null));
- assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_BOOT_TRIGGERED, null,
+ assertTrue(mLogger.watchdogEventOccurred(ROLLBACK_BOOT_TRIGGERED, null,
null, null));
- assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_SUCCESS, null, null, null));
+ assertTrue(mLogger.watchdogEventOccurred(ROLLBACK_SUCCESS, null, null, null));
}
@Test
@@ -233,12 +229,11 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
// verify all available rollbacks have been committed
runPhase("testNativeWatchdogTriggersRollbackForAll_Phase4");
- List<String> watchdogEvents = mLogger.getWatchdogLoggingEvents();
- assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_INITIATE, null,
+ assertTrue(mLogger.watchdogEventOccurred(ROLLBACK_INITIATE, null,
REASON_NATIVE_CRASH, null));
- assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_BOOT_TRIGGERED, null,
+ assertTrue(mLogger.watchdogEventOccurred(ROLLBACK_BOOT_TRIGGERED, null,
null, null));
- assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_SUCCESS, null, null, null));
+ assertTrue(mLogger.watchdogEventOccurred(ROLLBACK_SUCCESS, null, null, null));
}
/**
@@ -316,12 +311,11 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
// Verify rollback occurred due to crash of apk-in-apex
runPhase("testRollbackApexWithApkCrashing_Phase3");
- List<String> watchdogEvents = mLogger.getWatchdogLoggingEvents();
- assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_INITIATE, null,
+ assertTrue(mLogger.watchdogEventOccurred(ROLLBACK_INITIATE, null,
REASON_APP_CRASH, TESTAPP_A));
- assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_BOOT_TRIGGERED, null,
+ assertTrue(mLogger.watchdogEventOccurred(ROLLBACK_BOOT_TRIGGERED, null,
null, null));
- assertTrue(watchdogEventOccurred(watchdogEvents, ROLLBACK_SUCCESS, null, null, null));
+ assertTrue(mLogger.watchdogEventOccurred(ROLLBACK_SUCCESS, null, null, null));
}
/**
diff --git a/tests/RollbackTest/lib/src/com/android/tests/rollback/host/WatchdogEventLogger.java b/tests/RollbackTest/lib/src/com/android/tests/rollback/host/WatchdogEventLogger.java
index 88731504eafe..6b0d1f860956 100644
--- a/tests/RollbackTest/lib/src/com/android/tests/rollback/host/WatchdogEventLogger.java
+++ b/tests/RollbackTest/lib/src/com/android/tests/rollback/host/WatchdogEventLogger.java
@@ -17,52 +17,50 @@
package com.android.tests.rollback.host;
import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.device.LogcatReceiver;
-import com.android.tradefed.result.InputStreamSource;
-import java.io.BufferedReader;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.List;
+import static com.google.common.truth.Truth.assertThat;
public class WatchdogEventLogger {
- private LogcatReceiver mReceiver;
+ private static final String[] ROLLBACK_EVENT_TYPES = {
+ "ROLLBACK_INITIATE", "ROLLBACK_BOOT_TRIGGERED", "ROLLBACK_SUCCESS"};
+ private static final String[] ROLLBACK_EVENT_ATTRS = {
+ "logPackage", "rollbackReason", "failedPackageName"};
+ private static final String PROP_PREFIX = "persist.sys.rollbacktest.";
- public void start(ITestDevice device) {
- mReceiver = new LogcatReceiver(device, "logcat -s WatchdogRollbackLogger",
- device.getOptions().getMaxLogcatDataSize(), 0);
- mReceiver.start();
- }
+ private ITestDevice mDevice;
- public void stop() {
- if (mReceiver != null) {
- mReceiver.stop();
- mReceiver.clear();
+ private void resetProperties(boolean enabled) throws Exception {
+ try {
+ mDevice.enableAdbRoot();
+ assertThat(mDevice.setProperty(
+ PROP_PREFIX + "enabled", String.valueOf(enabled))).isTrue();
+ for (String type : ROLLBACK_EVENT_TYPES) {
+ String key = PROP_PREFIX + type;
+ assertThat(mDevice.setProperty(key, "")).isTrue();
+ for (String attr : ROLLBACK_EVENT_ATTRS) {
+ assertThat(mDevice.setProperty(key + "." + attr, "")).isTrue();
+ }
+ }
+ } finally {
+ mDevice.disableAdbRoot();
}
}
- /**
- * Returns a list of all Watchdog logging events which have occurred.
- */
- public List<String> getWatchdogLoggingEvents() throws Exception {
- try (InputStreamSource logcatStream = mReceiver.getLogcatData()) {
- return getWatchdogLoggingEvents(logcatStream);
- }
+ public void start(ITestDevice device) throws Exception {
+ mDevice = device;
+ resetProperties(true);
}
- private static List<String> getWatchdogLoggingEvents(InputStreamSource inputStreamSource)
- throws Exception {
- List<String> watchdogEvents = new ArrayList<>();
- InputStream inputStream = inputStreamSource.createInputStream();
- BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
- String line;
- while ((line = reader.readLine()) != null) {
- if (line.contains("Watchdog event occurred")) {
- watchdogEvents.add(line);
- }
+ public void stop() throws Exception {
+ if (mDevice != null) {
+ resetProperties(false);
}
- return watchdogEvents;
+ }
+
+ private boolean matchProperty(String type, String attr, String expectedVal) throws Exception {
+ String key = PROP_PREFIX + type + "." + attr;
+ String val = mDevice.getProperty(key);
+ return expectedVal == null || expectedVal.equals(val);
}
/**
@@ -71,33 +69,11 @@ public class WatchdogEventLogger {
* Check the value of all non-null parameters against the list of Watchdog events that have
* occurred, and return {@code true} if an event exists which matches all criteria.
*/
- public static boolean watchdogEventOccurred(List<String> loggingEvents,
- String type, String logPackage,
+ public boolean watchdogEventOccurred(String type, String logPackage,
String rollbackReason, String failedPackageName) throws Exception {
- List<String> eventCriteria = new ArrayList<>();
- if (type != null) {
- eventCriteria.add("type: " + type);
- }
- if (logPackage != null) {
- eventCriteria.add("logPackage: " + logPackage);
- }
- if (rollbackReason != null) {
- eventCriteria.add("rollbackReason: " + rollbackReason);
- }
- if (failedPackageName != null) {
- eventCriteria.add("failedPackageName: " + failedPackageName);
- }
- for (String loggingEvent: loggingEvents) {
- boolean matchesCriteria = true;
- for (String criterion: eventCriteria) {
- if (!loggingEvent.contains(criterion)) {
- matchesCriteria = false;
- }
- }
- if (matchesCriteria) {
- return true;
- }
- }
- return false;
+ return mDevice.getBooleanProperty(PROP_PREFIX + type, false)
+ && matchProperty(type, "logPackage", logPackage)
+ && matchProperty(type, "rollbackReason", rollbackReason)
+ && matchProperty(type, "failedPackageName", failedPackageName);
}
}
diff --git a/tests/vcn/Android.bp b/tests/vcn/Android.bp
new file mode 100644
index 000000000000..f967bf0d8f6b
--- /dev/null
+++ b/tests/vcn/Android.bp
@@ -0,0 +1,27 @@
+//########################################################################
+// Build FrameworksVcnTests package
+//########################################################################
+
+android_test {
+ name: "FrameworksVcnTests",
+ srcs: [
+ "java/**/*.java",
+ "java/**/*.kt",
+ ],
+ platform_apis: true,
+ test_suites: ["device-tests"],
+ certificate: "platform",
+ static_libs: [
+ "androidx.test.rules",
+ "frameworks-base-testutils",
+ "framework-protos",
+ "mockito-target-minus-junit4",
+ "platform-test-annotations",
+ "services.core",
+ ],
+ libs: [
+ "android.test.runner",
+ "android.test.base",
+ "android.test.mock",
+ ],
+}
diff --git a/tests/vcn/AndroidManifest.xml b/tests/vcn/AndroidManifest.xml
new file mode 100644
index 000000000000..2ad9aac67029
--- /dev/null
+++ b/tests/vcn/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.tests.vcn">
+
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.frameworks.tests.vcn"
+ android:label="Frameworks VCN Tests" />
+</manifest>
diff --git a/tests/vcn/AndroidTest.xml b/tests/vcn/AndroidTest.xml
new file mode 100644
index 000000000000..dc521fd7bcd9
--- /dev/null
+++ b/tests/vcn/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs VCN Tests.">
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="FrameworksVcnTests.apk" />
+ </target_preparer>
+
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-tag" value="FrameworksVcnTests" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.frameworks.tests.vcn" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/tests/vcn/TEST_MAPPING b/tests/vcn/TEST_MAPPING
new file mode 100644
index 000000000000..54fa411e3570
--- /dev/null
+++ b/tests/vcn/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "FrameworksVcnTests"
+ }
+ ]
+} \ No newline at end of file
diff --git a/wifi/aidl-export/android/net/wifi/aware/AwareResources.aidl b/wifi/aidl-export/android/net/wifi/aware/AwareResources.aidl
new file mode 100644
index 000000000000..d0bd2dda5722
--- /dev/null
+++ b/wifi/aidl-export/android/net/wifi/aware/AwareResources.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.net.wifi.aware;
+
+parcelable AwareResources; \ No newline at end of file
diff --git a/wifi/api/current.txt b/wifi/api/current.txt
index 0bc1ff22b704..d5ef703253cb 100644
--- a/wifi/api/current.txt
+++ b/wifi/api/current.txt
@@ -561,6 +561,15 @@ package android.net.wifi.aware {
method public void onAttached(android.net.wifi.aware.WifiAwareSession);
}
+ public final class AwareResources implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getNumOfAvailableDataPaths();
+ method public int getNumOfAvailablePublishSessions();
+ method public int getNumOfAvailableSubscribeSessions();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.aware.AwareResources> CREATOR;
+ }
+
public final class Characteristics implements android.os.Parcelable {
method public int describeContents();
method public int getMaxMatchFilterLength();
@@ -663,7 +672,8 @@ package android.net.wifi.aware {
public class WifiAwareManager {
method public void attach(@NonNull android.net.wifi.aware.AttachCallback, @Nullable android.os.Handler);
method public void attach(@NonNull android.net.wifi.aware.AttachCallback, @NonNull android.net.wifi.aware.IdentityChangedListener, @Nullable android.os.Handler);
- method public android.net.wifi.aware.Characteristics getCharacteristics();
+ method @Nullable public android.net.wifi.aware.AwareResources getAvailableAwareResources();
+ method @Nullable public android.net.wifi.aware.Characteristics getCharacteristics();
method public boolean isAvailable();
method public boolean isDeviceAttached();
method public boolean isInstantCommunicationModeEnabled();
diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt
index fa99da786ae5..edbd46300191 100644
--- a/wifi/api/system-current.txt
+++ b/wifi/api/system-current.txt
@@ -428,8 +428,11 @@ package android.net.wifi {
method public double getSuccessfulRxPacketsPerSecond();
method public double getSuccessfulTxPacketsPerSecond();
method public boolean isEphemeral();
+ method public boolean isOemPaid();
+ method public boolean isOemPrivate();
method public boolean isOsuAp();
method public boolean isPasspointAp();
+ method public boolean isTrusted();
method @Nullable public static String sanitizeSsid(@Nullable String);
field public static final String DEFAULT_MAC_ADDRESS = "02:00:00:00:00:00";
field public static final int INVALID_RSSI = -127; // 0xffffff81
@@ -618,11 +621,13 @@ package android.net.wifi {
public final class WifiNetworkSuggestion implements android.os.Parcelable {
method @NonNull public android.net.wifi.WifiConfiguration getWifiConfiguration();
method public boolean isOemPaid();
+ method public boolean isOemPrivate();
}
public static final class WifiNetworkSuggestion.Builder {
method @NonNull @RequiresPermission(android.Manifest.permission.NETWORK_CARRIER_PROVISIONING) public android.net.wifi.WifiNetworkSuggestion.Builder setCarrierId(int);
method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setOemPaid(boolean);
+ method @NonNull public android.net.wifi.WifiNetworkSuggestion.Builder setOemPrivate(boolean);
}
public class WifiScanner {
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 9ca64d2ae2ef..9298c1ea7836 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -1011,6 +1011,17 @@ public class WifiConfiguration implements Parcelable {
*/
public boolean oemPaid;
+
+ /**
+ * Indicate whether the network is oem private or not. Networks are considered oem private
+ * if the corresponding connection is only available to system apps.
+ *
+ * This bit can only be used by suggestion network, see
+ * {@link WifiNetworkSuggestion.Builder#setOemPrivate(boolean)}
+ * @hide
+ */
+ public boolean oemPrivate;
+
/**
* True if this Wifi configuration is created from a {@link WifiNetworkSuggestion},
* false otherwise.
@@ -1349,36 +1360,26 @@ public class WifiConfiguration implements Parcelable {
* @hide
*/
public static final int NETWORK_SELECTION_DISABLED_STARTING_INDEX = 1;
- /**
- * The starting index for network selection temporarily disabled reasons.
- * @hide
- */
- public static final int TEMPORARILY_DISABLED_STARTING_INDEX = 1;
- /** This network is disabled because of multiple association rejections. */
+ /** This network is temporarily disabled because of multiple association rejections. */
public static final int DISABLED_ASSOCIATION_REJECTION = 1;
- /** This network is disabled because of multiple authentication failure. */
+ /** This network is temporarily disabled because of multiple authentication failure. */
public static final int DISABLED_AUTHENTICATION_FAILURE = 2;
- /** This network is disabled because of multiple DHCP failure. */
+ /** This network is temporarily disabled because of multiple DHCP failure. */
public static final int DISABLED_DHCP_FAILURE = 3;
/** This network is temporarily disabled because it has no Internet access. */
public static final int DISABLED_NO_INTERNET_TEMPORARY = 4;
- /**
- * The starting index for network selection permanently disabled reasons.
- * @hide
- */
- public static final int PERMANENTLY_DISABLED_STARTING_INDEX = 5;
- /** This network is disabled due to absence of user credentials */
+ /** This network is permanently disabled due to absence of user credentials */
public static final int DISABLED_AUTHENTICATION_NO_CREDENTIALS = 5;
/**
* This network is permanently disabled because it has no Internet access and the user does
* not want to stay connected.
*/
public static final int DISABLED_NO_INTERNET_PERMANENT = 6;
- /** This network is disabled due to WifiManager disabling it explicitly. */
+ /** This network is permanently disabled due to WifiManager disabling it explicitly. */
public static final int DISABLED_BY_WIFI_MANAGER = 7;
- /** This network is disabled due to wrong password. */
+ /** This network is permanently disabled due to wrong password. */
public static final int DISABLED_BY_WRONG_PASSWORD = 8;
- /** This network is disabled because service is not subscribed. */
+ /** This network is permanently disabled because service is not subscribed. */
public static final int DISABLED_AUTHENTICATION_NO_SUBSCRIPTION = 9;
/**
* All other disable reasons should be strictly less than this value.
@@ -1428,6 +1429,8 @@ public class WifiConfiguration implements Parcelable {
/**
* Network Selection disable timeout for the error. After the timeout milliseconds,
* enable the network again.
+ * If this is set to Integer.MAX_VALUE, the network will be permanently disabled until
+ * the next time the user manually connects to it.
*/
public final int mDisableTimeoutMillis;
@@ -2249,6 +2252,7 @@ public class WifiConfiguration implements Parcelable {
osu = false;
trusted = true; // Networks are considered trusted by default.
oemPaid = false;
+ oemPrivate = false;
fromWifiNetworkSuggestion = false;
fromWifiNetworkSpecifier = false;
meteredHint = false;
@@ -2372,13 +2376,14 @@ public class WifiConfiguration implements Parcelable {
if (this.osu) sbuf.append(" osu");
if (this.trusted) sbuf.append(" trusted");
if (this.oemPaid) sbuf.append(" oemPaid");
+ if (this.oemPrivate) sbuf.append(" oemPrivate");
if (this.fromWifiNetworkSuggestion) sbuf.append(" fromWifiNetworkSuggestion");
if (this.fromWifiNetworkSpecifier) sbuf.append(" fromWifiNetworkSpecifier");
if (this.meteredHint) sbuf.append(" meteredHint");
if (this.useExternalScores) sbuf.append(" useExternalScores");
if (this.validatedInternetAccess || this.ephemeral || this.trusted || this.oemPaid
- || this.fromWifiNetworkSuggestion || this.fromWifiNetworkSpecifier
- || this.meteredHint || this.useExternalScores) {
+ || this.oemPrivate || this.fromWifiNetworkSuggestion
+ || this.fromWifiNetworkSpecifier || this.meteredHint || this.useExternalScores) {
sbuf.append("\n");
}
if (this.meteredOverride != METERED_OVERRIDE_NONE) {
@@ -2943,6 +2948,7 @@ public class WifiConfiguration implements Parcelable {
osu = source.osu;
trusted = source.trusted;
oemPaid = source.oemPaid;
+ oemPrivate = source.oemPrivate;
fromWifiNetworkSuggestion = source.fromWifiNetworkSuggestion;
fromWifiNetworkSpecifier = source.fromWifiNetworkSpecifier;
meteredHint = source.meteredHint;
@@ -3024,6 +3030,7 @@ public class WifiConfiguration implements Parcelable {
dest.writeInt(ephemeral ? 1 : 0);
dest.writeInt(trusted ? 1 : 0);
dest.writeInt(oemPaid ? 1 : 0);
+ dest.writeInt(oemPrivate ? 1 : 0);
dest.writeInt(fromWifiNetworkSuggestion ? 1 : 0);
dest.writeInt(fromWifiNetworkSpecifier ? 1 : 0);
dest.writeInt(meteredHint ? 1 : 0);
@@ -3102,6 +3109,7 @@ public class WifiConfiguration implements Parcelable {
config.ephemeral = in.readInt() != 0;
config.trusted = in.readInt() != 0;
config.oemPaid = in.readInt() != 0;
+ config.oemPrivate = in.readInt() != 0;
config.fromWifiNetworkSuggestion = in.readInt() != 0;
config.fromWifiNetworkSpecifier = in.readInt() != 0;
config.meteredHint = in.readInt() != 0;
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index fe5002eb8854..774c043136e7 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -164,6 +164,11 @@ public class WifiInfo implements Parcelable {
private boolean mOemPaid;
/**
+ * Whether the network is oem private or not.
+ */
+ private boolean mOemPrivate;
+
+ /**
* OSU (Online Sign Up) AP for Passpoint R2.
*/
private boolean mOsuAp;
@@ -327,6 +332,9 @@ public class WifiInfo implements Parcelable {
setFrequency(-1);
setMeteredHint(false);
setEphemeral(false);
+ setTrusted(false);
+ setOemPaid(false);
+ setOemPrivate(false);
setOsuAp(false);
setRequestingPackageName(null);
setFQDN(null);
@@ -363,7 +371,8 @@ public class WifiInfo implements Parcelable {
mMeteredHint = source.mMeteredHint;
mEphemeral = source.mEphemeral;
mTrusted = source.mTrusted;
- mTrusted = source.mOemPaid;
+ mOemPaid = source.mOemPaid;
+ mOemPrivate = source.mOemPrivate;
mRequestingPackageName =
source.mRequestingPackageName;
mOsuAp = source.mOsuAp;
@@ -722,7 +731,12 @@ public class WifiInfo implements Parcelable {
mTrusted = trusted;
}
- /** {@hide} */
+ /**
+ * Returns true if the current Wifi network is a trusted network, false otherwise.
+ * @see WifiNetworkSuggestion.Builder#setUntrusted(boolean).
+ * {@hide}
+ */
+ @SystemApi
public boolean isTrusted() {
return mTrusted;
}
@@ -732,12 +746,32 @@ public class WifiInfo implements Parcelable {
mOemPaid = oemPaid;
}
- /** {@hide} */
+ /**
+ * Returns true if the current Wifi network is an oem paid network, false otherwise.
+ * @see WifiNetworkSuggestion.Builder#setOemPaid(boolean).
+ * {@hide}
+ */
+ @SystemApi
public boolean isOemPaid() {
return mOemPaid;
}
/** {@hide} */
+ public void setOemPrivate(boolean oemPrivate) {
+ mOemPrivate = oemPrivate;
+ }
+
+ /**
+ * Returns true if the current Wifi network is an oem private network, false otherwise.
+ * @see WifiNetworkSuggestion.Builder#setOemPrivate(boolean).
+ * {@hide}
+ */
+ @SystemApi
+ public boolean isOemPrivate() {
+ return mOemPrivate;
+ }
+
+ /** {@hide} */
public void setOsuAp(boolean osuAp) {
mOsuAp = osuAp;
}
@@ -975,6 +1009,7 @@ public class WifiInfo implements Parcelable {
dest.writeInt(mEphemeral ? 1 : 0);
dest.writeInt(mTrusted ? 1 : 0);
dest.writeInt(mOemPaid ? 1 : 0);
+ dest.writeInt(mOemPrivate ? 1 : 0);
dest.writeInt(score);
dest.writeLong(txSuccess);
dest.writeDouble(mSuccessfulTxPacketsPerSecond);
@@ -1021,6 +1056,7 @@ public class WifiInfo implements Parcelable {
info.mEphemeral = in.readInt() != 0;
info.mTrusted = in.readInt() != 0;
info.mOemPaid = in.readInt() != 0;
+ info.mOemPrivate = in.readInt() != 0;
info.score = in.readInt();
info.txSuccess = in.readLong();
info.mSuccessfulTxPacketsPerSecond = in.readDouble();
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index acae218b74e0..dc6ec907ab95 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -25,6 +25,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.net.MacAddress;
import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.os.Parcel;
import android.os.Parcelable;
@@ -180,6 +181,12 @@ public final class WifiNetworkSuggestion implements Parcelable {
private boolean mIsNetworkOemPaid;
/**
+ * Whether this network will be brought up as OEM private (OEM_PRIVATE capability bit
+ * added).
+ */
+ private boolean mIsNetworkOemPrivate;
+
+ /**
* Whether this network will use enhanced MAC randomization.
*/
private boolean mIsEnhancedMacRandomizationEnabled;
@@ -206,6 +213,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
mWapiEnterpriseConfig = null;
mIsNetworkUntrusted = false;
mIsNetworkOemPaid = false;
+ mIsNetworkOemPrivate = false;
mPriorityGroup = 0;
mIsEnhancedMacRandomizationEnabled = false;
mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -667,6 +675,9 @@ public final class WifiNetworkSuggestion implements Parcelable {
* reduce it). The connectivity service may use this information to influence the overall
* network configuration of the device.
* <p>
+ * <li> These suggestions are only considered for network selection if a
+ * {@link NetworkRequest} without {@link NetworkCapabilities#NET_CAPABILITY_TRUSTED}
+ * capability is filed.
* <li> An untrusted network's credentials may not be shared with the user using
* {@link #setCredentialSharedWithUser(boolean)}.</li>
* <li> If not set, defaults to false (i.e. network is trusted).</li>
@@ -688,7 +699,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
* <li>The connectivity service may use this information to influence the overall
* network configuration of the device. This network is typically only available to system
* apps.
- * <li>On devices which support only 1 concurrent connection (indicated via
+ * <li>On devices which do not support concurrent connection (indicated via
* {@link WifiManager#isMultiStaConcurrencySupported()}, Wi-Fi network selection process may
* use this information to influence priority of the suggested network for Wi-Fi network
* selection (most likely to reduce it).
@@ -699,6 +710,13 @@ public final class WifiNetworkSuggestion implements Parcelable {
* <p>
* <li> An OEM paid network's credentials may not be shared with the user using
* {@link #setCredentialSharedWithUser(boolean)}.</li>
+ * <li> These suggestions are only considered for network selection if a
+ * {@link NetworkRequest} with {@link NetworkCapabilities#NET_CAPABILITY_OEM_PAID}
+ * capability is filed.
+ * <li> Each suggestion can have both {@link #setOemPaid(boolean)} and
+ * {@link #setOemPrivate(boolean)} set if the app wants these suggestions considered
+ * for creating either an OEM paid network or OEM private network determined based on
+ * the {@link NetworkRequest} that is active.
* <li> If not set, defaults to false (i.e. network is not OEM paid).</li>
*
* @param isOemPaid Boolean indicating whether the network should be brought up as OEM paid
@@ -715,6 +733,48 @@ public final class WifiNetworkSuggestion implements Parcelable {
return this;
}
+ /**
+ * Specifies whether the system will bring up the network (if selected) as OEM private. An
+ * OEM private network has {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE} capability
+ * added.
+ * Note:
+ * <li>The connectivity service may use this information to influence the overall
+ * network configuration of the device. This network is typically only available to system
+ * apps.
+ * <li>On devices which do not support concurrent connection (indicated via
+ * {@link WifiManager#isMultiStaConcurrencySupported()}, Wi-Fi network selection process may
+ * use this information to influence priority of the suggested network for Wi-Fi network
+ * selection (most likely to reduce it).
+ * <li>On devices which support more than 1 concurrent connections (indicated via
+ * {@link WifiManager#isMultiStaConcurrencySupported()}, these OEM private networks will be
+ * brought up as a secondary concurrent connection (primary connection will be used
+ * for networks available to the user and all apps.
+ * <p>
+ * <li> An OEM private network's credentials may not be shared with the user using
+ * {@link #setCredentialSharedWithUser(boolean)}.</li>
+ * <li> These suggestions are only considered for network selection if a
+ * {@link NetworkRequest} with {@link NetworkCapabilities#NET_CAPABILITY_OEM_PRIVATE}
+ * capability is filed.
+ * <li> Each suggestion can have both {@link #setOemPaid(boolean)} and
+ * {@link #setOemPrivate(boolean)} set if the app wants these suggestions considered
+ * for creating either an OEM paid network or OEM private network determined based on
+ * the {@link NetworkRequest} that is active.
+ * <li> If not set, defaults to false (i.e. network is not OEM private).</li>
+ *
+ * @param isOemPrivate Boolean indicating whether the network should be brought up as OEM
+ * private (if true) or not OEM private (if false).
+ * @return Instance of {@link Builder} to enable chaining of the builder method.
+ * @hide
+ */
+ @SystemApi
+ public @NonNull Builder setOemPrivate(boolean isOemPrivate) {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ mIsNetworkOemPrivate = isOemPrivate;
+ return this;
+ }
+
private void setSecurityParamsInWifiConfiguration(
@NonNull WifiConfiguration configuration) {
if (!TextUtils.isEmpty(mWpa2PskPassphrase)) { // WPA-PSK network.
@@ -786,6 +846,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
wifiConfiguration.carrierId = mCarrierId;
wifiConfiguration.trusted = !mIsNetworkUntrusted;
wifiConfiguration.oemPaid = mIsNetworkOemPaid;
+ wifiConfiguration.oemPrivate = mIsNetworkOemPrivate;
wifiConfiguration.macRandomizationSetting = mIsEnhancedMacRandomizationEnabled
? WifiConfiguration.RANDOMIZATION_ENHANCED
: WifiConfiguration.RANDOMIZATION_PERSISTENT;
@@ -819,6 +880,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
wifiConfiguration.meteredOverride = mMeteredOverride;
wifiConfiguration.trusted = !mIsNetworkUntrusted;
wifiConfiguration.oemPaid = mIsNetworkOemPaid;
+ wifiConfiguration.oemPrivate = mIsNetworkOemPrivate;
wifiConfiguration.subscriptionId = mSubscriptionId;
mPasspointConfiguration.setCarrierId(mCarrierId);
mPasspointConfiguration.setSubscriptionId(mSubscriptionId);
@@ -938,6 +1000,14 @@ public final class WifiNetworkSuggestion implements Parcelable {
}
mIsSharedWithUser = false;
}
+ if (mIsNetworkOemPrivate) {
+ if (mIsSharedWithUserSet && mIsSharedWithUser) {
+ throw new IllegalStateException("Should not be both"
+ + "setCredentialSharedWithUser and +"
+ + "setOemPrivate to true");
+ }
+ mIsSharedWithUser = false;
+ }
return new WifiNetworkSuggestion(
wifiConfiguration,
mPasspointConfiguration,
@@ -1105,6 +1175,7 @@ public final class WifiNetworkSuggestion implements Parcelable {
.append(", isInitialAutoJoinEnabled=").append(isInitialAutoJoinEnabled)
.append(", isUnTrusted=").append(!wifiConfiguration.trusted)
.append(", isOemPaid=").append(wifiConfiguration.oemPaid)
+ .append(", isOemPrivate=").append(wifiConfiguration.oemPrivate)
.append(", priorityGroup=").append(priorityGroup)
.append(" ]");
return sb.toString();
@@ -1212,6 +1283,18 @@ public final class WifiNetworkSuggestion implements Parcelable {
}
/**
+ * @see Builder#setOemPrivate(boolean)
+ * @hide
+ */
+ @SystemApi
+ public boolean isOemPrivate() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ return wifiConfiguration.oemPrivate;
+ }
+
+ /**
* Get the WifiEnterpriseConfig, or null if unset.
* @see Builder#setWapiEnterpriseConfig(WifiEnterpriseConfig)
* @see Builder#setWpa2EnterpriseConfig(WifiEnterpriseConfig)
diff --git a/wifi/java/android/net/wifi/aware/AwareResources.java b/wifi/java/android/net/wifi/aware/AwareResources.java
new file mode 100644
index 000000000000..cee1f40c05cd
--- /dev/null
+++ b/wifi/java/android/net/wifi/aware/AwareResources.java
@@ -0,0 +1,146 @@
+/*
+ * 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 android.net.wifi.aware;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * The resources of the Aware service.
+ */
+public final class AwareResources implements Parcelable {
+ /**
+ * Number of the NDPs are available.
+ */
+ private int mNumOfAvailableNdps;
+
+ /**
+ * Number of the publish sessions are available.
+ */
+ private int mNumOfAvailablePublishSessions;
+
+ /**
+ * Number of the subscribe sessions are available.
+ */
+ private int mNumOfAvailableSubscribeSessions;
+
+ /**
+ * @hide : should not be created by apps
+ */
+ public AwareResources() {
+ }
+
+ /**
+ * Return the number of Aware data-paths (also known as NDPs - NAN Data Paths) which an app
+ * could create. Please refer to the {@link WifiAwareNetworkSpecifier} to create
+ * a Network Specifier and request a data-path.
+ * <p>
+ * Note that these resources aren't reserved - other apps could use them by the time you
+ * attempt to create a data-path.
+ * </p>
+ * @return A Non-negative integer, number of data-paths that could be created.
+ */
+ public int getNumOfAvailableDataPaths() {
+ return mNumOfAvailableNdps;
+ }
+
+ /**
+ * Return the number of Aware publish sessions which an app could create. Please refer to the
+ * {@link WifiAwareSession#publish(PublishConfig, DiscoverySessionCallback, Handler)}
+ * to create a publish session.
+ * <p>
+ * Note that these resources aren't reserved - other apps could use them by the time you
+ * attempt to create a publish session.
+ * </p>
+ * @return A Non-negative integer, number of publish sessions that could be created.
+ */
+ public int getNumOfAvailablePublishSessions() {
+ return mNumOfAvailablePublishSessions;
+ }
+
+ /**
+ * Return the number of Aware subscribe sessions which an app could create. Please refer to the
+ * {@link WifiAwareSession#subscribe(SubscribeConfig, DiscoverySessionCallback, Handler)}
+ * to create a publish session.
+ * <p>
+ * Note that these resources aren't reserved - other apps could use them by the time you
+ * attempt to create a subscribe session.
+ * </p>
+ * @return A Non-negative integer, number of subscribe sessions that could be created.
+ */
+ public int getNumOfAvailableSubscribeSessions() {
+ return mNumOfAvailableSubscribeSessions;
+ }
+
+ /**
+ * Set the number of the available NDPs.
+ * @hide
+ * @param numOfAvailableNdps Number of available NDPs.
+ */
+ public void setNumOfAvailableDataPaths(int numOfAvailableNdps) {
+ mNumOfAvailableNdps = numOfAvailableNdps;
+ }
+
+ /**
+ * Set the number of the available publish sessions.
+ * @hide
+ * @param numOfAvailablePublishSessions Number of available publish sessions.
+ */
+ public void setNumOfAvailablePublishSessions(int numOfAvailablePublishSessions) {
+ mNumOfAvailablePublishSessions = numOfAvailablePublishSessions;
+ }
+
+ /**
+ * Set the number of the available subscribe sessions.
+ * @hide
+ * @param numOfAvailableSubscribeSessions Number of available subscribe sessions.
+ */
+ public void setNumOfAvailableSubscribeSessions(int numOfAvailableSubscribeSessions) {
+ mNumOfAvailableSubscribeSessions = numOfAvailableSubscribeSessions;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mNumOfAvailableNdps);
+ dest.writeInt(mNumOfAvailablePublishSessions);
+ dest.writeInt(mNumOfAvailableSubscribeSessions);
+ }
+
+ public static final @android.annotation.NonNull Creator<AwareResources> CREATOR =
+ new Creator<AwareResources>() {
+ @Override
+ public AwareResources createFromParcel(Parcel in) {
+ AwareResources awareResources = new AwareResources();
+ awareResources.setNumOfAvailableDataPaths(in.readInt());
+ awareResources.setNumOfAvailablePublishSessions(in.readInt());
+ awareResources.setNumOfAvailableSubscribeSessions(in.readInt());
+ return awareResources;
+ }
+
+ @Override
+ public AwareResources[] newArray(int size) {
+ return new AwareResources[size];
+ }
+ };
+}
diff --git a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
index cd2ca692137d..c90c4d8a27b2 100644
--- a/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
+++ b/wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl
@@ -25,6 +25,7 @@ import android.net.wifi.aware.IWifiAwareMacAddressProvider;
import android.net.wifi.aware.PublishConfig;
import android.net.wifi.aware.SubscribeConfig;
import android.net.wifi.aware.Characteristics;
+import android.net.wifi.aware.AwareResources;
/**
* Interface that WifiAwareService implements
@@ -36,6 +37,7 @@ interface IWifiAwareManager
// Aware API
boolean isUsageEnabled();
Characteristics getCharacteristics();
+ AwareResources getAvailableAwareResources();
boolean isDeviceAttached();
void enableInstantCommunicationMode(in String callingPackage, boolean enable);
boolean isInstantCommunicationModeEnabled();
diff --git a/wifi/java/android/net/wifi/aware/WifiAwareManager.java b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
index 67c60322e47a..e19b095b27eb 100644
--- a/wifi/java/android/net/wifi/aware/WifiAwareManager.java
+++ b/wifi/java/android/net/wifi/aware/WifiAwareManager.java
@@ -263,7 +263,7 @@ public class WifiAwareManager {
*
* @return An object specifying configuration limitations of Aware.
*/
- public Characteristics getCharacteristics() {
+ public @Nullable Characteristics getCharacteristics() {
try {
return mService.getCharacteristics();
} catch (RemoteException e) {
@@ -272,6 +272,23 @@ public class WifiAwareManager {
}
/**
+ * Return the available resources of the Wi-Fi aware service: a set of parameters which specify
+ * limitations on service usage, e.g the number of data-paths which could be created..
+ *
+ * @return An object specifying the currently available resource of the Wi-Fi Aware service.
+ */
+ public @Nullable AwareResources getAvailableAwareResources() {
+ if (!SdkLevel.isAtLeastS()) {
+ throw new UnsupportedOperationException();
+ }
+ try {
+ return mService.getAvailableAwareResources();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Attach to the Wi-Fi Aware service - enabling the application to create discovery sessions or
* create connections to peers. The device will attach to an existing cluster if it can find
* one or create a new cluster (if it is the first to enable Aware in its vicinity). Results
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index b82c67b658aa..f09c37d811f9 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -69,6 +69,7 @@ public class WifiConfigurationTest {
config.setPasspointManagementObjectTree(cookie);
config.trusted = false;
config.oemPaid = true;
+ config.oemPrivate = true;
config.updateIdentifier = "1234";
config.fromWifiNetworkSpecifier = true;
config.fromWifiNetworkSuggestion = true;
@@ -91,8 +92,10 @@ public class WifiConfigurationTest {
assertEquals(macBeforeParcel, reconfig.getRandomizedMacAddress());
assertEquals(config.updateIdentifier, reconfig.updateIdentifier);
assertFalse(reconfig.trusted);
- assertTrue(config.fromWifiNetworkSpecifier);
- assertTrue(config.fromWifiNetworkSuggestion);
+ assertTrue(reconfig.fromWifiNetworkSpecifier);
+ assertTrue(reconfig.fromWifiNetworkSuggestion);
+ assertTrue(reconfig.oemPaid);
+ assertTrue(reconfig.oemPrivate);
Parcel parcelWW = Parcel.obtain();
reconfig.writeToParcel(parcelWW, 0);
@@ -103,6 +106,32 @@ public class WifiConfigurationTest {
}
@Test
+ public void testWifiConfigurationCopyConstructor() {
+ WifiConfiguration config = new WifiConfiguration();
+ config.trusted = false;
+ config.oemPaid = true;
+ config.oemPrivate = true;
+ config.updateIdentifier = "1234";
+ config.fromWifiNetworkSpecifier = true;
+ config.fromWifiNetworkSuggestion = true;
+ config.setRandomizedMacAddress(MacAddressUtils.createRandomUnicastAddress());
+ MacAddress macBeforeParcel = config.getRandomizedMacAddress();
+ config.subscriptionId = 1;
+ config.carrierId = 1189;
+
+ WifiConfiguration reconfig = new WifiConfiguration(config);
+
+ // lacking a useful config.equals, check two fields near the end.
+ assertEquals(macBeforeParcel, reconfig.getRandomizedMacAddress());
+ assertEquals(config.updateIdentifier, reconfig.updateIdentifier);
+ assertFalse(reconfig.trusted);
+ assertTrue(reconfig.fromWifiNetworkSpecifier);
+ assertTrue(reconfig.fromWifiNetworkSuggestion);
+ assertTrue(reconfig.oemPaid);
+ assertTrue(reconfig.oemPrivate);
+ }
+
+ @Test
public void testIsOpenNetwork_IsOpen_NullWepKeys() {
WifiConfiguration config = new WifiConfiguration();
config.allowedKeyManagement.clear();
diff --git a/wifi/tests/src/android/net/wifi/WifiInfoTest.java b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
index 06ae13a21e38..c6faf66140e2 100644
--- a/wifi/tests/src/android/net/wifi/WifiInfoTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
@@ -17,6 +17,7 @@
package android.net.wifi;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue;
@@ -62,6 +63,7 @@ public class WifiInfoTest {
writeWifiInfo.rxSuccess = TEST_RX_SUCCESS;
writeWifiInfo.setTrusted(true);
writeWifiInfo.setOemPaid(true);
+ writeWifiInfo.setOemPrivate(true);
writeWifiInfo.setOsuAp(true);
writeWifiInfo.setFQDN(TEST_FQDN);
writeWifiInfo.setProviderFriendlyName(TEST_PROVIDER_NAME);
@@ -83,6 +85,46 @@ public class WifiInfoTest {
assertEquals(TEST_RX_SUCCESS, readWifiInfo.rxSuccess);
assertTrue(readWifiInfo.isTrusted());
assertTrue(readWifiInfo.isOemPaid());
+ assertTrue(readWifiInfo.isOemPrivate());
+ assertTrue(readWifiInfo.isOsuAp());
+ assertTrue(readWifiInfo.isPasspointAp());
+ assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getRequestingPackageName());
+ assertEquals(TEST_FQDN, readWifiInfo.getPasspointFqdn());
+ assertEquals(TEST_PROVIDER_NAME, readWifiInfo.getPasspointProviderFriendlyName());
+ assertEquals(TEST_WIFI_STANDARD, readWifiInfo.getWifiStandard());
+ assertEquals(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS,
+ readWifiInfo.getMaxSupportedTxLinkSpeedMbps());
+ assertEquals(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS,
+ readWifiInfo.getMaxSupportedRxLinkSpeedMbps());
+ }
+
+ @Test
+ public void testWifiInfoCopyConstructor() throws Exception {
+ WifiInfo writeWifiInfo = new WifiInfo();
+ writeWifiInfo.txSuccess = TEST_TX_SUCCESS;
+ writeWifiInfo.txRetries = TEST_TX_RETRIES;
+ writeWifiInfo.txBad = TEST_TX_BAD;
+ writeWifiInfo.rxSuccess = TEST_RX_SUCCESS;
+ writeWifiInfo.setTrusted(true);
+ writeWifiInfo.setOemPaid(true);
+ writeWifiInfo.setOemPrivate(true);
+ writeWifiInfo.setOsuAp(true);
+ writeWifiInfo.setFQDN(TEST_FQDN);
+ writeWifiInfo.setProviderFriendlyName(TEST_PROVIDER_NAME);
+ writeWifiInfo.setRequestingPackageName(TEST_PACKAGE_NAME);
+ writeWifiInfo.setWifiStandard(TEST_WIFI_STANDARD);
+ writeWifiInfo.setMaxSupportedTxLinkSpeedMbps(TEST_MAX_SUPPORTED_TX_LINK_SPEED_MBPS);
+ writeWifiInfo.setMaxSupportedRxLinkSpeedMbps(TEST_MAX_SUPPORTED_RX_LINK_SPEED_MBPS);
+
+ WifiInfo readWifiInfo = new WifiInfo(writeWifiInfo);
+
+ assertEquals(TEST_TX_SUCCESS, readWifiInfo.txSuccess);
+ assertEquals(TEST_TX_RETRIES, readWifiInfo.txRetries);
+ assertEquals(TEST_TX_BAD, readWifiInfo.txBad);
+ assertEquals(TEST_RX_SUCCESS, readWifiInfo.rxSuccess);
+ assertTrue(readWifiInfo.isTrusted());
+ assertTrue(readWifiInfo.isOemPaid());
+ assertTrue(readWifiInfo.isOemPrivate());
assertTrue(readWifiInfo.isOsuAp());
assertTrue(readWifiInfo.isPasspointAp());
assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getRequestingPackageName());
@@ -110,6 +152,8 @@ public class WifiInfoTest {
assertEquals(WifiManager.UNKNOWN_SSID, wifiInfo.getSSID());
assertEquals(null, wifiInfo.getBSSID());
assertEquals(-1, wifiInfo.getNetworkId());
+ assertFalse(wifiInfo.isOemPaid());
+ assertFalse(wifiInfo.isOemPrivate());
}
/**
diff --git a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
index 56e79983817f..870ff0a26d58 100644
--- a/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiNetworkSuggestionTest.java
@@ -223,6 +223,34 @@ public class WifiNetworkSuggestionTest {
/**
* Validate correctness of WifiNetworkSuggestion object created by
+ * {@link WifiNetworkSuggestion.Builder#build()} for OWE network.
+ */
+ @Test
+ public void testWifiNetworkSuggestionBuilderForOemPrivateEnhancedOpenNetworkWithBssid() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setBssid(MacAddress.fromString(TEST_BSSID))
+ .setOemPrivate(true)
+ .setIsEnhancedOpen(true)
+ .build();
+
+ assertEquals("\"" + TEST_SSID + "\"", suggestion.wifiConfiguration.SSID);
+ assertEquals(TEST_BSSID, suggestion.wifiConfiguration.BSSID);
+ assertTrue(suggestion.wifiConfiguration.allowedKeyManagement
+ .get(WifiConfiguration.KeyMgmt.OWE));
+ assertNull(suggestion.wifiConfiguration.preSharedKey);
+ assertTrue(suggestion.wifiConfiguration.requirePmf);
+ assertTrue(suggestion.wifiConfiguration.oemPrivate);
+ assertTrue(suggestion.isOemPrivate());
+ assertFalse(suggestion.isUserAllowedToManuallyConnect);
+ assertTrue(suggestion.isInitialAutoJoinEnabled);
+ assertNull(suggestion.getEnterpriseConfig());
+ }
+
+ /**
+ * Validate correctness of WifiNetworkSuggestion object created by
* {@link WifiNetworkSuggestion.Builder#build()} for SAE network.
*/
@Test
@@ -1285,6 +1313,41 @@ public class WifiNetworkSuggestionTest {
}
/**
+ * Validate {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} set the
+ * correct value to the WifiConfiguration.
+ */
+ @Test
+ public void testSetIsNetworkAsOemPrivate() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa2Passphrase(TEST_PRESHARED_KEY)
+ .setOemPrivate(true)
+ .build();
+ assertTrue(suggestion.isOemPrivate());
+ assertFalse(suggestion.isUserAllowedToManuallyConnect);
+ }
+
+ /**
+ * Validate {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} set the
+ * correct value to the WifiConfiguration.
+ * Also the {@link WifiNetworkSuggestion#isUserAllowedToManuallyConnect} should be false;
+ */
+ @Test
+ public void testSetIsNetworkAsOemPrivateOnPasspointNetwork() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ PasspointConfiguration passpointConfiguration = PasspointTestUtils.createConfig();
+ WifiNetworkSuggestion suggestion = new WifiNetworkSuggestion.Builder()
+ .setPasspointConfig(passpointConfiguration)
+ .setOemPrivate(true)
+ .build();
+ assertTrue(suggestion.isOemPrivate());
+ assertFalse(suggestion.isUserAllowedToManuallyConnect);
+ }
+
+ /**
* Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
* when set {@link WifiNetworkSuggestion.Builder#setUntrusted(boolean)} to true and
* set {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} to true
@@ -1320,6 +1383,24 @@ public class WifiNetworkSuggestionTest {
/**
* Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
+ * when set {@link WifiNetworkSuggestion.Builder#setOemPrivate(boolean)} to true and
+ * set {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} to true
+ * together.
+ */
+ @Test(expected = IllegalStateException.class)
+ public void testSetCredentialSharedWithUserWithSetIsNetworkAsOemPrivate() {
+ assumeTrue(SdkLevel.isAtLeastS());
+
+ new WifiNetworkSuggestion.Builder()
+ .setSsid(TEST_SSID)
+ .setWpa2Passphrase(TEST_PRESHARED_KEY)
+ .setCredentialSharedWithUser(true)
+ .setOemPrivate(true)
+ .build();
+ }
+
+ /**
+ * Ensure {@link WifiNetworkSuggestion.Builder#build()} throws an exception
* when set both {@link WifiNetworkSuggestion.Builder#setIsInitialAutojoinEnabled(boolean)}
* and {@link WifiNetworkSuggestion.Builder#setCredentialSharedWithUser(boolean)} (boolean)}
* to false on a passpoint suggestion.
diff --git a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
index d0d0c57008fc..1ecd32555bfe 100644
--- a/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/aware/WifiAwareManagerTest.java
@@ -155,6 +155,7 @@ public class WifiAwareManagerTest {
*/
@Test
public void testIsAttached() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastS());
mDut.isDeviceAttached();
verify(mockAwareService).isDeviceAttached();
}
@@ -172,6 +173,16 @@ public class WifiAwareManagerTest {
verify(mockAwareService).enableInstantCommunicationMode(anyString(), eq(true));
}
+ /**
+ * Validate pass-through of getAvailableAwareResources() API.
+ */
+ @Test
+ public void testGetAvailableAwareResource() throws Exception {
+ assumeTrue(SdkLevel.isAtLeastS());
+ mDut.getAvailableAwareResources();
+ verify(mockAwareService).getAvailableAwareResources();
+ }
+
/*
* WifiAwareEventCallbackProxy Tests
*/