summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--StubLibraries.bp43
-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--api/current.txt12
-rw-r--r--api/system-current.txt13
-rw-r--r--api/test-current.txt10
-rw-r--r--core/api/Android.bp (renamed from non-updatable-api/Android.bp)0
-rw-r--r--core/api/current.txt (renamed from non-updatable-api/current.txt)12
-rw-r--r--core/api/module-lib-current.txt (renamed from non-updatable-api/module-lib-current.txt)0
-rw-r--r--core/api/module-lib-removed.txt (renamed from non-updatable-api/module-lib-removed.txt)0
-rw-r--r--core/api/removed.txt (renamed from non-updatable-api/removed.txt)0
-rw-r--r--core/api/system-current.txt (renamed from non-updatable-api/system-current.txt)4
-rw-r--r--core/api/system-lint-baseline.txt (renamed from non-updatable-api/system-lint-baseline.txt)0
-rw-r--r--core/api/system-removed.txt (renamed from non-updatable-api/system-removed.txt)0
-rw-r--r--core/java/android/app/INotificationManager.aidl4
-rw-r--r--core/java/android/app/NotificationManager.java14
-rw-r--r--core/java/android/app/SystemServiceRegistry.java10
-rw-r--r--core/java/android/app/TaskInfo.java18
-rw-r--r--core/java/android/app/WindowConfiguration.java3
-rw-r--r--core/java/android/app/backup/FullBackup.java3
-rw-r--r--core/java/android/app/backup/OWNERS11
-rw-r--r--core/java/android/app/time/TimeManager.java2
-rw-r--r--core/java/android/app/time/TimeZoneCapabilities.java3
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java130
-rw-r--r--core/java/android/content/Context.java11
-rw-r--r--core/java/android/content/pm/PackageManager.java11
-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/net/vcn/IVcnManagementService.aidl (renamed from core/tests/coretests/src/android/app/appsearch/external/app/SearchResultsTest.java)21
-rw-r--r--core/java/android/net/vcn/VcnManager.java48
-rw-r--r--core/java/android/security/keymaster/KeymasterDefs.java3
-rw-r--r--core/java/android/view/IWindowManager.aidl7
-rw-r--r--core/java/android/view/SurfaceControl.java89
-rw-r--r--core/java/android/view/SyncRtSurfaceTransactionApplier.java26
-rw-r--r--core/java/android/view/ViewRootImpl.java39
-rw-r--r--core/java/android/view/WindowManager.java16
-rw-r--r--core/java/android/view/inputmethod/BaseInputConnection.java12
-rw-r--r--core/java/android/view/inputmethod/InputConnection.java18
-rw-r--r--core/java/android/view/inputmethod/InputConnectionWrapper.java16
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java2
-rw-r--r--core/java/com/android/internal/graphics/drawable/BackgroundBlurDrawable.java257
-rw-r--r--core/java/com/android/internal/view/InputConnectionWrapper.java23
-rw-r--r--core/jni/Android.bp2
-rw-r--r--core/jni/android_view_SurfaceControl.cpp43
-rw-r--r--core/res/AndroidManifest.xml4
-rw-r--r--core/res/res/layout/notification_material_action_list.xml8
-rw-r--r--core/res/res/values-bn/strings.xml6
-rw-r--r--core/res/res/values-ca/strings.xml6
-rw-r--r--core/res/res/values-es/strings.xml6
-rw-r--r--core/res/res/values-gu/strings.xml8
-rw-r--r--core/res/res/values-km/strings.xml6
-rw-r--r--core/res/res/values-kn/strings.xml6
-rw-r--r--core/res/res/values-ky/strings.xml4
-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-pa/strings.xml6
-rw-r--r--core/res/res/values-te/strings.xml6
-rw-r--r--core/res/res/values/dimens.xml4
-rw-r--r--core/res/res/values/symbols.xml3
-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/widget/TextViewOnReceiveContentTest.java (renamed from core/tests/coretests/src/android/widget/TextViewOnReceiveContentCallbackTest.java)4
-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/common/SystemWindows.java34
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java15
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java95
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuActivityController.java170
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java18
-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/DividerWindowManager.java3
-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.java9
-rw-r--r--media/java/android/media/Image.java3
-rw-r--r--media/java/android/media/MediaTranscodeManager.java13
-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/DynamicSystemInstallationService/res/values/strings.xml3
-rw-r--r--packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java13
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java6
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/OWNERS7
-rw-r--r--packages/SettingsProvider/test/src/android/provider/OWNERS6
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml2
-rw-r--r--packages/SystemUI/res/drawable/ic_battery_unknown.xml24
-rw-r--r--packages/SystemUI/res/layout/notification_info.xml4
-rw-r--r--packages/SystemUI/res/layout/partial_conversation_info.xml4
-rw-r--r--packages/SystemUI/res/values/config.xml5
-rw-r--r--packages/SystemUI/res/values/dimens.xml3
-rw-r--r--packages/SystemUI/res/values/strings.xml8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/BatteryMeterView.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIService.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java17
-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.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java98
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java160
-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/KeyguardClockPositionAlgorithm.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenLockIconController.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt90
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java2
-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/MediaOutputControllerTest.java19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java4
-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.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt81
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java2
-rw-r--r--packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-bn/strings.xml21
-rw-r--r--services/backup/OWNERS1
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java4
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java3
-rw-r--r--services/core/java/com/android/server/VcnManagementService.java103
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/Face10.java16
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java21
-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/connectivity/NetworkNotificationManager.java14
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java11
-rw-r--r--services/core/java/com/android/server/display/LocalDisplayAdapter.java3
-rw-r--r--services/core/java/com/android/server/location/LocationManagerService.java5
-rw-r--r--services/core/java/com/android/server/location/LocationProviderManager.java21
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssLocationProvider.java6
-rw-r--r--services/core/java/com/android/server/net/LockdownVpnTracker.java6
-rw-r--r--services/core/java/com/android/server/notification/ManagedServices.java74
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java66
-rw-r--r--services/core/java/com/android/server/notification/NotificationShellCmd.java6
-rw-r--r--services/core/java/com/android/server/pm/InstantAppRegistry.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java50
-rw-r--r--services/core/java/com/android/server/pm/Settings.java67
-rw-r--r--services/core/java/com/android/server/pm/permission/LegacyPermission.java253
-rw-r--r--services/core/java/com/android/server/pm/permission/LegacyPermissionDataProvider.java20
-rw-r--r--services/core/java/com/android/server/pm/permission/LegacyPermissionSettings.java182
-rw-r--r--services/core/java/com/android/server/pm/permission/LegacyPermissionState.java22
-rw-r--r--services/core/java/com/android/server/pm/permission/Permission.java (renamed from services/core/java/com/android/server/pm/permission/BasePermission.java)399
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java847
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java50
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionRegistry.java156
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionSettings.java277
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionState.java6
-rw-r--r--services/core/java/com/android/server/pm/permission/UidPermissionState.java10
-rw-r--r--services/core/java/com/android/server/stats/pull/StatsPullAtomService.java9
-rw-r--r--services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java23
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java30
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java6
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java48
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java11
-rw-r--r--services/core/java/com/android/server/wm/InputMonitor.java9
-rw-r--r--services/core/java/com/android/server/wm/LockTaskController.java15
-rw-r--r--services/core/java/com/android/server/wm/ShellRoot.java55
-rw-r--r--services/core/java/com/android/server/wm/Task.java37
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java24
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java284
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java46
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java65
-rw-r--r--services/java/com/android/server/SystemServer.java20
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java33
-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/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/pm/PackageManagerSettingsTests.java29
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java102
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java2
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java31
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskTests.java37
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java15
-rw-r--r--telephony/common/com/android/internal/telephony/CarrierAppUtils.java6
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java6
-rw-r--r--telephony/java/com/android/internal/telephony/RILConstants.java4
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java20
-rw-r--r--tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java54
-rw-r--r--tests/net/java/com/android/server/connectivity/VpnTest.java21
-rw-r--r--wifi/api/system-current.txt9
-rw-r--r--wifi/jarjar-rules.txt2
-rw-r--r--wifi/java/android/net/wifi/SoftApCapability.java20
-rw-r--r--wifi/java/android/net/wifi/SoftApConfiguration.java40
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java85
-rw-r--r--wifi/java/android/net/wifi/WifiInfo.java42
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkSuggestion.java85
-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
327 files changed, 7028 insertions, 3750 deletions
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 754c4e94e73a..8090bec24fdb 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -152,8 +152,8 @@ droidstubs {
args: metalava_framework_docs_args,
check_api: {
current: {
- api_file: "non-updatable-api/current.txt",
- removed_api_file: "non-updatable-api/removed.txt",
+ api_file: "core/api/current.txt",
+ removed_api_file: "core/api/removed.txt",
},
last_released: {
api_file: ":android-non-updatable.api.public.latest",
@@ -212,8 +212,8 @@ droidstubs {
args: metalava_framework_docs_args + priv_apps,
check_api: {
current: {
- api_file: "non-updatable-api/system-current.txt",
- removed_api_file: "non-updatable-api/system-removed.txt",
+ api_file: "core/api/system-current.txt",
+ removed_api_file: "core/api/system-removed.txt",
},
last_released: {
api_file: ":android-non-updatable.api.system.latest",
@@ -223,7 +223,7 @@ droidstubs {
api_lint: {
enabled: true,
new_since: ":android-non-updatable.api.system.latest",
- baseline_file: "non-updatable-api/system-lint-baseline.txt",
+ baseline_file: "core/api/system-lint-baseline.txt",
},
},
}
@@ -257,46 +257,19 @@ droidstubs {
}
/////////////////////////////////////////////////////////////////////
-// Following droidstubs modules are for extra APIs for modules,
+// Following droidstub module for extra APIs for modules,
// namely @SystemApi(client=MODULE_LIBRARIES) APIs.
/////////////////////////////////////////////////////////////////////
droidstubs {
- name: "module-lib-api",
- defaults: ["metalava-full-api-stubs-default"],
- arg_files: ["core/res/AndroidManifest.xml"],
- args: metalava_framework_docs_args + module_libs,
-
- // Do not generate stubs as they are not needed
- generate_stubs: false,
-
- check_api: {
- current: {
- api_file: "api/module-lib-current.txt",
- removed_api_file: "api/module-lib-removed.txt",
- },
- last_released: {
- api_file: ":android.api.module-lib.latest",
- removed_api_file: ":removed.api.module-lib.latest",
- baseline_file: ":module-lib-api-incompatibilities-with-last-released"
- },
- api_lint: {
- enabled: true,
- new_since: ":android.api.module-lib.latest",
- baseline_file: "api/module-lib-lint-baseline.txt",
- },
- },
-}
-
-droidstubs {
name: "module-lib-api-stubs-docs-non-updatable",
defaults: ["metalava-non-updatable-api-stubs-default"],
arg_files: ["core/res/AndroidManifest.xml"],
args: metalava_framework_docs_args + priv_apps + module_libs,
check_api: {
current: {
- api_file: "non-updatable-api/module-lib-current.txt",
- removed_api_file: "non-updatable-api/module-lib-removed.txt",
+ api_file: "core/api/module-lib-current.txt",
+ removed_api_file: "core/api/module-lib-removed.txt",
},
last_released: {
api_file: ":android-non-updatable.api.module-lib.latest",
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/api/current.txt b/api/current.txt
index 11d445fb6bab..9ff7cc255bf4 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -57228,8 +57228,8 @@ package android.view.inputmethod {
method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
method public android.os.Handler getHandler();
method public CharSequence getSelectedText(int);
- method public CharSequence getTextAfterCursor(int, int);
- method public CharSequence getTextBeforeCursor(int, int);
+ method @Nullable public CharSequence getTextAfterCursor(@IntRange(from=0) int, int);
+ method @Nullable public CharSequence getTextBeforeCursor(@IntRange(from=0) int, int);
method public boolean performContextMenuAction(int);
method public boolean performEditorAction(int);
method public boolean performPrivateCommand(String, android.os.Bundle);
@@ -57455,8 +57455,8 @@ package android.view.inputmethod {
method public android.os.Handler getHandler();
method public CharSequence getSelectedText(int);
method @Nullable public default android.view.inputmethod.SurroundingText getSurroundingText(@IntRange(from=0) int, @IntRange(from=0) int, int);
- method public CharSequence getTextAfterCursor(int, int);
- method public CharSequence getTextBeforeCursor(int, int);
+ method @Nullable public CharSequence getTextAfterCursor(@IntRange(from=0) int, int);
+ method @Nullable public CharSequence getTextBeforeCursor(@IntRange(from=0) int, int);
method public boolean performContextMenuAction(int);
method public boolean performEditorAction(int);
method public boolean performPrivateCommand(String, android.os.Bundle);
@@ -57490,8 +57490,8 @@ package android.view.inputmethod {
method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
method public android.os.Handler getHandler();
method public CharSequence getSelectedText(int);
- method public CharSequence getTextAfterCursor(int, int);
- method public CharSequence getTextBeforeCursor(int, int);
+ method @Nullable public CharSequence getTextAfterCursor(@IntRange(from=0) int, int);
+ method @Nullable public CharSequence getTextBeforeCursor(@IntRange(from=0) int, int);
method public boolean performContextMenuAction(int);
method public boolean performEditorAction(int);
method public boolean performPrivateCommand(String, android.os.Bundle);
diff --git a/api/system-current.txt b/api/system-current.txt
index 4f74874a7838..5ef042f062b1 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -682,7 +682,7 @@ package android.app {
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public java.util.List<android.content.ComponentName> getEnabledNotificationListeners();
method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName);
method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean);
- method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean, boolean);
field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL = "android.app.action.CLOSE_NOTIFICATION_HANDLER_PANEL";
field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_OPEN_NOTIFICATION_HANDLER_PANEL = "android.app.action.OPEN_NOTIFICATION_HANDLER_PANEL";
field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_TOGGLE_NOTIFICATION_HANDLER_PANEL = "android.app.action.TOGGLE_NOTIFICATION_HANDLER_PANEL";
@@ -7494,6 +7494,7 @@ package android.net.wifi {
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApCapability> CREATOR;
field public static final long SOFTAP_FEATURE_ACS_OFFLOAD = 1L; // 0x1L
field public static final long SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT = 2L; // 0x2L
+ field public static final long SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION = 8L; // 0x8L
field public static final long SOFTAP_FEATURE_WPA3_SAE = 4L; // 0x4L
}
@@ -7584,8 +7585,11 @@ package android.net.wifi {
field @Deprecated public static final int RANDOMIZATION_NONE = 0; // 0x0
field @Deprecated public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1
field @Deprecated public static final int RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA = 17; // 0x11
+ field @Deprecated public static final int RECENT_FAILURE_DISCONNECTION_AP_BUSY = 1004; // 0x3ec
field @Deprecated public static final int RECENT_FAILURE_MBO_OCE_DISCONNECT = 1001; // 0x3e9
field @Deprecated public static final int RECENT_FAILURE_NONE = 0; // 0x0
+ field @Deprecated public static final int RECENT_FAILURE_POOR_CHANNEL_CONDITIONS = 1003; // 0x3eb
+ field @Deprecated public static final int RECENT_FAILURE_REFUSED_TEMPORARILY = 1002; // 0x3ea
field @Deprecated public boolean allowAutojoin;
field @Deprecated public int carrierId;
field @Deprecated public String creatorName;
@@ -7672,8 +7676,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
@@ -7899,11 +7906,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 {
@@ -11769,7 +11778,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int);
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCdmaEnhancedRoamingIndicatorIconIndex();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCdmaEnhancedRoamingIndicatorDisplayNumber();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMin();
diff --git a/api/test-current.txt b/api/test-current.txt
index 0a8f7a59d3b1..edc422dbf24d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -270,6 +270,7 @@ package android.app {
method public void disallowAssistantAdjustment(String);
method public android.content.ComponentName getEffectsSuppressor();
method public boolean matchesCallFilter(android.os.Bundle);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean, boolean);
method public void updateNotificationChannel(@NonNull String, int, @NonNull android.app.NotificationChannel);
}
@@ -289,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 {
@@ -969,6 +971,14 @@ package android.media {
field public static final String SAMPLE_RATE = "android.media.audiotrack.sampleRate";
}
+ public abstract class Image implements java.lang.AutoCloseable {
+ ctor protected Image();
+ }
+
+ public abstract static class Image.Plane {
+ ctor protected Image.Plane();
+ }
+
public final class MediaCas implements java.lang.AutoCloseable {
method public void forceResourceLost();
}
diff --git a/non-updatable-api/Android.bp b/core/api/Android.bp
index 00b901992b90..00b901992b90 100644
--- a/non-updatable-api/Android.bp
+++ b/core/api/Android.bp
diff --git a/non-updatable-api/current.txt b/core/api/current.txt
index ff2e1d490c2e..16a5f5e82f21 100644
--- a/non-updatable-api/current.txt
+++ b/core/api/current.txt
@@ -55346,8 +55346,8 @@ package android.view.inputmethod {
method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
method public android.os.Handler getHandler();
method public CharSequence getSelectedText(int);
- method public CharSequence getTextAfterCursor(int, int);
- method public CharSequence getTextBeforeCursor(int, int);
+ method @Nullable public CharSequence getTextAfterCursor(@IntRange(from=0) int, int);
+ method @Nullable public CharSequence getTextBeforeCursor(@IntRange(from=0) int, int);
method public boolean performContextMenuAction(int);
method public boolean performEditorAction(int);
method public boolean performPrivateCommand(String, android.os.Bundle);
@@ -55573,8 +55573,8 @@ package android.view.inputmethod {
method public android.os.Handler getHandler();
method public CharSequence getSelectedText(int);
method @Nullable public default android.view.inputmethod.SurroundingText getSurroundingText(@IntRange(from=0) int, @IntRange(from=0) int, int);
- method public CharSequence getTextAfterCursor(int, int);
- method public CharSequence getTextBeforeCursor(int, int);
+ method @Nullable public CharSequence getTextAfterCursor(@IntRange(from=0) int, int);
+ method @Nullable public CharSequence getTextBeforeCursor(@IntRange(from=0) int, int);
method public boolean performContextMenuAction(int);
method public boolean performEditorAction(int);
method public boolean performPrivateCommand(String, android.os.Bundle);
@@ -55608,8 +55608,8 @@ package android.view.inputmethod {
method public android.view.inputmethod.ExtractedText getExtractedText(android.view.inputmethod.ExtractedTextRequest, int);
method public android.os.Handler getHandler();
method public CharSequence getSelectedText(int);
- method public CharSequence getTextAfterCursor(int, int);
- method public CharSequence getTextBeforeCursor(int, int);
+ method @Nullable public CharSequence getTextAfterCursor(@IntRange(from=0) int, int);
+ method @Nullable public CharSequence getTextBeforeCursor(@IntRange(from=0) int, int);
method public boolean performContextMenuAction(int);
method public boolean performEditorAction(int);
method public boolean performPrivateCommand(String, android.os.Bundle);
diff --git a/non-updatable-api/module-lib-current.txt b/core/api/module-lib-current.txt
index 06e6d9ccbbf0..06e6d9ccbbf0 100644
--- a/non-updatable-api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
diff --git a/non-updatable-api/module-lib-removed.txt b/core/api/module-lib-removed.txt
index d802177e249b..d802177e249b 100644
--- a/non-updatable-api/module-lib-removed.txt
+++ b/core/api/module-lib-removed.txt
diff --git a/non-updatable-api/removed.txt b/core/api/removed.txt
index f2dfb84eb8fe..f2dfb84eb8fe 100644
--- a/non-updatable-api/removed.txt
+++ b/core/api/removed.txt
diff --git a/non-updatable-api/system-current.txt b/core/api/system-current.txt
index 217c4b0674f5..eea50be6da1d 100644
--- a/non-updatable-api/system-current.txt
+++ b/core/api/system-current.txt
@@ -682,7 +682,7 @@ package android.app {
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public java.util.List<android.content.ComponentName> getEnabledNotificationListeners();
method public boolean isNotificationAssistantAccessGranted(@NonNull android.content.ComponentName);
method public void setNotificationAssistantAccessGranted(@Nullable android.content.ComponentName, boolean);
- method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted(@NonNull android.content.ComponentName, boolean, boolean);
field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL = "android.app.action.CLOSE_NOTIFICATION_HANDLER_PANEL";
field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_OPEN_NOTIFICATION_HANDLER_PANEL = "android.app.action.OPEN_NOTIFICATION_HANDLER_PANEL";
field @RequiresPermission(android.Manifest.permission.STATUS_BAR_SERVICE) public static final String ACTION_TOGGLE_NOTIFICATION_HANDLER_PANEL = "android.app.action.TOGGLE_NOTIFICATION_HANDLER_PANEL";
@@ -10620,7 +10620,7 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCarrierPrivilegeStatus(int);
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<java.lang.String> getCarrierPrivilegedPackagesForAllActiveSubscriptions();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CarrierRestrictionRules getCarrierRestrictionRules();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCdmaEnhancedRoamingIndicatorIconIndex();
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCdmaEnhancedRoamingIndicatorDisplayNumber();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMdn(int);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public String getCdmaMin();
diff --git a/non-updatable-api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index 4db55e7e07eb..4db55e7e07eb 100644
--- a/non-updatable-api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
diff --git a/non-updatable-api/system-removed.txt b/core/api/system-removed.txt
index 0c02c43b1084..0c02c43b1084 100644
--- a/non-updatable-api/system-removed.txt
+++ b/core/api/system-removed.txt
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index c052186bb974..d798f22a6af9 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -177,9 +177,9 @@ interface INotificationManager
boolean isNotificationListenerAccessGranted(in ComponentName listener);
boolean isNotificationListenerAccessGrantedForUser(in ComponentName listener, int userId);
boolean isNotificationAssistantAccessGranted(in ComponentName assistant);
- void setNotificationListenerAccessGranted(in ComponentName listener, boolean enabled);
+ void setNotificationListenerAccessGranted(in ComponentName listener, boolean enabled, boolean userSet);
void setNotificationAssistantAccessGranted(in ComponentName assistant, boolean enabled);
- void setNotificationListenerAccessGrantedForUser(in ComponentName listener, int userId, boolean enabled);
+ void setNotificationListenerAccessGrantedForUser(in ComponentName listener, int userId, boolean enabled, boolean userSet);
void setNotificationAssistantAccessGrantedForUser(in ComponentName assistant, int userId, boolean enabled);
List<String> getEnabledNotificationListenerPackages();
List<ComponentName> getEnabledNotificationListeners(int userId);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 27cd78acb35f..12460ba2bd4b 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -1565,6 +1565,12 @@ public class NotificationManager {
}
}
+ /** @hide */
+ public void setNotificationListenerAccessGranted(
+ @NonNull ComponentName listener, boolean granted) {
+ setNotificationListenerAccessGranted(listener, granted, true);
+ }
+
/**
* Grants/revokes Notification Listener access to the given component for current user.
* To grant access for a particular user, obtain this service by using the {@link Context}
@@ -1572,15 +1578,17 @@ public class NotificationManager {
*
* @param listener Name of component to grant/revoke access
* @param granted Grant/revoke access
+ * @param userSet Whether the action was triggered explicitly by user
* @hide
*/
@SystemApi
+ @TestApi
@RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS)
public void setNotificationListenerAccessGranted(
- @NonNull ComponentName listener, boolean granted) {
+ @NonNull ComponentName listener, boolean granted, boolean userSet) {
INotificationManager service = getService();
try {
- service.setNotificationListenerAccessGranted(listener, granted);
+ service.setNotificationListenerAccessGranted(listener, granted, userSet);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1591,7 +1599,7 @@ public class NotificationManager {
boolean granted) {
INotificationManager service = getService();
try {
- service.setNotificationListenerAccessGrantedForUser(listener, userId, granted);
+ service.setNotificationListenerAccessGrantedForUser(listener, userId, granted, true);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 4b3bebe36c29..73777909d417 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -136,6 +136,8 @@ import android.net.lowpan.ILowpanManager;
import android.net.lowpan.LowpanManager;
import android.net.nsd.INsdManager;
import android.net.nsd.NsdManager;
+import android.net.vcn.IVcnManagementService;
+import android.net.vcn.VcnManager;
import android.net.wifi.WifiFrameworkInitializer;
import android.net.wifi.nl80211.WifiNl80211Manager;
import android.nfc.NfcManager;
@@ -385,6 +387,14 @@ public final class SystemServiceRegistry {
ctx, () -> ServiceManager.getService(Context.TETHERING_SERVICE));
}});
+ registerService(Context.VCN_MANAGEMENT_SERVICE, VcnManager.class,
+ new CachedServiceFetcher<VcnManager>() {
+ @Override
+ public VcnManager createService(ContextImpl ctx) throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getService(Context.VCN_MANAGEMENT_SERVICE);
+ IVcnManagementService service = IVcnManagementService.Stub.asInterface(b);
+ return new VcnManager(ctx, service);
+ }});
registerService(Context.IPSEC_SERVICE, IpSecManager.class,
new CachedServiceFetcher<IpSecManager>() {
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/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index c4af4edb467b..4ae1670e9041 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -796,9 +796,6 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
/**
* Returns {@code true} if the windowingMode represents a window in multi-window mode.
* I.e. sharing the screen with another activity.
- *
- * TODO(b/171672645): This API could be misleading - in 'undefined' mode it's determined by the
- * parent's mode
* @hide
*/
public static boolean inMultiWindowMode(int windowingMode) {
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/app/backup/OWNERS b/core/java/android/app/backup/OWNERS
index 9c21e8fe5e45..7e7710b4d550 100644
--- a/core/java/android/app/backup/OWNERS
+++ b/core/java/android/app/backup/OWNERS
@@ -1,9 +1,4 @@
-alsutton@google.com
-anniemeng@google.com
-brufino@google.com
-bryanmawhinney@google.com
-ctate@google.com
-jorlow@google.com
-nathch@google.com
-rthakohov@google.com
+# Bug component: 656484
+
+include platform/frameworks/base/services/backup:/OWNERS
diff --git a/core/java/android/app/time/TimeManager.java b/core/java/android/app/time/TimeManager.java
index 4796d8db3e96..262d244c5b1c 100644
--- a/core/java/android/app/time/TimeManager.java
+++ b/core/java/android/app/time/TimeManager.java
@@ -110,7 +110,7 @@ public final class TimeManager {
@RequiresPermission(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION)
public boolean updateTimeZoneConfiguration(@NonNull TimeZoneConfiguration configuration) {
if (DEBUG) {
- Log.d(TAG, "updateConfiguration called: " + configuration);
+ Log.d(TAG, "updateTimeZoneConfiguration called: " + configuration);
}
try {
return mITimeZoneDetectorService.updateConfiguration(configuration);
diff --git a/core/java/android/app/time/TimeZoneCapabilities.java b/core/java/android/app/time/TimeZoneCapabilities.java
index 7cc67b310f31..a27be96e6e69 100644
--- a/core/java/android/app/time/TimeZoneCapabilities.java
+++ b/core/java/android/app/time/TimeZoneCapabilities.java
@@ -180,8 +180,7 @@ public final class TimeZoneCapabilities implements Parcelable {
public TimeZoneConfiguration tryApplyConfigChanges(
@NonNull TimeZoneConfiguration config,
@NonNull TimeZoneConfiguration requestedChanges) {
- TimeZoneConfiguration.Builder newConfigBuilder =
- new TimeZoneConfiguration.Builder(config);
+ TimeZoneConfiguration.Builder newConfigBuilder = new TimeZoneConfiguration.Builder(config);
if (requestedChanges.hasIsAutoDetectionEnabled()) {
if (this.getConfigureAutoDetectionEnabledCapability() < CAPABILITY_NOT_APPLICABLE) {
return null;
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 475be121b735..c07cd52c581e 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -18,6 +18,7 @@
package android.bluetooth;
import android.Manifest;
+import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -687,6 +688,8 @@ public final class BluetoothAdapter {
private final Map<LeScanCallback, ScanCallback> mLeScanClients;
private static final Map<BluetoothDevice, List<Pair<OnMetadataChangedListener, Executor>>>
sMetadataListeners = new HashMap<>();
+ private final Map<BluetoothConnectionCallback, Executor>
+ mBluetoothConnectionCallbackExecutorMap = new HashMap<>();
/**
* Bluetooth metadata listener. Overrides the default BluetoothMetadataListener
@@ -3573,6 +3576,133 @@ public final class BluetoothAdapter {
@Nullable byte[] value);
}
+ private final IBluetoothConnectionCallback mConnectionCallback =
+ new IBluetoothConnectionCallback.Stub() {
+ @Override
+ public void onDeviceConnected(BluetoothDevice device) {
+ for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry:
+ mBluetoothConnectionCallbackExecutorMap.entrySet()) {
+ BluetoothConnectionCallback callback = callbackExecutorEntry.getKey();
+ Executor executor = callbackExecutorEntry.getValue();
+ executor.execute(() -> callback.onDeviceConnected(device));
+ }
+ }
+
+ @Override
+ public void onDeviceDisconnected(BluetoothDevice device) {
+ for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry:
+ mBluetoothConnectionCallbackExecutorMap.entrySet()) {
+ BluetoothConnectionCallback callback = callbackExecutorEntry.getKey();
+ Executor executor = callbackExecutorEntry.getValue();
+ executor.execute(() -> callback.onDeviceDisconnected(device));
+ }
+ }
+ };
+
+ /**
+ * Registers the BluetoothConnectionCallback to receive callback events when a bluetooth device
+ * (classic or low energy) is connected or disconnected.
+ *
+ * @param executor is the callback executor
+ * @param callback is the connection callback you wish to register
+ * @return true if the callback was registered successfully, false otherwise
+ * @throws IllegalArgumentException if the callback is already registered
+ * @hide
+ */
+ public boolean registerBluetoothConnectionCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull BluetoothConnectionCallback callback) {
+ if (DBG) Log.d(TAG, "registerBluetoothConnectionCallback()");
+ if (callback == null) {
+ return false;
+ }
+
+ // If the callback map is empty, we register the service-to-app callback
+ if (mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null) {
+ if (!mService.registerBluetoothConnectionCallback(mConnectionCallback)) {
+ return false;
+ }
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ mBluetoothConnectionCallbackExecutorMap.remove(callback);
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ }
+
+ // Adds the passed in callback to our map of callbacks to executors
+ synchronized (mBluetoothConnectionCallbackExecutorMap) {
+ if (mBluetoothConnectionCallbackExecutorMap.containsKey(callback)) {
+ throw new IllegalArgumentException("This callback has already been registered");
+ }
+ mBluetoothConnectionCallbackExecutorMap.put(callback, executor);
+ }
+
+ return true;
+ }
+
+ /**
+ * Unregisters the BluetoothConnectionCallback that was previously registered by the application
+ *
+ * @param callback is the connection callback you wish to unregister
+ * @return true if the callback was unregistered successfully, false otherwise
+ * @hide
+ */
+ public boolean unregisterBluetoothConnectionCallback(
+ @NonNull BluetoothConnectionCallback callback) {
+ if (DBG) Log.d(TAG, "unregisterBluetoothConnectionCallback()");
+ if (callback == null) {
+ return false;
+ }
+
+ synchronized (mBluetoothConnectionCallbackExecutorMap) {
+ if (mBluetoothConnectionCallbackExecutorMap.remove(callback) != null) {
+ return false;
+ }
+ }
+
+ if (!mBluetoothConnectionCallbackExecutorMap.isEmpty()) {
+ return true;
+ }
+
+ // If the callback map is empty, we unregister the service-to-app callback
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null) {
+ return mService.unregisterBluetoothConnectionCallback(mConnectionCallback);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+
+ return false;
+ }
+
+ /**
+ * This abstract class is used to implement callbacks for when a bluetooth classic or Bluetooth
+ * Low Energy (BLE) device is either connected or disconnected.
+ *
+ * @hide
+ */
+ public abstract class BluetoothConnectionCallback {
+ /**
+ * Callback triggered when a bluetooth device (classic or BLE) is connected
+ * @param device is the connected bluetooth device
+ */
+ public void onDeviceConnected(BluetoothDevice device) {}
+
+ /**
+ * Callback triggered when a bluetooth device (classic or BLE) is disconnected
+ * @param device is the disconnected bluetooth device
+ */
+ public void onDeviceDisconnected(BluetoothDevice device) {}
+ }
+
/**
* Converts old constant of priority to the new for connection policy
*
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 1d7a54c3021c..46d4f222a6b4 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3416,6 +3416,7 @@ public abstract class Context {
VIBRATOR_SERVICE,
//@hide: STATUS_BAR_SERVICE,
CONNECTIVITY_SERVICE,
+ VCN_MANAGEMENT_SERVICE,
//@hide: IP_MEMORY_STORE_SERVICE,
IPSEC_SERVICE,
VPN_MANAGEMENT_SERVICE,
@@ -3995,6 +3996,16 @@ public abstract class Context {
public static final String CONNECTIVITY_SERVICE = "connectivity";
/**
+ * Use with {@link #getSystemService(String)} to retrieve a {@link android.net.vcn.VcnManager}
+ * for managing Virtual Carrier Networks
+ *
+ * @see #getSystemService(String)
+ * @see android.net.vcn.VcnManager
+ * @hide
+ */
+ public static final String VCN_MANAGEMENT_SERVICE = "vcn_management";
+
+ /**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.net.INetd} for communicating with the network stack
* @hide
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index c0f581717641..946c634e3b41 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1712,6 +1712,15 @@ public abstract class PackageManager {
public static final int DELETE_FAILED_USED_SHARED_LIBRARY = -6;
/**
+ * Deletion failed return code: this is passed to the
+ * {@link IPackageDeleteObserver} if the system failed to delete the package
+ * because there is an app pinned.
+ *
+ * @hide
+ */
+ public static final int DELETE_FAILED_APP_PINNED = -7;
+
+ /**
* Return code that is passed to the {@link IPackageMoveObserver} when the
* package has been successfully moved by the system.
*
@@ -7739,6 +7748,7 @@ public abstract class PackageManager {
case DELETE_FAILED_OWNER_BLOCKED: return "DELETE_FAILED_OWNER_BLOCKED";
case DELETE_FAILED_ABORTED: return "DELETE_FAILED_ABORTED";
case DELETE_FAILED_USED_SHARED_LIBRARY: return "DELETE_FAILED_USED_SHARED_LIBRARY";
+ case DELETE_FAILED_APP_PINNED: return "DELETE_FAILED_APP_PINNED";
default: return Integer.toString(status);
}
}
@@ -7753,6 +7763,7 @@ public abstract class PackageManager {
case DELETE_FAILED_OWNER_BLOCKED: return PackageInstaller.STATUS_FAILURE_BLOCKED;
case DELETE_FAILED_ABORTED: return PackageInstaller.STATUS_FAILURE_ABORTED;
case DELETE_FAILED_USED_SHARED_LIBRARY: return PackageInstaller.STATUS_FAILURE_CONFLICT;
+ case DELETE_FAILED_APP_PINNED: return PackageInstaller.STATUS_FAILURE_BLOCKED;
default: return PackageInstaller.STATUS_FAILURE;
}
}
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/tests/coretests/src/android/app/appsearch/external/app/SearchResultsTest.java b/core/java/android/net/vcn/IVcnManagementService.aidl
index acbf11ae8669..af06906ca2e9 100644
--- a/core/tests/coretests/src/android/app/appsearch/external/app/SearchResultsTest.java
+++ b/core/java/android/net/vcn/IVcnManagementService.aidl
@@ -1,11 +1,11 @@
/*
- * Copyright 2020 The Android Open Source Project
+ * 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
+ * http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,17 +14,10 @@
* limitations under the License.
*/
-package android.app.appsearch;
+package android.net.vcn;
-import static org.testng.Assert.expectThrows;
-
-import org.junit.Test;
-
-public class SearchResultsTest {
- @Test
- public void buildSearchSpecWithoutTermMatchType() {
- expectThrows(RuntimeException.class, () -> new SearchSpec.Builder()
- .setSchemaTypes("testSchemaType")
- .build());
- }
+/**
+ * @hide
+ */
+interface IVcnManagementService {
}
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
new file mode 100644
index 000000000000..d563b0350187
--- /dev/null
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -0,0 +1,48 @@
+/*
+ * 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.vcn;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.annotation.SystemService;
+import android.content.Context;
+
+/**
+ * VcnManager publishes APIs for applications to configure and manage Virtual Carrier Networks
+ *
+ * @hide
+ */
+@SystemService(Context.VCN_MANAGEMENT_SERVICE)
+public final class VcnManager {
+ @NonNull private static final String TAG = VcnManager.class.getSimpleName();
+
+ @NonNull private final Context mContext;
+ @NonNull private final IVcnManagementService mService;
+
+ /**
+ * Construct an instance of VcnManager within an application context.
+ *
+ * @param ctx the application context for this manager
+ * @param service the VcnManagementService binder backing this manager
+ *
+ * @hide
+ */
+ public VcnManager(@NonNull Context ctx, @NonNull IVcnManagementService service) {
+ mContext = requireNonNull(ctx, "missing context");
+ mService = requireNonNull(service, "missing service");
+ }
+}
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/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 11423e6de93e..924fc6d6dca0 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -153,11 +153,10 @@ interface IWindowManager
* WindowlessWindowManager).
*
* @param client an IWindow used for window-level communication (ime, finish draw, etc.).
- * @param windowType used by WM to determine the z-order. This is the same as the window type
- * used in {@link WindowManager.LayoutParams}.
+ * @param shellRootLayer The container's layer. See WindowManager#ShellRootLayer.
* @return a SurfaceControl to add things to.
*/
- SurfaceControl addShellRoot(int displayId, IWindow client, int windowType);
+ SurfaceControl addShellRoot(int displayId, IWindow client, int shellRootLayer);
/**
* Sets the window token sent to accessibility for a particular shell root. The
@@ -165,7 +164,7 @@ interface IWindowManager
*
* @param target The IWindow that accessibility service interfaces with.
*/
- void setShellRootAccessibilityWindow(int displayId, int windowType, IWindow target);
+ void setShellRootAccessibilityWindow(int displayId, int shellRootLayer, IWindow target);
/**
* Like overridePendingAppTransitionMultiThumb, but uses a future to supply the specs. This is
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 3a15aa26e357..d37edaa633a5 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);
@@ -654,6 +656,7 @@ public final class SurfaceControl implements Parcelable {
private final float mFrameScale;
private final boolean mCaptureSecureLayers;
private final boolean mAllowProtected;
+ private final long mUid;
private CaptureArgs(Builder<? extends Builder<?>> builder) {
mPixelFormat = builder.mPixelFormat;
@@ -661,6 +664,7 @@ public final class SurfaceControl implements Parcelable {
mFrameScale = builder.mFrameScale;
mCaptureSecureLayers = builder.mCaptureSecureLayers;
mAllowProtected = builder.mAllowProtected;
+ mUid = builder.mUid;
}
/**
@@ -674,6 +678,7 @@ public final class SurfaceControl implements Parcelable {
private float mFrameScale = 1;
private boolean mCaptureSecureLayers;
private boolean mAllowProtected;
+ private long mUid = -1;
/**
* The desired pixel format of the returned buffer.
@@ -723,6 +728,15 @@ public final class SurfaceControl implements Parcelable {
}
/**
+ * Set the uid of the content that should be screenshot. The code will skip any surfaces
+ * that don't belong to the specified uid.
+ */
+ public T setUid(long uid) {
+ mUid = uid;
+ return getThis();
+ }
+
+ /**
* Each sub class should return itself to allow the builder to chain properly
*/
abstract T getThis();
@@ -2942,6 +2956,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)
@@ -3470,4 +3499,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/SyncRtSurfaceTransactionApplier.java b/core/java/android/view/SyncRtSurfaceTransactionApplier.java
index bce78b572360..b10370aa5d4c 100644
--- a/core/java/android/view/SyncRtSurfaceTransactionApplier.java
+++ b/core/java/android/view/SyncRtSurfaceTransactionApplier.java
@@ -38,6 +38,7 @@ public class SyncRtSurfaceTransactionApplier {
public static final int FLAG_CORNER_RADIUS = 1 << 4;
public static final int FLAG_BACKGROUND_BLUR_RADIUS = 1 << 5;
public static final int FLAG_VISIBILITY = 1 << 6;
+ public static final int FLAG_TRANSACTION = 1 << 7;
private SurfaceControl mTargetSc;
private final ViewRootImpl mTargetViewRootImpl;
@@ -93,6 +94,10 @@ public class SyncRtSurfaceTransactionApplier {
}
public static void applyParams(Transaction t, SurfaceParams params, float[] tmpFloat9) {
+ if ((params.flags & FLAG_TRANSACTION) != 0) {
+ t.merge(params.mergeTransaction);
+ }
+
if ((params.flags & FLAG_MATRIX) != 0) {
t.setMatrix(params.surface, params.matrix, tmpFloat9);
}
@@ -161,6 +166,7 @@ public class SyncRtSurfaceTransactionApplier {
Rect windowCrop;
int layer;
boolean visible;
+ Transaction mergeTransaction;
/**
* @param surface The surface to modify.
@@ -240,17 +246,28 @@ public class SyncRtSurfaceTransactionApplier {
}
/**
+ * @param mergeTransaction The transaction to apply to the surface. Note this is applied
+ * first before all the other properties.
+ * @return this Builder
+ */
+ public Builder withMergeTransaction(Transaction mergeTransaction) {
+ this.mergeTransaction = mergeTransaction;
+ flags |= FLAG_TRANSACTION;
+ return this;
+ }
+
+ /**
* @return a new SurfaceParams instance
*/
public SurfaceParams build() {
return new SurfaceParams(surface, flags, alpha, matrix, windowCrop, layer,
- cornerRadius, backgroundBlurRadius, visible);
+ cornerRadius, backgroundBlurRadius, visible, mergeTransaction);
}
}
private SurfaceParams(SurfaceControl surface, int params, float alpha, Matrix matrix,
- Rect windowCrop, int layer, float cornerRadius, int backgroundBlurRadius,
- boolean visible) {
+ Rect windowCrop, int layer, float cornerRadius,
+ int backgroundBlurRadius, boolean visible, Transaction mergeTransaction) {
this.flags = params;
this.surface = surface;
this.alpha = alpha;
@@ -260,6 +277,7 @@ public class SyncRtSurfaceTransactionApplier {
this.cornerRadius = cornerRadius;
this.backgroundBlurRadius = backgroundBlurRadius;
this.visible = visible;
+ this.mergeTransaction = mergeTransaction;
}
private final int flags;
@@ -286,5 +304,7 @@ public class SyncRtSurfaceTransactionApplier {
public final int layer;
public final boolean visible;
+
+ public final Transaction mergeTransaction;
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 14ba699933f0..0e8cd546a2ae 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.
*/
@@ -3819,6 +3823,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 +3855,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 +9922,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 f85489871730..f7578abfe4f0 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -133,6 +133,22 @@ public interface WindowManager extends ViewManager {
/** @hide */
String INPUT_CONSUMER_RECENTS_ANIMATION = "recents_animation_input_consumer";
+ /** @hide */
+ int SHELL_ROOT_LAYER_DIVIDER = 0;
+ /** @hide */
+ int SHELL_ROOT_LAYER_PIP = 1;
+
+ /**
+ * Declares the layer the shell root will belong to. This is for z-ordering.
+ * @hide
+ */
+ @IntDef(prefix = { "SHELL_ROOT_LAYER_" }, value = {
+ SHELL_ROOT_LAYER_DIVIDER,
+ SHELL_ROOT_LAYER_PIP
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface ShellRootLayer {}
+
/**
* Not set up for a transition.
* @hide
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 093dfb4e196e..62b1b1f8cf53 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -502,7 +502,10 @@ public class BaseInputConnection implements InputConnection {
* The default implementation returns the given amount of text from the
* current cursor position in the buffer.
*/
- public CharSequence getTextBeforeCursor(int length, int flags) {
+ @Nullable
+ public CharSequence getTextBeforeCursor(@IntRange(from = 0) int length, int flags) {
+ if (length < 0) return null;
+
final Editable content = getEditable();
if (content == null) return null;
@@ -558,7 +561,10 @@ public class BaseInputConnection implements InputConnection {
* The default implementation returns the given amount of text from the
* current cursor position in the buffer.
*/
- public CharSequence getTextAfterCursor(int length, int flags) {
+ @Nullable
+ public CharSequence getTextAfterCursor(@IntRange(from = 0) int length, int flags) {
+ if (length < 0) return null;
+
final Editable content = getEditable();
if (content == null) return null;
@@ -594,6 +600,8 @@ public class BaseInputConnection implements InputConnection {
@Nullable
public SurroundingText getSurroundingText(
@IntRange(from = 0) int beforeLength, @IntRange(from = 0) int afterLength, int flags) {
+ if (beforeLength < 0 || afterLength < 0) return null;
+
final Editable content = getEditable();
if (content == null) return null;
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index c7acd298cd20..0fe47b7828d9 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -27,6 +27,8 @@ import android.text.TextUtils;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
+import com.android.internal.util.Preconditions;
+
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -186,13 +188,15 @@ public interface InputConnection {
* the current line, and specifically do not return 0 characters unless
* the cursor is really at the start of the text.</p>
*
- * @param n The expected length of the text.
+ * @param n The expected length of the text. This must be non-negative.
* @param flags Supplies additional options controlling how the text is
* returned. May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
* @return the text before the cursor position; the length of the
* returned text might be less than <var>n</var>.
+ * @throws IllegalArgumentException if {@code n} is negative.
*/
- CharSequence getTextBeforeCursor(int n, int flags);
+ @Nullable
+ CharSequence getTextBeforeCursor(@IntRange(from = 0) int n, int flags);
/**
* Get <var>n</var> characters of text after the current cursor
@@ -228,14 +232,16 @@ public interface InputConnection {
* the current line, and specifically do not return 0 characters unless
* the cursor is really at the end of the text.</p>
*
- * @param n The expected length of the text.
+ * @param n The expected length of the text. This must be non-negative.
* @param flags Supplies additional options controlling how the text is
* returned. May be either 0 or {@link #GET_TEXT_WITH_STYLES}.
*
* @return the text after the cursor position; the length of the
* returned text might be less than <var>n</var>.
+ * @throws IllegalArgumentException if {@code n} is negative.
*/
- CharSequence getTextAfterCursor(int n, int flags);
+ @Nullable
+ CharSequence getTextAfterCursor(@IntRange(from = 0) int n, int flags);
/**
* Gets the selected text, if any.
@@ -307,11 +313,15 @@ public interface InputConnection {
* editor can't comply with the request for some reason, or the application does not implement
* this method. The length of the returned text might be less than the sum of
* <var>beforeLength</var> and <var>afterLength</var> .
+ * @throws IllegalArgumentException if {@code beforeLength} or {@code afterLength} is negative.
*/
@Nullable
default SurroundingText getSurroundingText(
@IntRange(from = 0) int beforeLength, @IntRange(from = 0) int afterLength,
@GetTextType int flags) {
+ Preconditions.checkArgumentNonnegative(beforeLength);
+ Preconditions.checkArgumentNonnegative(afterLength);
+
CharSequence textBeforeCursor = getTextBeforeCursor(beforeLength, flags);
if (textBeforeCursor == null) {
textBeforeCursor = "";
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index ec7fa60a62ba..77956d15e399 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -16,11 +16,14 @@
package android.view.inputmethod;
+import android.annotation.IntRange;
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Handler;
import android.view.KeyEvent;
+import com.android.internal.util.Preconditions;
+
/**
* <p>Wrapper class for proxying calls to another InputConnection. Subclass and have fun!
*/
@@ -74,18 +77,24 @@ public class InputConnectionWrapper implements InputConnection {
/**
* {@inheritDoc}
* @throws NullPointerException if the target is {@code null}.
+ * @throws IllegalArgumentException if {@code length} is negative.
*/
+ @Nullable
@Override
- public CharSequence getTextBeforeCursor(int n, int flags) {
+ public CharSequence getTextBeforeCursor(@IntRange(from = 0) int n, int flags) {
+ Preconditions.checkArgumentNonnegative(n);
return mTarget.getTextBeforeCursor(n, flags);
}
/**
* {@inheritDoc}
* @throws NullPointerException if the target is {@code null}.
+ * @throws IllegalArgumentException if {@code length} is negative.
*/
+ @Nullable
@Override
- public CharSequence getTextAfterCursor(int n, int flags) {
+ public CharSequence getTextAfterCursor(@IntRange(from = 0) int n, int flags) {
+ Preconditions.checkArgumentNonnegative(n);
return mTarget.getTextAfterCursor(n, flags);
}
@@ -101,10 +110,13 @@ public class InputConnectionWrapper implements InputConnection {
/**
* {@inheritDoc}
* @throws NullPointerException if the target is {@code null}.
+ * @throws IllegalArgumentException if {@code beforeLength} or {@code afterLength} is negative.
*/
@Nullable
@Override
public SurroundingText getSurroundingText(int beforeLength, int afterLength, int flags) {
+ Preconditions.checkArgumentNonnegative(beforeLength);
+ Preconditions.checkArgumentNonnegative(afterLength);
return mTarget.getSurroundingText(beforeLength, afterLength, flags);
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index cb4f285c7772..2e3d560ccb56 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -1090,7 +1090,7 @@ public class ChooserActivity extends ResolverActivity implements
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
ViewPager viewPager = findViewById(R.id.profile_pager);
- if (shouldShowTabs() && viewPager.isLayoutRtl()) {
+ if (viewPager.isLayoutRtl()) {
mMultiProfilePagerAdapter.setupViewPager(viewPager);
}
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/view/InputConnectionWrapper.java b/core/java/com/android/internal/view/InputConnectionWrapper.java
index f086dd79758b..e05aa8351681 100644
--- a/core/java/com/android/internal/view/InputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/InputConnectionWrapper.java
@@ -17,6 +17,7 @@
package com.android.internal.view;
import android.annotation.AnyThread;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.inputmethodservice.AbstractInputMethodService;
@@ -106,9 +107,13 @@ public class InputConnectionWrapper implements InputConnection {
return null;
}
+ /**
+ * See {@link InputConnection#getTextAfterCursor(int, int)}.
+ */
+ @Nullable
@AnyThread
- public CharSequence getTextAfterCursor(int length, int flags) {
- if (mCancellationGroup.isCanceled()) {
+ public CharSequence getTextAfterCursor(@IntRange(from = 0) int length, int flags) {
+ if (length < 0 || mCancellationGroup.isCanceled()) {
return null;
}
@@ -122,9 +127,13 @@ public class InputConnectionWrapper implements InputConnection {
return getResultOrNull(value, "getTextAfterCursor()");
}
+ /**
+ * See {@link InputConnection#getTextBeforeCursor(int, int)}.
+ */
+ @Nullable
@AnyThread
- public CharSequence getTextBeforeCursor(int length, int flags) {
- if (mCancellationGroup.isCanceled()) {
+ public CharSequence getTextBeforeCursor(@IntRange(from = 0) int length, int flags) {
+ if (length < 0 || mCancellationGroup.isCanceled()) {
return null;
}
@@ -171,10 +180,12 @@ public class InputConnectionWrapper implements InputConnection {
* not support this protocol.
*/
@AnyThread
- public SurroundingText getSurroundingText(int beforeLength, int afterLength, int flags) {
- if (mCancellationGroup.isCanceled()) {
+ public SurroundingText getSurroundingText(
+ @IntRange(from = 0) int beforeLength, @IntRange(from = 0) int afterLength, int flags) {
+ if (beforeLength < 0 || afterLength < 0 || mCancellationGroup.isCanceled()) {
return null;
}
+
if (isMethodMissing(MissingMethodFlags.GET_SURROUNDING_TEXT)) {
// This method is not implemented.
return null;
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 661bbed8abcb..1123f20c3e7e 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -329,7 +329,7 @@ cc_library_shared {
],
shared_libs: [
// libbinder needs to be shared since it has global state
- // (e.g. gDefaultServiceManager)
+ // (e.g. gDefaultServiceManager)
"libbinder",
"libhidlbase", // libhwbinder is in here
],
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 94151b522c9c..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>
@@ -111,6 +112,7 @@ static struct {
jfieldID frameScale;
jfieldID captureSecureLayers;
jfieldID allowProtected;
+ jfieldID uid;
} gCaptureArgsClassInfo;
static struct {
@@ -371,6 +373,7 @@ static void getCaptureArgs(JNIEnv* env, jobject captureArgsObject, CaptureArgs&
env->GetBooleanField(captureArgsObject, gCaptureArgsClassInfo.captureSecureLayers);
captureArgs.allowProtected =
env->GetBooleanField(captureArgsObject, gCaptureArgsClassInfo.allowProtected);
+ captureArgs.uid = env->GetLongField(captureArgsObject, gCaptureArgsClassInfo.uid);
}
static DisplayCaptureArgs displayCaptureArgsFromObject(JNIEnv* env,
@@ -520,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);
@@ -1624,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",
@@ -1895,6 +1937,7 @@ int register_android_view_SurfaceControl(JNIEnv* env)
GetFieldIDOrDie(env, captureArgsClazz, "mCaptureSecureLayers", "Z");
gCaptureArgsClassInfo.allowProtected =
GetFieldIDOrDie(env, captureArgsClazz, "mAllowProtected", "Z");
+ gCaptureArgsClassInfo.uid = GetFieldIDOrDie(env, captureArgsClazz, "mUid", "J");
jclass displayCaptureArgsClazz =
FindClassOrDie(env, "android/view/SurfaceControl$DisplayCaptureArgs");
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 3248cfedb523..4df7d589d707 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -669,10 +669,6 @@
<!-- For tether entitlement recheck-->
<protected-broadcast
android:name="com.android.server.connectivity.tethering.PROVISIONING_RECHECK_ALARM" />
-
- <!-- Made protected in S (was added in R) -->
- <protected-broadcast android:name="com.android.internal.intent.action.BUGREPORT_REQUESTED" />
-
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
<!-- ====================================================================== -->
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-bn/strings.xml b/core/res/res/values-bn/strings.xml
index bebece81c7f4..3b92f87cfc1c 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/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-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 8c9c674372f8..df447afca7eb 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -314,7 +314,7 @@
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Registres de trucades"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"llegir i editar el registre de trucades del telèfon"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"Telèfon"</string>
- <string name="permgroupdesc_phone" msgid="270048070781478204">"fer i gestionar trucades"</string>
+ <string name="permgroupdesc_phone" msgid="270048070781478204">"fer i gestionar trucades telefòniques"</string>
<string name="permgrouplab_sensors" msgid="9134046949784064495">"Sensors corporals"</string>
<string name="permgroupdesc_sensors" msgid="2610631290633747752">"accedir a les dades del sensor sobre els signes vitals"</string>
<string name="capability_title_canRetrieveWindowContent" msgid="7554282892101587296">"Recuperar el contingut de la finestra"</string>
@@ -343,8 +343,8 @@
<string name="permdesc_uninstall_shortcut" msgid="1924735350988629188">"Permet que l\'aplicació suprimeixi les dreceres de la pantalla d\'inici sense la intervenció de l\'usuari."</string>
<string name="permlab_processOutgoingCalls" msgid="4075056020714266558">"desviació de les trucades sortints"</string>
<string name="permdesc_processOutgoingCalls" msgid="7833149750590606334">"Permet que l\'aplicació vegi el número que s\'està marcant durant una trucada sortint, amb l\'opció de redirigir la trucada a un altre número o bé de cancel·lar-la completament."</string>
- <string name="permlab_answerPhoneCalls" msgid="4131324833663725855">"contestar a trucades"</string>
- <string name="permdesc_answerPhoneCalls" msgid="894386681983116838">"Permet que l\'aplicació contesti a una trucada entrant."</string>
+ <string name="permlab_answerPhoneCalls" msgid="4131324833663725855">"contestar a trucades telefòniques"</string>
+ <string name="permdesc_answerPhoneCalls" msgid="894386681983116838">"Permet que l\'aplicació contesti a una trucada telefònica entrant."</string>
<string name="permlab_receiveSms" msgid="505961632050451881">"recepció de missatges de text (SMS)"</string>
<string name="permdesc_receiveSms" msgid="1797345626687832285">"Permet que l\'aplicació rebi i processi missatges SMS. Això vol dir que l\'aplicació pot controlar o suprimir missatges que s\'han enviat al teu dispositiu sense mostrar-te\'ls."</string>
<string name="permlab_receiveMms" msgid="4000650116674380275">"recepció de missatges de text (MMS)"</string>
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 d417c903b5a5..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>
@@ -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-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-kn/strings.xml b/core/res/res/values-kn/strings.xml
index dc8f237308c5..811973b205d5 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/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-ky/strings.xml b/core/res/res/values-ky/strings.xml
index 451821681f0b..b2e2c1df8226 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -2009,8 +2009,8 @@
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батарея кубаттоого чейин отуруп калышы мүмкүн"</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_charged_notification_summary" product="default" msgid="5544457317418624367">"Телефон жеткиликтүү кубатталды. Функцияны колдоно берсеңиз болот."</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>
<string name="mime_type_folder" msgid="2203536499348787650">"Папка"</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-pa/strings.xml b/core/res/res/values-pa/strings.xml
index 2df3c44f59f8..1dec3f977f00 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/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-te/strings.xml b/core/res/res/values-te/strings.xml
index 1247dc1c874d..2d56fb18d323 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/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/dimens.xml b/core/res/res/values/dimens.xml
index 84e7d42f2ed9..544be54eb785 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -207,9 +207,6 @@
<!-- Default padding for dialogs. -->
<dimen name="dialog_padding">16dp</dimen>
- <!-- The horizontal margin of the content in the notification shade -->
- <dimen name="notification_shade_content_margin_horizontal">16dp</dimen>
-
<!-- The margin on the start of the content view -->
<dimen name="notification_content_margin_start">16dp</dimen>
@@ -861,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 a716875b068f..a294c9d1e537 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2864,7 +2864,6 @@
<java-symbol type="drawable" name="ic_collapse_bundle" />
<java-symbol type="dimen" name="notification_min_content_height" />
<java-symbol type="dimen" name="notification_header_shrink_min_width" />
- <java-symbol type="dimen" name="notification_shade_content_margin_horizontal" />
<java-symbol type="dimen" name="notification_content_margin_start" />
<java-symbol type="dimen" name="notification_content_margin_end" />
<java-symbol type="dimen" name="notification_reply_inset" />
@@ -3554,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" />
@@ -4079,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/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/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/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 24381d937e2f..4c06a2ca3bca 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -101,13 +101,13 @@ public class SystemWindows {
* Adds a view to system-ui window management.
*/
public void addView(View view, WindowManager.LayoutParams attrs, int displayId,
- int windowType) {
+ @WindowManager.ShellRootLayer int shellRootLayer) {
PerDisplay pd = mPerDisplay.get(displayId);
if (pd == null) {
pd = new PerDisplay(displayId);
mPerDisplay.put(displayId, pd);
}
- pd.addView(view, attrs, windowType);
+ pd.addView(view, attrs, shellRootLayer);
}
/**
@@ -149,18 +149,6 @@ public class SystemWindows {
}
/**
- * Adds a root for system-ui window management with no views. Only useful for IME.
- */
- public void addRoot(int displayId, int windowType) {
- PerDisplay pd = mPerDisplay.get(displayId);
- if (pd == null) {
- pd = new PerDisplay(displayId);
- mPerDisplay.put(displayId, pd);
- }
- pd.addRoot(windowType);
- }
-
- /**
* Get the IWindow token for a specific root.
*
* @param windowType A window type from {@link WindowManager}.
@@ -198,8 +186,9 @@ public class SystemWindows {
mDisplayId = displayId;
}
- public void addView(View view, WindowManager.LayoutParams attrs, int windowType) {
- SysUiWindowManager wwm = addRoot(windowType);
+ public void addView(View view, WindowManager.LayoutParams attrs,
+ @WindowManager.ShellRootLayer int shellRootLayer) {
+ SysUiWindowManager wwm = addRoot(shellRootLayer);
if (wwm == null) {
Slog.e(TAG, "Unable to create systemui root");
return;
@@ -213,23 +202,22 @@ public class SystemWindows {
mViewRoots.put(view, viewRoot);
try {
- mWmService.setShellRootAccessibilityWindow(mDisplayId, windowType,
+ mWmService.setShellRootAccessibilityWindow(mDisplayId, shellRootLayer,
viewRoot.getWindowToken());
} catch (RemoteException e) {
Slog.e(TAG, "Error setting accessibility window for " + mDisplayId + ":"
- + windowType, e);
+ + shellRootLayer, e);
}
}
-
- SysUiWindowManager addRoot(int windowType) {
- SysUiWindowManager wwm = mWwms.get(windowType);
+ SysUiWindowManager addRoot(@WindowManager.ShellRootLayer int shellRootLayer) {
+ SysUiWindowManager wwm = mWwms.get(shellRootLayer);
if (wwm != null) {
return wwm;
}
SurfaceControl rootSurface = null;
ContainerWindow win = new ContainerWindow();
try {
- rootSurface = mWmService.addShellRoot(mDisplayId, win, windowType);
+ rootSurface = mWmService.addShellRoot(mDisplayId, win, shellRootLayer);
} catch (RemoteException e) {
}
if (rootSurface == null) {
@@ -238,7 +226,7 @@ public class SystemWindows {
}
Context displayContext = mDisplayController.getDisplayContext(mDisplayId);
wwm = new SysUiWindowManager(mDisplayId, displayContext, rootSurface, win);
- mWwms.put(windowType, wwm);
+ mWwms.put(shellRootLayer, wwm);
return wwm;
}
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..fc523aef9d16 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;
}
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 d223934fcf34..f44ebf3a3a5c 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
@@ -52,9 +52,6 @@ import android.util.Log;
import android.util.Rational;
import android.util.Size;
import android.view.SurfaceControl;
-import android.view.SurfaceControlViewHost;
-import android.view.View;
-import android.view.WindowManager;
import android.window.TaskOrganizer;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
@@ -66,6 +63,7 @@ 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;
@@ -138,6 +136,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
private final Handler mUpdateHandler;
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<>();
@@ -146,8 +146,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
private final Map<IBinder, Configuration> mInitialState = new HashMap<>();
private final Optional<SplitScreen> mSplitScreenOptional;
protected final ShellTaskOrganizer mTaskOrganizer;
- private SurfaceControlViewHost mPipViewHost;
- private SurfaceControl mPipMenuSurface;
// These callbacks are called on the update thread
private final PipAnimationController.PipAnimationCallback mPipAnimationCallback =
@@ -267,15 +265,19 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
public PipTaskOrganizer(Context context, @NonNull PipBoundsState pipBoundsState,
@NonNull PipBoundsHandler boundsHandler,
+ PipMenuActivityController menuActivityController,
@NonNull PipSurfaceTransactionHelper surfaceTransactionHelper,
Optional<SplitScreen> splitScreenOptional,
@NonNull DisplayController displayController,
@NonNull PipUiEventLogger pipUiEventLogger,
- @NonNull ShellTaskOrganizer shellTaskOrganizer) {
+ @NonNull ShellTaskOrganizer shellTaskOrganizer,
+ @NonNull SystemWindows systemWindows) {
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;
@@ -640,60 +642,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
}
/**
- * Setup the ViewHost and attach the provided menu view to the ViewHost.
- * @return The input token belonging to the PipMenuView.
- */
- public IBinder attachPipMenuViewHost(View menuView, WindowManager.LayoutParams lp) {
- if (mPipMenuSurface != null) {
- Log.e(TAG, "PIP Menu View already created and attached.");
- return null;
- }
-
- if (mLeash == null) {
- Log.e(TAG, "PiP Leash is not yet ready.");
- return null;
- }
-
- if (Looper.getMainLooper() != Looper.myLooper()) {
- throw new RuntimeException("PipMenuView needs to be attached on the main thread.");
- }
- final Context context = menuView.getContext();
- mPipViewHost = new SurfaceControlViewHost(context, context.getDisplay(),
- (android.os.Binder) null);
- mPipMenuSurface = mPipViewHost.getSurfacePackage().getSurfaceControl();
- SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
- transaction.reparent(mPipMenuSurface, mLeash);
- transaction.show(mPipMenuSurface);
- transaction.setRelativeLayer(mPipMenuSurface, mLeash, 1);
- transaction.apply();
- mPipViewHost.setView(menuView, lp);
-
- return mPipViewHost.getSurfacePackage().getInputToken();
- }
-
-
- /**
- * Releases the PIP Menu's View host, remove it from PIP task surface.
- */
- public void detachPipMenuViewHost() {
- if (mPipMenuSurface != null) {
- SurfaceControl.Transaction transaction = new SurfaceControl.Transaction();
- transaction.remove(mPipMenuSurface);
- transaction.apply();
- mPipMenuSurface = null;
- mPipViewHost = null;
- }
- }
-
- /**
- * Return whether the PiP Menu has been attached to the leash yet.
- */
- public boolean isPipMenuViewHostAttached() {
- return mPipViewHost != null;
- }
-
-
- /**
* Note that dismissing PiP is now originated from SystemUI, see {@link #exitPip(int)}.
* Meanwhile this callback is invoked whenever the task is removed. For instance:
* - as a result of removeRootTasksInWindowingModes from WM
@@ -998,7 +946,13 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
mSurfaceTransactionHelper
.crop(tx, mLeash, destinationBounds)
.round(tx, mLeash, mState.isInPip());
- tx.apply();
+ if (mMenuActivityController.isMenuVisible()) {
+ runOnMainHandler(() -> {
+ mMenuActivityController.resizePipMenu(mLeash, tx, destinationBounds);
+ });
+ } else {
+ tx.apply();
+ }
}
private void userResizePip(Rect startBounds, Rect destinationBounds) {
@@ -1019,7 +973,13 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
mSurfaceTransactionHelper.scale(tx, mLeash, startBounds, destinationBounds);
- tx.apply();
+ if (mMenuActivityController.isMenuVisible()) {
+ runOnMainHandler(() -> {
+ mMenuActivityController.movePipMenu(mLeash, tx, destinationBounds);
+ });
+ } else {
+ tx.apply();
+ }
}
private void finishResize(SurfaceControl.Transaction tx, Rect destinationBounds,
@@ -1034,6 +994,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
removePipImmediately();
return;
} else if (isInPipDirection(direction) && type == ANIM_TYPE_ALPHA) {
+ // TODO: Synchronize this correctly in #applyEnterPipSyncTransaction
+ runOnMainHandler(() -> {
+ mMenuActivityController.movePipMenu(null, null, destinationBounds);
+ mMenuActivityController.updateMenuBounds(destinationBounds);
+ });
return;
}
@@ -1041,10 +1006,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
prepareFinishResizeTransaction(destinationBounds, direction, tx, wct);
applyFinishBoundsResize(wct, direction);
runOnMainHandler(() -> {
- if (mPipViewHost != null) {
- mPipViewHost.relayout(PipMenuActivityController.getPipMenuLayoutParams(
- destinationBounds.width(), destinationBounds.height()));
- }
+ 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 a87fa20a7f11..a5252654aa23 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
@@ -18,25 +18,37 @@ package com.android.wm.shell.pip.phone;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
-
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
+import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+import static android.view.WindowManager.SHELL_ROOT_LAYER_PIP;
+
+import android.annotation.Nullable;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.RemoteAction;
import android.content.Context;
import android.content.pm.ParceledListSlice;
+import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.os.Debug;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.MotionEvent;
+import android.view.SurfaceControl;
+import android.view.SyncRtSurfaceTransactionApplier;
+import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import com.android.wm.shell.common.SystemWindows;
import com.android.wm.shell.pip.PipMediaController;
import com.android.wm.shell.pip.PipMediaController.ActionListener;
-import com.android.wm.shell.pip.PipTaskOrganizer;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -51,6 +63,7 @@ import java.util.List;
public class PipMenuActivityController {
private static final String TAG = "PipMenuActController";
+ private static final String MENU_WINDOW_TITLE = "PipMenuView";
private static final boolean DEBUG = false;
public static final int MENU_STATE_NONE = 0;
@@ -85,13 +98,18 @@ public class PipMenuActivityController {
void onPipShowMenu();
}
- private Context mContext;
- private PipTaskOrganizer mPipTaskOrganizer;
- private PipMediaController mMediaController;
+ private final Matrix mMoveTransform = new Matrix();
+ private final Rect mTmpSourceBounds = new Rect();
+ private final RectF mTmpSourceRectF = new RectF();
+ private final RectF mTmpDestinationRectF = new RectF();
+ private final Context mContext;
+ private final PipMediaController mMediaController;
- private ArrayList<Listener> mListeners = new ArrayList<>();
+ private final ArrayList<Listener> mListeners = new ArrayList<>();
+ private final SystemWindows mSystemWindows;
private ParceledListSlice<RemoteAction> mAppActions;
private ParceledListSlice<RemoteAction> mMediaActions;
+ private SyncRtSurfaceTransactionApplier mApplier;
private int mMenuState;
private PipMenuView mPipMenuView;
@@ -106,10 +124,10 @@ public class PipMenuActivityController {
};
public PipMenuActivityController(Context context,
- PipMediaController mediaController, PipTaskOrganizer pipTaskOrganizer) {
+ PipMediaController mediaController, SystemWindows systemWindows) {
mContext = context;
mMediaController = mediaController;
- mPipTaskOrganizer = pipTaskOrganizer;
+ mSystemWindows = systemWindows;
}
public boolean isMenuVisible() {
@@ -122,9 +140,7 @@ public class PipMenuActivityController {
public void onActivityUnpinned() {
hideMenu();
- mPipTaskOrganizer.detachPipMenuViewHost();
- mPipMenuView = null;
- mPipMenuInputToken = null;
+ detachPipMenuView();
}
public void onPinnedStackAnimationEnded() {
@@ -136,15 +152,39 @@ public class PipMenuActivityController {
private void attachPipMenuView() {
if (mPipMenuView == null) {
mPipMenuView = new PipMenuView(mContext, this);
-
}
- // If we haven't gotten the input toekn, that means we haven't had a success attempt
- // yet at attaching the PipMenuView
- if (mPipMenuInputToken == null) {
- mPipMenuInputToken = mPipTaskOrganizer.attachPipMenuViewHost(mPipMenuView,
- getPipMenuLayoutParams(0, 0));
+ mSystemWindows.addView(mPipMenuView, getPipMenuLayoutParams(0, 0), 0, SHELL_ROOT_LAYER_PIP);
+ }
+
+ private void detachPipMenuView() {
+ if (mPipMenuView == null) {
+ return;
}
+
+ mApplier = null;
+ mSystemWindows.removeView(mPipMenuView);
+ mPipMenuView = null;
+ mPipMenuInputToken = null;
+ }
+
+ /**
+ * Updates the layout parameters of the menu.
+ * @param destinationBounds New Menu bounds.
+ */
+ public void updateMenuBounds(Rect destinationBounds) {
+ mSystemWindows.updateViewLayout(mPipMenuView,
+ getPipMenuLayoutParams(destinationBounds.width(), destinationBounds.height()));
+ }
+
+ /**
+ * Tries to grab a surface control from {@link PipMenuView}. If this isn't available for some
+ * reason (ie. the window isn't ready yet, thus {@link android.view.ViewRootImpl} is
+ * {@code null}), it will get the leash that the WindowlessWM has assigned to it.
+ */
+ public SurfaceControl getSurfaceControl() {
+ SurfaceControl sf = mPipMenuView.getWindowSurfaceControl();
+ return sf != null ? sf : mSystemWindows.getViewSurface(mPipMenuView);
}
/**
@@ -190,16 +230,95 @@ public class PipMenuActivityController {
+ " callers=\n" + Debug.getCallers(5, " "));
}
- if (!mPipTaskOrganizer.isPipMenuViewHostAttached()) {
- Log.d(TAG, "PipMenu has not been attached yet. Attaching now at showMenuInternal().");
- attachPipMenuView();
- }
+ maybeCreateSyncApplier();
mPipMenuView.showMenu(menuState, stackBounds, allowMenuTimeout, willResizeMenu, withDelay,
showResizeHandle);
}
/**
+ * Move the PiP menu, which does a translation and possibly a scale transformation.
+ */
+ public void movePipMenu(@Nullable SurfaceControl pipLeash,
+ @Nullable SurfaceControl.Transaction t,
+ Rect destinationBounds) {
+ if (destinationBounds.isEmpty()) {
+ return;
+ }
+
+ if (!maybeCreateSyncApplier()) {
+ return;
+ }
+
+ // If there is no pip leash supplied, that means the PiP leash is already finalized
+ // resizing and the PiP menu is also resized. We then want to do a scale from the current
+ // new menu bounds.
+ if (pipLeash != null && t != null) {
+ mPipMenuView.getBoundsOnScreen(mTmpSourceBounds);
+ } else {
+ mTmpSourceBounds.set(0, 0, destinationBounds.width(), destinationBounds.height());
+ }
+
+ mTmpSourceRectF.set(mTmpSourceBounds);
+ mTmpDestinationRectF.set(destinationBounds);
+ mMoveTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
+ SurfaceControl surfaceControl = getSurfaceControl();
+ SurfaceParams params = new SurfaceParams.Builder(surfaceControl)
+ .withMatrix(mMoveTransform)
+ .build();
+ if (pipLeash != null && t != null) {
+ SurfaceParams pipParams = new SurfaceParams.Builder(pipLeash)
+ .withMergeTransaction(t)
+ .build();
+ mApplier.scheduleApply(params, pipParams);
+ } else {
+ mApplier.scheduleApply(params);
+ }
+ }
+
+ /**
+ * Does an immediate window crop of the PiP menu.
+ */
+ public void resizePipMenu(@Nullable SurfaceControl pipLeash,
+ @Nullable SurfaceControl.Transaction t,
+ Rect destinationBounds) {
+ if (destinationBounds.isEmpty()) {
+ return;
+ }
+
+ if (!maybeCreateSyncApplier()) {
+ return;
+ }
+
+ SurfaceControl surfaceControl = getSurfaceControl();
+ SurfaceParams params = new SurfaceParams.Builder(surfaceControl)
+ .withWindowCrop(destinationBounds)
+ .build();
+ if (pipLeash != null && t != null) {
+ SurfaceParams pipParams = new SurfaceParams.Builder(pipLeash)
+ .withMergeTransaction(t)
+ .build();
+ mApplier.scheduleApply(params, pipParams);
+ } else {
+ mApplier.scheduleApply(params);
+ }
+ }
+
+ private boolean maybeCreateSyncApplier() {
+ if (mPipMenuView == null) {
+ Log.v(TAG, "Not going to move PiP since the menu is not created.");
+ return false;
+ }
+
+ if (mApplier == null) {
+ mApplier = new SyncRtSurfaceTransactionApplier(mPipMenuView);
+ mPipMenuInputToken = mPipMenuView.getViewRootImpl().getInputToken();
+ }
+
+ return mApplier != null;
+ }
+
+ /**
* Pokes the menu, indicating that the user is interacting with it.
*/
public void pokeMenu() {
@@ -296,8 +415,13 @@ public class PipMenuActivityController {
* @param height the PIP stack height.
*/
public static WindowManager.LayoutParams getPipMenuLayoutParams(int width, int height) {
- return new WindowManager.LayoutParams(width, height,
- WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSLUCENT);
+ final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(width, height,
+ TYPE_APPLICATION_OVERLAY,
+ FLAG_WATCH_OUTSIDE_TOUCH | FLAG_SPLIT_TOUCH | FLAG_SLIPPERY | FLAG_NOT_TOUCHABLE,
+ PixelFormat.TRANSLUCENT);
+
+ lp.setTitle(MENU_WINDOW_TITLE);
+ return lp;
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
index 3e06ec44989e..6e3cd8e9aa09 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
@@ -32,6 +32,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
+import android.annotation.Nullable;
import android.app.PendingIntent.CanceledException;
import android.app.RemoteAction;
import android.content.ComponentName;
@@ -50,8 +51,10 @@ import android.util.Pair;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
+import android.view.SurfaceControl;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewRootImpl;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
@@ -268,10 +271,12 @@ public class PipMenuView extends FrameLayout {
return;
}
mMenuContainerAnimator.setStartDelay(MENU_SHOW_ON_EXPAND_START_DELAY);
+ setVisibility(VISIBLE);
mMenuContainerAnimator.start();
});
} else {
notifyMenuStateChange(menuState, resizeMenuOnShow, null);
+ setVisibility(VISIBLE);
mMenuContainerAnimator.start();
}
} else {
@@ -283,6 +288,18 @@ public class PipMenuView extends FrameLayout {
}
}
+ @Nullable SurfaceControl getWindowSurfaceControl() {
+ final ViewRootImpl root = getViewRootImpl();
+ if (root == null) {
+ return null;
+ }
+ final SurfaceControl out = root.getSurfaceControl();
+ if (out != null && out.isValid()) {
+ return out;
+ }
+ return null;
+ }
+
/**
* Different from {@link #hideMenu()}, this function does not try to finish this menu activity
* and instead, it fades out the controls by setting the alpha to 0 directly without menu
@@ -338,6 +355,7 @@ public class PipMenuView extends FrameLayout {
mMenuContainerAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
+ setVisibility(GONE);
if (animationFinishedRunnable != null) {
animationFinishedRunnable.run();
}
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/DividerWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java
index 0b4e17c27398..f2becc99eae8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/DividerWindowManager.java
@@ -25,6 +25,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+import static android.view.WindowManager.SHELL_ROOT_LAYER_DIVIDER;
import android.graphics.PixelFormat;
import android.graphics.Region;
@@ -63,7 +64,7 @@ final class DividerWindowManager {
view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
- mSystemWindows.addView(view, mLp, displayId, TYPE_DOCK_DIVIDER);
+ mSystemWindows.addView(view, mLp, displayId, SHELL_ROOT_LAYER_DIVIDER);
mView = view;
}
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 1d10a84c53b9..ccc679797472 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,6 +41,8 @@ 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;
import org.junit.Before;
@@ -62,10 +64,12 @@ public class PipTaskOrganizerTest extends PipTestCase {
@Mock private DisplayController mMockdDisplayController;
@Mock private PipBoundsHandler mMockPipBoundsHandler;
+ @Mock private PipMenuActivityController mMenuActivityController;
@Mock private PipSurfaceTransactionHelper mMockPipSurfaceTransactionHelper;
@Mock private PipUiEventLogger mMockPipUiEventLogger;
@Mock private Optional<SplitScreen> mMockOptionalSplitScreen;
@Mock private ShellTaskOrganizer mMockShellTaskOrganizer;
+ @Mock private SystemWindows mSystemWindows;
private PipBoundsState mPipBoundsState;
private ComponentName mComponent1;
@@ -78,8 +82,9 @@ public class PipTaskOrganizerTest extends PipTestCase {
mComponent2 = new ComponentName(mContext, "component2");
mPipBoundsState = new PipBoundsState();
mSpiedPipTaskOrganizer = spy(new PipTaskOrganizer(mContext, mPipBoundsState,
- mMockPipBoundsHandler, mMockPipSurfaceTransactionHelper, mMockOptionalSplitScreen,
- mMockdDisplayController, mMockPipUiEventLogger, mMockShellTaskOrganizer));
+ mMockPipBoundsHandler, mMenuActivityController, mMockPipSurfaceTransactionHelper,
+ mMockOptionalSplitScreen, mMockdDisplayController, mMockPipUiEventLogger,
+ mMockShellTaskOrganizer, mSystemWindows));
preparePipTaskOrg();
}
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index 79b861136b64..610bffe13eae 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -17,6 +17,7 @@
package android.media;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
@@ -58,6 +59,7 @@ public abstract class Image implements AutoCloseable {
* @hide
*/
@UnsupportedAppUsage
+ @TestApi
protected Image() {
}
@@ -387,6 +389,7 @@ public abstract class Image implements AutoCloseable {
* @hide
*/
@UnsupportedAppUsage
+ @TestApi
protected Plane() {
}
diff --git a/media/java/android/media/MediaTranscodeManager.java b/media/java/android/media/MediaTranscodeManager.java
index e5163ce51a90..39511a573da2 100644
--- a/media/java/android/media/MediaTranscodeManager.java
+++ b/media/java/android/media/MediaTranscodeManager.java
@@ -489,8 +489,8 @@ public final class MediaTranscodeManager {
mContext = context;
mContentResolver = mContext.getContentResolver();
mPackageName = mContext.getPackageName();
- mPid = Os.getuid();
- mUid = Os.getpid();
+ mUid = Os.getuid();
+ mPid = Os.getpid();
IMediaTranscodingService service = getService(false /*retry*/);
mTranscodingClient = registerClient(service);
}
@@ -615,7 +615,7 @@ public final class MediaTranscodeManager {
}
/* Writes the TranscodingRequest to a parcel. */
- private TranscodingRequestParcel writeToParcel() {
+ private TranscodingRequestParcel writeToParcel(@NonNull Context context) {
TranscodingRequestParcel parcel = new TranscodingRequestParcel();
// TODO(hkuang): Implement all the fields here to pass to service.
parcel.priority = mPriority;
@@ -624,6 +624,8 @@ public final class MediaTranscodeManager {
parcel.destinationFilePath = mDestinationUri.toString();
parcel.clientUid = mClientUid;
parcel.clientPid = mClientPid;
+ parcel.clientPackageName = mClientUid < 0 ? context.getPackageName() :
+ context.getPackageManager().getNameForUid(mClientUid);
parcel.requestedVideoTrackFormat = convertToVideoTrackFormat(mVideoTrackFormat);
if (mTestConfig != null) {
parcel.isForTesting = true;
@@ -1203,7 +1205,8 @@ public final class MediaTranscodeManager {
try {
// Submits the request to MediaTranscoding service.
TranscodingSessionParcel sessionParcel = new TranscodingSessionParcel();
- if (!client.submitRequest(mRequest.writeToParcel(), sessionParcel)) {
+ if (!client.submitRequest(mRequest.writeToParcel(mManager.mContext),
+ sessionParcel)) {
mHasRetried = true;
throw new UnsupportedOperationException("Failed to enqueue request");
}
@@ -1383,7 +1386,7 @@ public final class MediaTranscodeManager {
Objects.requireNonNull(listener, "listener must not be null");
// Converts the request to TranscodingRequestParcel.
- TranscodingRequestParcel requestParcel = transcodingRequest.writeToParcel();
+ TranscodingRequestParcel requestParcel = transcodingRequest.writeToParcel(mContext);
Log.i(TAG, "Getting transcoding request " + transcodingRequest.getSourceUri());
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/DynamicSystemInstallationService/res/values/strings.xml b/packages/DynamicSystemInstallationService/res/values/strings.xml
index 719fc73bd225..bfeef0aa8c7b 100644
--- a/packages/DynamicSystemInstallationService/res/values/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values/strings.xml
@@ -37,6 +37,9 @@
<string name="toast_dynsystem_discarded">Discarded dynamic system</string>
<!-- Toast when we fail to launch into Dynamic System [CHAR LIMIT=128] -->
<string name="toast_failed_to_reboot_to_dynsystem">Can\u2019t restart or load dynamic system</string>
+ <!-- Toast when we fail to disable Dynamic System [CHAR LIMIT=128] -->
+ <string name="toast_failed_to_disable_dynsystem">Failed to disable dynamic system</string>
+
<!-- URL of Dynamic System Key Revocation List [DO NOT TRANSLATE] -->
<string name="key_revocation_list_url" translatable="false">https://dl.google.com/developers/android/gsi/gsi-keyblacklist.json</string>
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index 12505bc55b15..ac2758011816 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -375,8 +375,17 @@ public class DynamicSystemInstallationService extends Service
return;
}
- // Per current design, we don't have disable() API. AOT is disabled on next reboot.
- // TODO: Use better status query when b/125079548 is done.
+ if (!mDynSystem.setEnable(/* enable = */ false, /* oneShot = */ false)) {
+ Log.e(TAG, "Failed to disable DynamicSystem.");
+
+ // Dismiss status bar and show a toast.
+ sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+ Toast.makeText(this,
+ getString(R.string.toast_failed_to_disable_dynsystem),
+ Toast.LENGTH_LONG).show();
+ return;
+ }
+
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (powerManager != null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
index bc40903d88e4..f9bb90e9616a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
@@ -24,6 +24,7 @@ import static android.os.BatteryManager.EXTRA_LEVEL;
import static android.os.BatteryManager.EXTRA_MAX_CHARGING_CURRENT;
import static android.os.BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE;
import static android.os.BatteryManager.EXTRA_PLUGGED;
+import static android.os.BatteryManager.EXTRA_PRESENT;
import static android.os.BatteryManager.EXTRA_STATUS;
import android.content.Context;
@@ -49,14 +50,16 @@ public class BatteryStatus {
public final int plugged;
public final int health;
public final int maxChargingWattage;
+ public final boolean present;
public BatteryStatus(int status, int level, int plugged, int health,
- int maxChargingWattage) {
+ int maxChargingWattage, boolean present) {
this.status = status;
this.level = level;
this.plugged = plugged;
this.health = health;
this.maxChargingWattage = maxChargingWattage;
+ this.present = present;
}
public BatteryStatus(Intent batteryChangedIntent) {
@@ -64,6 +67,7 @@ public class BatteryStatus {
plugged = batteryChangedIntent.getIntExtra(EXTRA_PLUGGED, 0);
level = batteryChangedIntent.getIntExtra(EXTRA_LEVEL, 0);
health = batteryChangedIntent.getIntExtra(EXTRA_HEALTH, BATTERY_HEALTH_UNKNOWN);
+ present = batteryChangedIntent.getBooleanExtra(EXTRA_PRESENT, true);
final int maxChargingMicroAmp = batteryChangedIntent.getIntExtra(EXTRA_MAX_CHARGING_CURRENT,
-1);
diff --git a/packages/SettingsProvider/src/android/provider/settings/OWNERS b/packages/SettingsProvider/src/android/provider/settings/OWNERS
index 541dd8787545..7e7710b4d550 100644
--- a/packages/SettingsProvider/src/android/provider/settings/OWNERS
+++ b/packages/SettingsProvider/src/android/provider/settings/OWNERS
@@ -1,5 +1,4 @@
-# Please reach out to Android B&R when making Settings backup changes
-alsutton@google.com
-nathch@google.com
-rthakohov@google.com
+# Bug component: 656484
+
+include platform/frameworks/base/services/backup:/OWNERS
diff --git a/packages/SettingsProvider/test/src/android/provider/OWNERS b/packages/SettingsProvider/test/src/android/provider/OWNERS
index f3241ea9d1f9..7e7710b4d550 100644
--- a/packages/SettingsProvider/test/src/android/provider/OWNERS
+++ b/packages/SettingsProvider/test/src/android/provider/OWNERS
@@ -1,4 +1,4 @@
-per-file * = *
+# Bug component: 656484
+
+include platform/frameworks/base/services/backup:/OWNERS
-# Please reach out to the Android B&R team for settings backup changes
-per-file SettingsBackupTest.java = alsutton@google.com, nathch@google.com, rthakohov@google.com
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/drawable/ic_battery_unknown.xml b/packages/SystemUI/res/drawable/ic_battery_unknown.xml
new file mode 100644
index 000000000000..8b2ba12fe0be
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_battery_unknown.xml
@@ -0,0 +1,24 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="12dp"
+ android:height="24dp"
+ android:viewportWidth="12.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M10.404,2.4L8.4,2.4L8.4,0L3.6,0L3.6,2.4L1.596,2.4C0.72,2.4 0,3.12 0,3.996L0,22.392C0,23.28 0.72,24 1.596,24L10.392,24C11.28,24 12,23.28 12,22.404L12,3.996C12,3.12 11.28,2.4 10.404,2.4ZM7.14,19.14L4.86,19.14L4.86,16.86L7.14,16.86L7.14,19.14ZM8.76,12.828C8.76,12.828 8.304,13.332 7.956,13.68C7.38,14.256 6.96,15.06 6.96,15.6L5.04,15.6C5.04,14.604 5.592,13.776 6.156,13.2L7.272,12.072C7.596,11.748 7.8,11.292 7.8,10.8C7.8,9.804 6.996,9 6,9C5.004,9 4.2,9.804 4.2,10.8L2.4,10.8C2.4,8.808 4.008,7.2 6,7.2C7.992,7.2 9.6,8.808 9.6,10.8C9.6,11.592 9.276,12.312 8.76,12.828L8.76,12.828Z"
+ android:fillColor="#ffffff" />
+</vector>
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 0a33d5e4429b..b2c968c0292d 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -24,7 +24,7 @@
android:clipChildren="false"
android:clipToPadding="true"
android:orientation="vertical"
- android:paddingStart="@*android:dimen/notification_content_margin_start">
+ android:paddingStart="@dimen/notification_shade_content_margin_horizontal">
<!-- Package Info -->
<LinearLayout
@@ -120,7 +120,7 @@ asked for it -->
android:id="@+id/inline_controls"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingEnd="@*android:dimen/notification_content_margin_end"
+ android:paddingEnd="@dimen/notification_shade_content_margin_horizontal"
android:layout_marginTop="@dimen/notification_guts_option_vertical_padding"
android:clipChildren="false"
android:clipToPadding="false"
diff --git a/packages/SystemUI/res/layout/partial_conversation_info.xml b/packages/SystemUI/res/layout/partial_conversation_info.xml
index af66f8ba4cd6..9ed3f92a7d74 100644
--- a/packages/SystemUI/res/layout/partial_conversation_info.xml
+++ b/packages/SystemUI/res/layout/partial_conversation_info.xml
@@ -24,7 +24,7 @@
android:clipChildren="false"
android:clipToPadding="true"
android:orientation="vertical"
- android:paddingStart="@*android:dimen/notification_content_margin_start">
+ android:paddingStart="@dimen/notification_shade_content_margin_horizontal">
<!-- Package Info -->
<LinearLayout
@@ -93,7 +93,7 @@
android:id="@+id/inline_controls"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingEnd="@*android:dimen/notification_content_margin_end"
+ android:paddingEnd="@dimen/notification_shade_content_margin_horizontal"
android:layout_marginTop="@dimen/notification_guts_option_vertical_padding"
android:clipChildren="false"
android:clipToPadding="false"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 57ce0b5da7c1..1a72fc231815 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -568,4 +568,9 @@
<!-- The duraction of the hide animation for the volume dialog in milliseconds -->
<integer name="config_dialogHideAnimationDurationMs">250</integer>
+
+ <!-- Whether or not to show a notification for an unknown battery state -->
+ <bool name="config_showNotificationForUnknownBatteryState">false</bool>
+ <!-- content URL in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false -->
+ <string translatable="false" name="config_batteryStateUnknownUrl"></string>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 1ab776b2a0a8..17dc4004ae9b 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -623,6 +623,9 @@
@dimen/notification_divider_height
</dimen>
+ <!-- The horizontal margin of the content in the notification shade -->
+ <dimen name="notification_shade_content_margin_horizontal">16dp</dimen>
+
<!-- The top margin for the notification children container in its non-expanded form. -->
<dimen name="notification_children_container_margin_top">
@*android:dimen/notification_content_margin_top
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 2be89c1dff63..d5c98233b952 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -439,6 +439,8 @@
<string name="accessibility_battery_three_bars">Battery three bars.</string>
<!-- Content description of the battery when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_battery_full">Battery full.</string>
+ <!-- Content description of the battery when battery state is unknown for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_battery_unknown">Battery percentage unknown.</string>
<!-- Content description of the phone signal when no signal for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_no_phone">No phone.</string>
@@ -2862,4 +2864,10 @@
<!-- Status for conversation without interaction data [CHAR LIMIT=120] -->
<string name="basic_status" translatable="false">Open conversation</string>
+ <!-- Title to display in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false
+ [CHAR LIMIT=NONE] -->
+ <string name="battery_state_unknown_notification_title">Problem reading your battery meter</string>
+ <!-- Text to display in a notification when ACTION_BATTERY_CHANGED.EXTRA_PRESENT field is false
+ [CHAR LIMIT=NONE] -->
+ <string name="battery_state_unknown_notification_text">Tap for more information</string>
</resources>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 9beb7db40096..0e6bc24b02d6 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>();
@@ -1581,7 +1583,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 +1594,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) {
@@ -1717,7 +1721,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
// Take a guess at initial SIM state, battery status and PLMN until we get an update
- mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0, 0);
+ mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, 100, 0, 0, 0, true);
// Watch for interesting updates
final IntentFilter filter = new IntentFilter();
@@ -1853,7 +1857,7 @@ 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, mAuthController.isUdfpsEnrolled() ? 1 : 0);
}
private final UserSwitchObserver mUserSwitchObserver = new UserSwitchObserver() {
@@ -2621,6 +2625,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
final boolean wasPluggedIn = old.isPluggedIn();
final boolean stateChangedWhilePluggedIn = wasPluggedIn && nowPluggedIn
&& (old.status != current.status);
+ final boolean nowPresent = current.present;
+ final boolean wasPresent = old.present;
// change in plug state is always interesting
if (wasPluggedIn != nowPluggedIn || stateChangedWhilePluggedIn) {
@@ -2637,6 +2643,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
return true;
}
+ // Battery either showed up or disappeared
+ if (wasPresent != nowPresent) {
+ return true;
+ }
+
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 521bb8d58c2b..caaee5fd3f37 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -31,6 +31,7 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;
@@ -91,12 +92,15 @@ public class BatteryMeterView extends LinearLayout implements
private int mTextColor;
private int mLevel;
private int mShowPercentMode = MODE_DEFAULT;
- private boolean mForceShowPercent;
private boolean mShowPercentAvailable;
// Some places may need to show the battery conditionally, and not obey the tuner
private boolean mIgnoreTunerUpdates;
private boolean mIsSubscribedForTunerUpdates;
private boolean mCharging;
+ // Error state where we know nothing about the current battery state
+ private boolean mBatteryStateUnknown;
+ // Lazily-loaded since this is expected to be a rare-if-ever state
+ private Drawable mUnknownStateDrawable;
private DualToneHandler mDualToneHandler;
private int mUser;
@@ -341,6 +345,11 @@ public class BatteryMeterView extends LinearLayout implements
}
private void updatePercentText() {
+ if (mBatteryStateUnknown) {
+ setContentDescription(getContext().getString(R.string.accessibility_battery_unknown));
+ return;
+ }
+
if (mBatteryController == null) {
return;
}
@@ -381,9 +390,13 @@ public class BatteryMeterView extends LinearLayout implements
final boolean systemSetting = 0 != whitelistIpcs(() -> Settings.System
.getIntForUser(getContext().getContentResolver(),
SHOW_BATTERY_PERCENT, 0, mUser));
+ boolean shouldShow =
+ (mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF)
+ || mShowPercentMode == MODE_ON
+ || mShowPercentMode == MODE_ESTIMATE;
+ shouldShow = shouldShow && !mBatteryStateUnknown;
- if ((mShowPercentAvailable && systemSetting && mShowPercentMode != MODE_OFF)
- || mShowPercentMode == MODE_ON || mShowPercentMode == MODE_ESTIMATE) {
+ if (shouldShow) {
if (!showing) {
mBatteryPercentView = loadPercentView();
if (mPercentageStyleId != 0) { // Only set if specified as attribute
@@ -409,6 +422,32 @@ public class BatteryMeterView extends LinearLayout implements
scaleBatteryMeterViews();
}
+ private Drawable getUnknownStateDrawable() {
+ if (mUnknownStateDrawable == null) {
+ mUnknownStateDrawable = mContext.getDrawable(R.drawable.ic_battery_unknown);
+ mUnknownStateDrawable.setTint(mTextColor);
+ }
+
+ return mUnknownStateDrawable;
+ }
+
+ @Override
+ public void onBatteryUnknownStateChanged(boolean isUnknown) {
+ if (mBatteryStateUnknown == isUnknown) {
+ return;
+ }
+
+ mBatteryStateUnknown = isUnknown;
+
+ if (mBatteryStateUnknown) {
+ mBatteryIconView.setImageDrawable(getUnknownStateDrawable());
+ } else {
+ mBatteryIconView.setImageDrawable(mDrawable);
+ }
+
+ updateShowPercent();
+ }
+
/**
* Looks up the scale factor for status bar icons and scales the battery view by that amount.
*/
@@ -449,6 +488,10 @@ public class BatteryMeterView extends LinearLayout implements
if (mBatteryPercentView != null) {
mBatteryPercentView.setTextColor(singleToneColor);
}
+
+ if (mUnknownStateDrawable != null) {
+ mUnknownStateDrawable.setTint(singleToneColor);
+ }
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -458,8 +501,8 @@ public class BatteryMeterView extends LinearLayout implements
pw.println(" mDrawable.getPowerSave: " + powerSave);
pw.println(" mBatteryPercentView.getText(): " + percent);
pw.println(" mTextColor: #" + Integer.toHexString(mTextColor));
+ pw.println(" mBatteryStateUnknown: " + mBatteryStateUnknown);
pw.println(" mLevel: " + mLevel);
- pw.println(" mForceShowPercent: " + mForceShowPercent);
}
private final class SettingObserver extends ContentObserver {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 4f9d84de36a2..d8e94bb45b75 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -16,6 +16,7 @@
package com.android.systemui;
+import android.app.ActivityThread;
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
@@ -85,8 +86,10 @@ public class SystemUIFactory {
@VisibleForTesting
public void init(Context context, boolean fromTest)
throws ExecutionException, InterruptedException {
+ // Only initialize components for the main system ui process running as the primary user
final boolean initializeComponents = !fromTest
- && android.os.Process.myUserHandle().isSystem();
+ && android.os.Process.myUserHandle().isSystem()
+ && ActivityThread.currentProcessName().equals(ActivityThread.currentPackageName());
mRootComponent = buildGlobalRootComponent(context);
// Stand up WMComponent
mWMComponent = mRootComponent.getWMComponentBuilder().build();
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 708002d5b946..1f41038c260f 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -32,6 +32,7 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpHandler;
import com.android.systemui.dump.LogBufferFreezer;
import com.android.systemui.dump.SystemUIAuxiliaryDumpService;
+import com.android.systemui.statusbar.policy.BatteryStateNotifier;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -44,18 +45,21 @@ public class SystemUIService extends Service {
private final DumpHandler mDumpHandler;
private final BroadcastDispatcher mBroadcastDispatcher;
private final LogBufferFreezer mLogBufferFreezer;
+ private final BatteryStateNotifier mBatteryStateNotifier;
@Inject
public SystemUIService(
@Main Handler mainHandler,
DumpHandler dumpHandler,
BroadcastDispatcher broadcastDispatcher,
- LogBufferFreezer logBufferFreezer) {
+ LogBufferFreezer logBufferFreezer,
+ BatteryStateNotifier batteryStateNotifier) {
super();
mMainHandler = mainHandler;
mDumpHandler = dumpHandler;
mBroadcastDispatcher = broadcastDispatcher;
mLogBufferFreezer = logBufferFreezer;
+ mBatteryStateNotifier = batteryStateNotifier;
}
@Override
@@ -68,6 +72,11 @@ public class SystemUIService extends Service {
// Finish initializing dump logic
mLogBufferFreezer.attach(mBroadcastDispatcher);
+ // If configured, set up a battery notification
+ if (getResources().getBoolean(R.bool.config_showNotificationForUnknownBatteryState)) {
+ mBatteryStateNotifier.startListening();
+ }
+
// For debugging RescueParty
if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_sysui", false)) {
throw new RuntimeException();
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 874c73baf146..c72bc2543b36 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;
@@ -243,16 +245,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);
}
/**
@@ -475,7 +486,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
/**
* Whether the current user has a UDFP enrolled.
*/
- public boolean hasUdfpsEnrolled() {
+ public boolean isUdfpsEnrolled() {
// 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;
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..f07e5afdd887 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -156,7 +156,7 @@ public class DozeSensors {
findSensorWithType(config.udfpsLongPressSensorType()),
"doze_pulse_on_auth",
true /* settingDef */,
- authController.hasUdfpsEnrolled() /* configured */,
+ authController.isUdfpsEnrolled() /* configured */,
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/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/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 80928d6da978..451bd42bd053 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -16,10 +16,12 @@
package com.android.systemui.media.dialog;
+import android.app.Notification;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
import android.media.MediaMetadata;
import android.media.MediaRoute2Info;
import android.media.RoutingSessionInfo;
@@ -221,9 +223,14 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback {
}
for (NotificationEntry entry
: mNotificationEntryManager.getActiveNotificationsForCurrentUser()) {
- if (entry.getSbn().getNotification().hasMediaSession()
+ final Notification notification = entry.getSbn().getNotification();
+ if (notification.hasMediaSession()
&& TextUtils.equals(entry.getSbn().getPackageName(), mPackageName)) {
- return IconCompat.createFromIcon(entry.getSbn().getNotification().getLargeIcon());
+ final Icon icon = notification.getLargeIcon();
+ if (icon == null) {
+ break;
+ }
+ return IconCompat.createFromIcon(icon);
}
}
return null;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 8e0e4ac7c8ef..a35151068bee 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -71,8 +71,7 @@ public class QSContainerImpl extends FrameLayout {
private int mSideMargins;
private boolean mQsDisabled;
- private int mContentPaddingStart = -1;
- private int mContentPaddingEnd = -1;
+ private int mContentPadding = -1;
private boolean mAnimateBottomOnNextLayout;
public QSContainerImpl(Context context, AttributeSet attrs) {
@@ -206,10 +205,9 @@ public class QSContainerImpl extends FrameLayout {
mSideMargins = getResources().getDimensionPixelSize(R.dimen.notification_side_paddings);
int padding = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_shade_content_margin_horizontal);
- boolean marginsChanged = padding != mContentPaddingStart || padding != mContentPaddingEnd;
- mContentPaddingStart = padding;
- mContentPaddingEnd = padding;
+ R.dimen.notification_shade_content_margin_horizontal);
+ boolean marginsChanged = padding != mContentPadding;
+ mContentPadding = padding;
if (marginsChanged) {
updatePaddingsAndMargins();
}
@@ -290,19 +288,19 @@ public class QSContainerImpl extends FrameLayout {
lp.leftMargin = mSideMargins;
if (view == mQSPanelContainer) {
// QS panel lays out some of its content full width
- mQSPanel.setContentMargins(mContentPaddingStart, mContentPaddingEnd);
+ mQSPanel.setContentMargins(mContentPadding, mContentPadding);
Pair<Integer, Integer> margins = mQSPanel.getVisualSideMargins();
// Apply paddings based on QSPanel
mQSCustomizer.setContentPaddings(margins.first, margins.second);
} else if (view == mHeader) {
// The header contains the QQS panel which needs to have special padding, to
// visually align them.
- mHeader.setContentMargins(mContentPaddingStart, mContentPaddingEnd);
+ mHeader.setContentMargins(mContentPadding, mContentPadding);
} else {
view.setPaddingRelative(
- mContentPaddingStart,
+ mContentPadding,
view.getPaddingTop(),
- mContentPaddingEnd,
+ mContentPadding,
view.getPaddingBottom());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java
index e6f43c1ff1d2..45564b0bfa6b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenMediaRecorder.java
@@ -30,6 +30,8 @@ import android.graphics.Bitmap;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaCodecInfo;
+import android.media.MediaCodecList;
+import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.media.MediaRecorder;
import android.media.ThumbnailUtils;
@@ -124,17 +126,19 @@ public class ScreenMediaRecorder {
DisplayMetrics metrics = new DisplayMetrics();
WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
wm.getDefaultDisplay().getRealMetrics(metrics);
- int screenWidth = metrics.widthPixels;
- int screenHeight = metrics.heightPixels;
- int refereshRate = (int) wm.getDefaultDisplay().getRefreshRate();
- int vidBitRate = screenHeight * screenWidth * refereshRate / VIDEO_FRAME_RATE
+ int refreshRate = (int) wm.getDefaultDisplay().getRefreshRate();
+ int[] dimens = getSupportedSize(metrics.widthPixels, metrics.heightPixels, refreshRate);
+ int width = dimens[0];
+ int height = dimens[1];
+ refreshRate = dimens[2];
+ int vidBitRate = width * height * refreshRate / VIDEO_FRAME_RATE
* VIDEO_FRAME_RATE_TO_RESOLUTION_RATIO;
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setVideoEncodingProfileLevel(
MediaCodecInfo.CodecProfileLevel.AVCProfileHigh,
MediaCodecInfo.CodecProfileLevel.AVCLevel3);
- mMediaRecorder.setVideoSize(screenWidth, screenHeight);
- mMediaRecorder.setVideoFrameRate(refereshRate);
+ mMediaRecorder.setVideoSize(width, height);
+ mMediaRecorder.setVideoFrameRate(refreshRate);
mMediaRecorder.setVideoEncodingBitRate(vidBitRate);
mMediaRecorder.setMaxDuration(MAX_DURATION_MS);
mMediaRecorder.setMaxFileSize(MAX_FILESIZE_BYTES);
@@ -153,8 +157,8 @@ public class ScreenMediaRecorder {
mInputSurface = mMediaRecorder.getSurface();
mVirtualDisplay = mMediaProjection.createVirtualDisplay(
"Recording Display",
- screenWidth,
- screenHeight,
+ width,
+ height,
metrics.densityDpi,
DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
mInputSurface,
@@ -173,6 +177,84 @@ public class ScreenMediaRecorder {
}
/**
+ * Find the highest supported screen resolution and refresh rate for the given dimensions on
+ * this device, up to actual size and given rate.
+ * If possible this will return the same values as given, but values may be smaller on some
+ * devices.
+ *
+ * @param screenWidth Actual pixel width of screen
+ * @param screenHeight Actual pixel height of screen
+ * @param refreshRate Desired refresh rate
+ * @return array with supported width, height, and refresh rate
+ */
+ private int[] getSupportedSize(int screenWidth, int screenHeight, int refreshRate) {
+ double maxScale = 0;
+
+ MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
+ MediaCodecInfo.VideoCapabilities maxInfo = null;
+ for (MediaCodecInfo codec : codecList.getCodecInfos()) {
+ String videoType = MediaFormat.MIMETYPE_VIDEO_AVC;
+ String[] types = codec.getSupportedTypes();
+ for (String t : types) {
+ if (!t.equalsIgnoreCase(videoType)) {
+ continue;
+ }
+ MediaCodecInfo.CodecCapabilities capabilities =
+ codec.getCapabilitiesForType(videoType);
+ if (capabilities != null && capabilities.getVideoCapabilities() != null) {
+ MediaCodecInfo.VideoCapabilities vc = capabilities.getVideoCapabilities();
+
+ int width = vc.getSupportedWidths().getUpper();
+ int height = vc.getSupportedHeights().getUpper();
+
+ if (width >= screenWidth && height >= screenHeight
+ && vc.isSizeSupported(screenWidth, screenHeight)) {
+
+ // Desired size is supported, now get the rate
+ int maxRate = vc.getSupportedFrameRatesFor(screenWidth, screenHeight)
+ .getUpper().intValue();
+
+ if (maxRate < refreshRate) {
+ refreshRate = maxRate;
+ }
+ Log.d(TAG, "Screen size supported at rate " + refreshRate);
+ return new int[]{screenWidth, screenHeight, refreshRate};
+ }
+
+ // Otherwise, continue searching
+ double scale = Math.min(((double) width / screenWidth),
+ ((double) height / screenHeight));
+ if (scale > maxScale) {
+ maxScale = scale;
+ maxInfo = vc;
+ }
+ }
+ }
+ }
+
+ // Resize for max supported size
+ int scaledWidth = (int) (screenWidth * maxScale);
+ int scaledHeight = (int) (screenHeight * maxScale);
+ if (scaledWidth % maxInfo.getWidthAlignment() != 0) {
+ scaledWidth -= (scaledWidth % maxInfo.getWidthAlignment());
+ }
+ if (scaledHeight % maxInfo.getHeightAlignment() != 0) {
+ scaledHeight -= (scaledHeight % maxInfo.getHeightAlignment());
+ }
+
+ // Find max supported rate for size
+ int maxRate = maxInfo.getSupportedFrameRatesFor(scaledWidth, scaledHeight)
+ .getUpper().intValue();
+ if (maxRate < refreshRate) {
+ refreshRate = maxRate;
+ }
+
+ Log.d(TAG, "Resized by " + maxScale + ": " + scaledWidth + ", " + scaledHeight
+ + ", " + refreshRate);
+ return new int[]{scaledWidth, scaledHeight, refreshRate};
+ }
+
+ /**
* Start screen recording
*/
void start() throws IOException, RemoteException, IllegalStateException {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index a59ff38896dc..a252a7a12274 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -121,6 +121,7 @@ public class KeyguardIndicationController implements StateListener,
private int mChargingSpeed;
private int mChargingWattage;
private int mBatteryLevel;
+ private boolean mBatteryPresent = true;
private long mChargingTimeRemaining;
private float mDisclosureMaxAlpha;
private String mMessageToShowOnScreenOn;
@@ -389,86 +390,103 @@ public class KeyguardIndicationController implements StateListener,
mWakeLock.setAcquired(false);
}
- if (mVisible) {
- // Walk down a precedence-ordered list of what indication
- // should be shown based on user or device state
- if (mDozing) {
- // When dozing we ignore any text color and use white instead, because
- // colors can be hard to read in low brightness.
- mTextView.setTextColor(Color.WHITE);
- if (!TextUtils.isEmpty(mTransientIndication)) {
- mTextView.switchIndication(mTransientIndication);
- } else if (!TextUtils.isEmpty(mAlignmentIndication)) {
- mTextView.switchIndication(mAlignmentIndication);
- mTextView.setTextColor(mContext.getColor(R.color.misalignment_text_color));
- } else if (mPowerPluggedIn) {
- String indication = computePowerIndication();
- if (animate) {
- animateText(mTextView, indication);
- } else {
- mTextView.switchIndication(indication);
- }
- } else {
- String percentage = NumberFormat.getPercentInstance()
- .format(mBatteryLevel / 100f);
- mTextView.switchIndication(percentage);
- }
- return;
- }
+ if (!mVisible) {
+ return;
+ }
- int userId = KeyguardUpdateMonitor.getCurrentUser();
- String trustGrantedIndication = getTrustGrantedIndication();
- String trustManagedIndication = getTrustManagedIndication();
+ // A few places might need to hide the indication, so always start by making it visible
+ mIndicationArea.setVisibility(View.VISIBLE);
- String powerIndication = null;
- if (mPowerPluggedIn) {
- powerIndication = computePowerIndication();
- }
-
- boolean isError = false;
- if (!mKeyguardUpdateMonitor.isUserUnlocked(userId)) {
- mTextView.switchIndication(com.android.internal.R.string.lockscreen_storage_locked);
- } else if (!TextUtils.isEmpty(mTransientIndication)) {
- if (powerIndication != null && !mTransientIndication.equals(powerIndication)) {
- String indication = mContext.getResources().getString(
- R.string.keyguard_indication_trust_unlocked_plugged_in,
- mTransientIndication, powerIndication);
- mTextView.switchIndication(indication);
- } else {
- mTextView.switchIndication(mTransientIndication);
- }
- isError = mTransientTextIsError;
- } else if (!TextUtils.isEmpty(trustGrantedIndication)
- && mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
- if (powerIndication != null) {
- String indication = mContext.getResources().getString(
- R.string.keyguard_indication_trust_unlocked_plugged_in,
- trustGrantedIndication, powerIndication);
- mTextView.switchIndication(indication);
- } else {
- mTextView.switchIndication(trustGrantedIndication);
- }
+ // Walk down a precedence-ordered list of what indication
+ // should be shown based on user or device state
+ if (mDozing) {
+ // When dozing we ignore any text color and use white instead, because
+ // colors can be hard to read in low brightness.
+ mTextView.setTextColor(Color.WHITE);
+ if (!TextUtils.isEmpty(mTransientIndication)) {
+ mTextView.switchIndication(mTransientIndication);
+ } else if (!mBatteryPresent) {
+ // If there is no battery detected, hide the indication and bail
+ mIndicationArea.setVisibility(View.GONE);
} else if (!TextUtils.isEmpty(mAlignmentIndication)) {
mTextView.switchIndication(mAlignmentIndication);
- isError = true;
+ mTextView.setTextColor(mContext.getColor(R.color.misalignment_text_color));
} else if (mPowerPluggedIn) {
- if (DEBUG_CHARGING_SPEED) {
- powerIndication += ", " + (mChargingWattage / 1000) + " mW";
- }
+ String indication = computePowerIndication();
if (animate) {
- animateText(mTextView, powerIndication);
+ animateText(mTextView, indication);
} else {
- mTextView.switchIndication(powerIndication);
+ mTextView.switchIndication(indication);
}
- } else if (!TextUtils.isEmpty(trustManagedIndication)
- && mKeyguardUpdateMonitor.getUserTrustIsManaged(userId)
- && !mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
- mTextView.switchIndication(trustManagedIndication);
} else {
- mTextView.switchIndication(mRestingIndication);
+ String percentage = NumberFormat.getPercentInstance()
+ .format(mBatteryLevel / 100f);
+ mTextView.switchIndication(percentage);
}
- mTextView.setTextColor(isError ? Utils.getColorError(mContext)
- : mInitialTextColorState);
+ return;
+ }
+
+ int userId = KeyguardUpdateMonitor.getCurrentUser();
+ String trustGrantedIndication = getTrustGrantedIndication();
+ String trustManagedIndication = getTrustManagedIndication();
+
+ String powerIndication = null;
+ if (mPowerPluggedIn) {
+ powerIndication = computePowerIndication();
+ }
+
+ // Some cases here might need to hide the indication (if the battery is not present)
+ boolean hideIndication = false;
+ boolean isError = false;
+ if (!mKeyguardUpdateMonitor.isUserUnlocked(userId)) {
+ mTextView.switchIndication(com.android.internal.R.string.lockscreen_storage_locked);
+ } else if (!TextUtils.isEmpty(mTransientIndication)) {
+ if (powerIndication != null && !mTransientIndication.equals(powerIndication)) {
+ String indication = mContext.getResources().getString(
+ R.string.keyguard_indication_trust_unlocked_plugged_in,
+ mTransientIndication, powerIndication);
+ mTextView.switchIndication(indication);
+ hideIndication = !mBatteryPresent;
+ } else {
+ mTextView.switchIndication(mTransientIndication);
+ }
+ isError = mTransientTextIsError;
+ } else if (!TextUtils.isEmpty(trustGrantedIndication)
+ && mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
+ if (powerIndication != null) {
+ String indication = mContext.getResources().getString(
+ R.string.keyguard_indication_trust_unlocked_plugged_in,
+ trustGrantedIndication, powerIndication);
+ mTextView.switchIndication(indication);
+ hideIndication = !mBatteryPresent;
+ } else {
+ mTextView.switchIndication(trustGrantedIndication);
+ }
+ } else if (!TextUtils.isEmpty(mAlignmentIndication)) {
+ mTextView.switchIndication(mAlignmentIndication);
+ isError = true;
+ hideIndication = !mBatteryPresent;
+ } else if (mPowerPluggedIn) {
+ if (DEBUG_CHARGING_SPEED) {
+ powerIndication += ", " + (mChargingWattage / 1000) + " mW";
+ }
+ if (animate) {
+ animateText(mTextView, powerIndication);
+ } else {
+ mTextView.switchIndication(powerIndication);
+ }
+ hideIndication = !mBatteryPresent;
+ } else if (!TextUtils.isEmpty(trustManagedIndication)
+ && mKeyguardUpdateMonitor.getUserTrustIsManaged(userId)
+ && !mKeyguardUpdateMonitor.getUserHasTrust(userId)) {
+ mTextView.switchIndication(trustManagedIndication);
+ } else {
+ mTextView.switchIndication(mRestingIndication);
+ }
+ mTextView.setTextColor(isError ? Utils.getColorError(mContext)
+ : mInitialTextColorState);
+ if (hideIndication) {
+ mIndicationArea.setVisibility(View.GONE);
}
}
@@ -647,6 +665,7 @@ public class KeyguardIndicationController implements StateListener,
pw.println(" mMessageToShowOnScreenOn: " + mMessageToShowOnScreenOn);
pw.println(" mDozing: " + mDozing);
pw.println(" mBatteryLevel: " + mBatteryLevel);
+ pw.println(" mBatteryPresent: " + mBatteryPresent);
pw.println(" mTextView.getText(): " + (mTextView == null ? null : mTextView.getText()));
pw.println(" computePowerIndication(): " + computePowerIndication());
}
@@ -685,6 +704,7 @@ public class KeyguardIndicationController implements StateListener,
mChargingWattage = status.maxChargingWattage;
mChargingSpeed = status.getChargingSpeed(mContext);
mBatteryLevel = status.level;
+ mBatteryPresent = status.present;
try {
mChargingTimeRemaining = mPowerPluggedIn
? mBatteryInfo.computeChargeTimeRemaining() : -1;
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/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..5e883bee13a8 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;
@@ -37,6 +39,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.R;
+import com.android.systemui.biometrics.AuthController;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
@@ -74,6 +77,7 @@ public class LockscreenLockIconController {
private final KeyguardStateController mKeyguardStateController;
private final Resources mResources;
private final HeadsUpManagerPhone mHeadsUpManagerPhone;
+ private final AuthController mAuthController;
private boolean mKeyguardShowing;
private boolean mKeyguardJustShown;
private boolean mBlockUpdates;
@@ -322,7 +326,8 @@ public class LockscreenLockIconController {
@Nullable DockManager dockManager,
KeyguardStateController keyguardStateController,
@Main Resources resources,
- HeadsUpManagerPhone headsUpManagerPhone) {
+ HeadsUpManagerPhone headsUpManagerPhone,
+ AuthController authController) {
mLockscreenGestureLogger = lockscreenGestureLogger;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mLockPatternUtils = lockPatternUtils;
@@ -337,6 +342,7 @@ public class LockscreenLockIconController {
mKeyguardStateController = keyguardStateController;
mResources = resources;
mHeadsUpManagerPhone = headsUpManagerPhone;
+ mAuthController = authController;
mKeyguardIndicationController.setLockIconController(this);
}
@@ -502,6 +508,11 @@ public class LockscreenLockIconController {
* @return true if the visibility changed
*/
private boolean updateIconVisibility() {
+ if (mAuthController.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..e9a7132f4a5c 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(),
+ mAuthController.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 (mAuthController.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/statusbar/policy/BatteryController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
index 06e4731265e3..08e70a97e0ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryController.java
@@ -97,6 +97,9 @@ public interface BatteryController extends DemoMode, Dumpable,
default void onPowerSaveChanged(boolean isPowerSave) {
}
+ default void onBatteryUnknownStateChanged(boolean isUnknown) {
+ }
+
default void onReverseChanged(boolean isReverse, int level, String name) {
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index 57ac85e1e86d..d8710bf85a6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.policy;
+import static android.os.BatteryManager.EXTRA_PRESENT;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -75,6 +77,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
protected int mLevel;
protected boolean mPluggedIn;
protected boolean mCharging;
+ private boolean mStateUnknown = false;
private boolean mCharged;
protected boolean mPowerSave;
private boolean mAodPowerSave;
@@ -138,6 +141,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
pw.print(" mCharging="); pw.println(mCharging);
pw.print(" mCharged="); pw.println(mCharged);
pw.print(" mPowerSave="); pw.println(mPowerSave);
+ pw.print(" mStateUnknown="); pw.println(mStateUnknown);
}
@Override
@@ -180,6 +184,13 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
mWirelessCharging = mCharging && intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0)
== BatteryManager.BATTERY_PLUGGED_WIRELESS;
+ boolean present = intent.getBooleanExtra(EXTRA_PRESENT, true);
+ boolean unknown = !present;
+ if (unknown != mStateUnknown) {
+ mStateUnknown = unknown;
+ fireBatteryUnknownStateChanged();
+ }
+
fireBatteryLevelChanged();
} else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
updatePowerSave();
@@ -328,6 +339,15 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
}
}
+ private void fireBatteryUnknownStateChanged() {
+ synchronized (mChangeCallbacks) {
+ final int n = mChangeCallbacks.size();
+ for (int i = 0; i < n; i++) {
+ mChangeCallbacks.get(i).onBatteryUnknownStateChanged(mStateUnknown);
+ }
+ }
+ }
+
private void firePowerSaveChanged() {
synchronized (mChangeCallbacks) {
final int N = mChangeCallbacks.size();
@@ -346,6 +366,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
String level = args.getString("level");
String plugged = args.getString("plugged");
String powerSave = args.getString("powersave");
+ String present = args.getString("present");
if (level != null) {
mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100);
}
@@ -356,6 +377,10 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
mPowerSave = powerSave.equals("true");
firePowerSaveChanged();
}
+ if (present != null) {
+ mStateUnknown = !present.equals("true");
+ fireBatteryUnknownStateChanged();
+ }
fireBatteryLevelChanged();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
new file mode 100644
index 000000000000..92e5b78f776a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
@@ -0,0 +1,90 @@
+/*
+ * 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.statusbar.policy
+
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import com.android.systemui.R
+import com.android.systemui.util.concurrency.DelayableExecutor
+import javax.inject.Inject
+
+/**
+ * Listens for important battery states and sends non-dismissible system notifications if there is a
+ * problem
+ */
+class BatteryStateNotifier @Inject constructor(
+ val controller: BatteryController,
+ val noMan: NotificationManager,
+ val delayableExecutor: DelayableExecutor,
+ val context: Context
+) : BatteryController.BatteryStateChangeCallback {
+ var stateUnknown = false
+
+ fun startListening() {
+ controller.addCallback(this)
+ }
+
+ fun stopListening() {
+ controller.removeCallback(this)
+ }
+
+ override fun onBatteryUnknownStateChanged(isUnknown: Boolean) {
+ stateUnknown = isUnknown
+ if (stateUnknown) {
+ val channel = NotificationChannel("battery_status", "Battery status",
+ NotificationManager.IMPORTANCE_DEFAULT)
+ noMan.createNotificationChannel(channel)
+
+ val intent = Intent(Intent.ACTION_VIEW,
+ Uri.parse(context.getString(R.string.config_batteryStateUnknownUrl)))
+ val pi = PendingIntent.getActivity(context, 0, intent, 0)
+
+ val builder = Notification.Builder(context, channel.id)
+ .setAutoCancel(false)
+ .setContentTitle(
+ context.getString(R.string.battery_state_unknown_notification_title))
+ .setContentText(
+ context.getString(R.string.battery_state_unknown_notification_text))
+ .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+ .setContentIntent(pi)
+ .setAutoCancel(true)
+ .setOngoing(true)
+
+ noMan.notify(TAG, ID, builder.build())
+ } else {
+ scheduleNotificationCancel()
+ }
+ }
+
+ private fun scheduleNotificationCancel() {
+ val r = {
+ if (!stateUnknown) {
+ noMan.cancel(ID)
+ }
+ }
+ delayableExecutor.executeDelayed(r, DELAY_MILLIS)
+ }
+}
+
+private const val TAG = "BatteryStateNotifier"
+private const val ID = 666
+private const val DELAY_MILLIS: Long = 4 * 60 * 60 * 1000 \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 6b991f8ec521..49be648755c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -427,7 +427,8 @@ public class MobileSignalController extends SignalController<
return false;
}
if (isCdma()) {
- return mPhone.getCdmaEnhancedRoamingIndicatorIconIndex() != TelephonyManager.ERI_OFF;
+ return mPhone.getCdmaEnhancedRoamingIndicatorDisplayNumber()
+ != TelephonyManager.ERI_OFF;
} else {
return mServiceState != null && mServiceState.getRoaming();
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
index b7efa7c4c5ac..bbabaf429859 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/TvPipModule.java
@@ -22,6 +22,7 @@ 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;
@@ -106,9 +107,10 @@ public abstract class TvPipModule {
PipBoundsHandler pipBoundsHandler,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
Optional<SplitScreen> splitScreenOptional, DisplayController displayController,
- PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer) {
+ PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer,
+ SystemWindows systemWindows) {
return new PipTaskOrganizer(context, pipBoundsState, pipBoundsHandler,
- pipSurfaceTransactionHelper, splitScreenOptional, displayController,
- pipUiEventLogger, shellTaskOrganizer);
+ null /* menuActivityController */, pipSurfaceTransactionHelper, splitScreenOptional,
+ displayController, pipUiEventLogger, shellTaskOrganizer, systemWindows);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
index b6fbd589ae2c..1ca04af393ff 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java
@@ -106,9 +106,9 @@ public class WMShellModule {
@WMSingleton
@Provides
- static PipMenuActivityController providePipMenuActivityController(Context context,
- PipMediaController pipMediaController, PipTaskOrganizer pipTaskOrganizer) {
- return new PipMenuActivityController(context, pipMediaController, pipTaskOrganizer);
+ static PipMenuActivityController providesPipMenuActivityController(Context context,
+ PipMediaController pipMediaController, SystemWindows systemWindows) {
+ return new PipMenuActivityController(context, pipMediaController, systemWindows);
}
@WMSingleton
@@ -128,11 +128,13 @@ public class WMShellModule {
static PipTaskOrganizer providePipTaskOrganizer(Context context,
PipBoundsState pipBoundsState,
PipBoundsHandler pipBoundsHandler,
+ PipMenuActivityController menuActivityController,
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
Optional<SplitScreen> splitScreenOptional, DisplayController displayController,
- PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer) {
+ PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer,
+ SystemWindows systemWindows) {
return new PipTaskOrganizer(context, pipBoundsState, pipBoundsHandler,
- pipSurfaceTransactionHelper, splitScreenOptional, displayController,
- pipUiEventLogger, shellTaskOrganizer);
+ menuActivityController, pipSurfaceTransactionHelper, splitScreenOptional,
+ displayController, pipUiEventLogger, shellTaskOrganizer, systemWindows);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index e6479ddaedb3..caab2abd7ec6 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()).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/accessibility/WindowMagnificationAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
index 33b1d94df80e..6978ef4fb9ac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
@@ -92,7 +92,7 @@ public class WindowMagnificationAnimationControllerTest extends SysuiTestCase {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mInstrumentation = InstrumentationRegistry.getInstrumentation();
- mWaitingAnimationPeriod = ANIMATION_DURATION_MS + 50;
+ mWaitingAnimationPeriod = 2 * ANIMATION_DURATION_MS;
mWaitIntermediateAnimationPeriod = ANIMATION_DURATION_MS / 2;
mController = new SpyWindowMagnificationController(mContext, mHandler,
mSfVsyncFrameProvider, null, new SurfaceControl.Transaction(),
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/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
index 6ceac131ed4b..0d352c1b42d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
@@ -447,6 +447,25 @@ public class MediaOutputControllerTest extends SysuiTestCase {
}
@Test
+ public void getNotificationLargeIcon_withoutLargeIcon_returnsNull() {
+ final List<NotificationEntry> entryList = new ArrayList<>();
+ final NotificationEntry entry = mock(NotificationEntry.class);
+ final StatusBarNotification sbn = mock(StatusBarNotification.class);
+ final Notification notification = mock(Notification.class);
+ entryList.add(entry);
+
+ when(mNotificationEntryManager.getActiveNotificationsForCurrentUser())
+ .thenReturn(entryList);
+ when(entry.getSbn()).thenReturn(sbn);
+ when(sbn.getNotification()).thenReturn(notification);
+ when(sbn.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ when(notification.hasMediaSession()).thenReturn(true);
+ when(notification.getLargeIcon()).thenReturn(null);
+
+ assertThat(mMediaOutputController.getNotificationIcon()).isNull();
+ }
+
+ @Test
public void getNotificationLargeIcon_withPackageNameAndMediaSession_returnsIconCompat() {
final List<NotificationEntry> entryList = new ArrayList<>();
final NotificationEntry entry = mock(NotificationEntry.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index e0d268127d90..f9b14ba7cd31 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -494,7 +494,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
createController();
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
80 /* level */, BatteryManager.BATTERY_PLUGGED_WIRELESS, 100 /* health */,
- 0 /* maxChargingWattage */);
+ 0 /* maxChargingWattage */, true /* present */);
mController.getKeyguardCallback().onRefreshBatteryInfo(status);
verify(mIBatteryStats).computeChargeTimeRemaining();
@@ -506,7 +506,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
createController();
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
80 /* level */, 0 /* plugged */, 100 /* health */,
- 0 /* maxChargingWattage */);
+ 0 /* maxChargingWattage */, true /* present */);
mController.getKeyguardCallback().onRefreshBatteryInfo(status);
verify(mIBatteryStats, never()).computeChargeTimeRemaining();
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..72a0258e148a 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
@@ -32,6 +32,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.biometrics.AuthController;
import com.android.systemui.dock.DockManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -80,6 +81,8 @@ public class LockscreenIconControllerTest extends SysuiTestCase {
private Resources mResources;
@Mock
private HeadsUpManagerPhone mHeadsUpManagerPhone;
+ @Mock
+ private AuthController mAuthController;
private LockscreenLockIconController mLockIconController;
private OnAttachStateChangeListener mOnAttachStateChangeListener;
@@ -89,13 +92,14 @@ public class LockscreenIconControllerTest extends SysuiTestCase {
public void setUp() {
MockitoAnnotations.initMocks(this);
+ when(mAuthController.isUdfpsEnrolled()).thenReturn(false);
when(mLockIcon.getContext()).thenReturn(mContext);
mLockIconController = new LockscreenLockIconController(
mLockscreenGestureLogger, mKeyguardUpdateMonitor, mLockPatternUtils,
mShadeController, mAccessibilityController, mKeyguardIndicationController,
mStatusBarStateController, mConfigurationController, mNotificationWakeUpCoordinator,
mKeyguardBypassController, mDockManager, mKeyguardStateController, mResources,
- mHeadsUpManagerPhone);
+ mHeadsUpManagerPhone, mAuthController);
ArgumentCaptor<OnAttachStateChangeListener> onAttachStateChangeListenerArgumentCaptor =
ArgumentCaptor.forClass(OnAttachStateChangeListener.class);
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..3b123f65d886 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
@@ -58,6 +58,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 +195,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 +204,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+ when(mAuthController.isUdfpsEnrolled()).thenReturn(false);
when(mHeadsUpCallback.getContext()).thenReturn(mContext);
when(mView.getResources()).thenReturn(mResources);
when(mResources.getConfiguration()).thenReturn(mConfiguration);
@@ -267,7 +271,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mNotificationStackScrollLayoutController,
mKeyguardStatusViewComponentFactory,
mGroupManager,
- mNotificationAreaController);
+ mNotificationAreaController,
+ mAuthController);
mNotificationPanelViewController.initDependencies(
mStatusBar,
mNotificationShelfController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
new file mode 100644
index 000000000000..dcd57f137d71
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
@@ -0,0 +1,81 @@
+/*
+ * 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.statusbar.policy
+
+import android.app.NotificationManager
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+
+import androidx.test.filters.SmallTest
+
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.time.FakeSystemClock
+
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.anyString
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+private fun <T> anyObject(): T {
+ return Mockito.anyObject<T>()
+}
+
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper()
+@SmallTest
+class BatteryStateNotifierTest : SysuiTestCase() {
+ @Mock private lateinit var batteryController: BatteryController
+ @Mock private lateinit var noMan: NotificationManager
+
+ private val clock = FakeSystemClock()
+ private val executor = FakeExecutor(clock)
+
+ private lateinit var notifier: BatteryStateNotifier
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ notifier = BatteryStateNotifier(batteryController, noMan, executor, context)
+ notifier.startListening()
+
+ context.ensureTestableResources()
+ }
+
+ @Test
+ fun testNotifyWhenStateUnknown() {
+ notifier.onBatteryUnknownStateChanged(true)
+ verify(noMan).notify(anyString(), anyInt(), anyObject())
+ }
+
+ @Test
+ fun testCancelAfterDelay() {
+ notifier.onBatteryUnknownStateChanged(true)
+ notifier.onBatteryUnknownStateChanged(false)
+
+ clock.advanceTime(DELAY_MILLIS + 1)
+ verify(noMan).cancel(anyInt())
+ }
+}
+
+// From BatteryStateNotifier.kt
+private const val DELAY_MILLIS: Long = 40 * 60 * 60 * 1000
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 13cf679cc5d2..138236af70ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -314,7 +314,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
}
public void setCdmaRoaming(boolean isRoaming) {
- when(mMockTm.getCdmaEnhancedRoamingIndicatorIconIndex()).thenReturn(
+ when(mMockTm.getCdmaEnhancedRoamingIndicatorDisplayNumber()).thenReturn(
isRoaming ? TelephonyManager.ERI_ON : TelephonyManager.ERI_OFF);
}
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/backup/OWNERS b/services/backup/OWNERS
index 7c7e74285bf5..3c5268c5a2a9 100644
--- a/services/backup/OWNERS
+++ b/services/backup/OWNERS
@@ -1,7 +1,6 @@
# Bug component: 656484
aabhinav@google.com
-alsutton@google.com
bryanmawhinney@google.com
jstemmer@google.com
nathch@google.com
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 21ad6de045bb..22423fe00b6c 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -65,7 +65,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
-import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -1146,8 +1145,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
dataConnectionStats.startMonitoring();
mKeepaliveTracker = new KeepaliveTracker(mContext, mHandler);
- mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager,
- mContext.getSystemService(NotificationManager.class));
+ mNotifier = new NetworkNotificationManager(mContext, mTelephonyManager);
final int dailyLimit = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.NETWORK_SWITCH_NOTIFICATION_DAILY_LIMIT,
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 8ea71b3202e5..770e8de66bd7 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -340,7 +340,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
| PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED
| PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES
| PhoneStateListener.LISTEN_REGISTRATION_FAILURE
- | PhoneStateListener.LISTEN_BARRING_INFO;
+ | PhoneStateListener.LISTEN_BARRING_INFO
+ | PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION;
static final long READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK =
PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
new file mode 100644
index 000000000000..db7e16ca8b25
--- /dev/null
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -0,0 +1,103 @@
+/*
+ * 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;
+
+import static java.util.Objects.requireNonNull;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.vcn.IVcnManagementService;
+
+/**
+ * VcnManagementService manages Virtual Carrier Network profiles and lifecycles.
+ *
+ * <pre>The internal structure of the VCN Management subsystem is as follows:
+ *
+ * +------------------------+ 1:1 +--------------------------------+
+ * | VcnManagementService | ------------ Creates -------------> | TelephonySubscriptionManager |
+ * | | | |
+ * | Manages configs and | | Tracks subscriptions, carrier |
+ * | VcnInstance lifecycles | <--- Notifies of subscription & --- | privilege changes, caches maps |
+ * +------------------------+ carrier privilege changes +--------------------------------+
+ * | 1:N ^
+ * | |
+ * | +-------------------------------+
+ * +---------------+ |
+ * | |
+ * Creates when config present, |
+ * subscription group active, and |
+ * providing app is carrier privileged Notifies of safe
+ * | mode state changes
+ * v |
+ * +-----------------------------------------------------------------------+
+ * | VcnInstance |
+ * | |
+ * | Manages tunnel lifecycles based on fulfillable NetworkRequest(s) |
+ * | and overall safe-mode |
+ * +-----------------------------------------------------------------------+
+ * | 1:N ^
+ * Creates to fulfill |
+ * NetworkRequest(s), tears Notifies of VcnTunnel
+ * down when no longer needed teardown (e.g. Network reaped)
+ * | and safe-mode timer changes
+ * v |
+ * +-----------------------------------------------------------------------+
+ * | VcnTunnel |
+ * | |
+ * | Manages a single (IKEv2) tunnel session and NetworkAgent, |
+ * | handles mobility events, (IPsec) Tunnel setup and safe-mode timers |
+ * +-----------------------------------------------------------------------+
+ * | 1:1 ^
+ * | |
+ * Creates upon instantiation Notifies of changes in
+ * | selected underlying network
+ * | or its properties
+ * v |
+ * +-----------------------------------------------------------------------+
+ * | UnderlyingNetworkTracker |
+ * | |
+ * | Manages lifecycle of underlying physical networks, filing requests to |
+ * | bring them up, and releasing them as they become no longer necessary |
+ * +-----------------------------------------------------------------------+
+ * </pre>
+ *
+ * @hide
+ */
+public class VcnManagementService extends IVcnManagementService.Stub {
+ @NonNull private static final String TAG = VcnManagementService.class.getSimpleName();
+
+ public static final boolean VDBG = false; // STOPSHIP: if true
+
+ /* Binder context for this service */
+ @NonNull private final Context mContext;
+ @NonNull private final Dependencies mDeps;
+
+ private VcnManagementService(@NonNull Context context, @NonNull Dependencies deps) {
+ mContext = requireNonNull(context, "Missing context");
+ mDeps = requireNonNull(deps, "Missing dependencies");
+ }
+
+ // Package-visibility for SystemServer to create instances.
+ static VcnManagementService create(@NonNull Context context) {
+ return new VcnManagementService(context, new Dependencies());
+ }
+
+ private static class Dependencies {}
+
+ /** Notifies the VcnManagementService that external dependencies can be set up */
+ public void systemReady() {}
+}
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..d67ea1687595 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
@@ -582,13 +582,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);
+ }
}
}
}
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/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/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 26356b440d09..338539312278 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -21,6 +21,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import android.annotation.NonNull;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -75,16 +76,21 @@ public class NetworkNotificationManager {
private static final boolean DBG = true;
private static final boolean VDBG = false;
+ // The context is for the current user (system server)
private final Context mContext;
private final TelephonyManager mTelephonyManager;
+ // The notification manager is created from a context for User.ALL, so notifications
+ // will be sent to all users.
private final NotificationManager mNotificationManager;
// Tracks the types of notifications managed by this instance, from creation to cancellation.
private final SparseIntArray mNotificationTypeMap;
- public NetworkNotificationManager(Context c, TelephonyManager t, NotificationManager n) {
+ public NetworkNotificationManager(@NonNull final Context c, @NonNull final TelephonyManager t) {
mContext = c;
mTelephonyManager = t;
- mNotificationManager = n;
+ mNotificationManager =
+ (NotificationManager) c.createContextAsUser(UserHandle.ALL, 0 /* flags */)
+ .getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationTypeMap = new SparseIntArray();
}
@@ -282,7 +288,7 @@ public class NetworkNotificationManager {
mNotificationTypeMap.put(id, eventId);
try {
- mNotificationManager.notifyAsUser(tag, eventId, notification, UserHandle.ALL);
+ mNotificationManager.notify(tag, eventId, notification);
} catch (NullPointerException npe) {
Slog.d(TAG, "setNotificationVisible: visible notificationManager error", npe);
}
@@ -311,7 +317,7 @@ public class NetworkNotificationManager {
nameOf(eventId)));
}
try {
- mNotificationManager.cancelAsUser(tag, eventId, UserHandle.ALL);
+ mNotificationManager.cancel(tag, eventId);
} catch (NullPointerException npe) {
Slog.d(TAG, String.format(
"failed to clear notification tag=%s event=%s", tag, nameOf(eventId)), npe);
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index aebcdf19ecf4..4d3998956858 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -199,6 +199,8 @@ public class Vpn {
// automated reconnection
private final Context mContext;
+ // The context is for specific user which is created from mUserId
+ private final Context mUserIdContext;
@VisibleForTesting final Dependencies mDeps;
private final NetworkInfo mNetworkInfo;
private int mLegacyState;
@@ -399,6 +401,7 @@ public class Vpn {
int userId, @NonNull KeyStore keyStore, SystemServices systemServices,
Ikev2SessionCreator ikev2SessionCreator) {
mContext = context;
+ mUserIdContext = context.createContextAsUser(UserHandle.of(userId), 0 /* flags */);
mDeps = deps;
mNetd = netService;
mUserId = userId;
@@ -1925,9 +1928,10 @@ public class Vpn {
final UserHandle user = UserHandle.of(mUserId);
final long token = Binder.clearCallingIdentity();
try {
- final NotificationManager notificationManager = NotificationManager.from(mContext);
+ final NotificationManager notificationManager =
+ mUserIdContext.getSystemService(NotificationManager.class);
if (!visible) {
- notificationManager.cancelAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, user);
+ notificationManager.cancel(TAG, SystemMessage.NOTE_VPN_DISCONNECTED);
return;
}
final Intent intent = new Intent();
@@ -1947,8 +1951,7 @@ public class Vpn {
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setOngoing(true)
.setColor(mContext.getColor(R.color.system_notification_accent_color));
- notificationManager.notifyAsUser(TAG, SystemMessage.NOTE_VPN_DISCONNECTED,
- builder.build(), user);
+ notificationManager.notify(TAG, SystemMessage.NOTE_VPN_DISCONNECTED, builder.build());
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 9437677d8ab8..9245f55bd9fe 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -351,10 +351,9 @@ final class LocalDisplayAdapter extends DisplayAdapter {
if (mDefaultModeId == NO_DISPLAY_MODE_ID) {
mDefaultModeId = activeRecord.mMode.getModeId();
mDefaultConfigGroup = configs[activeConfigId].configGroup;
- } else if (modesAdded && mActiveModeId != activeRecord.mMode.getModeId()) {
+ } else if (modesAdded && activeModeChanged) {
Slog.d(TAG, "New display modes are added and the active mode has changed, "
+ "use active mode as default mode.");
- mActiveModeId = activeRecord.mMode.getModeId();
mDefaultModeId = activeRecord.mMode.getModeId();
mDefaultConfigGroup = configs[activeConfigId].configGroup;
} else if (findDisplayConfigIdLocked(mDefaultModeId, mDefaultConfigGroup) < 0) {
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 9ca4d35f4579..9c48d23dade6 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -306,9 +306,8 @@ public class LocationManagerService extends ILocationManager.Stub {
private void removeLocationProviderManager(LocationProviderManager manager) {
synchronized (mProviderManagers) {
- Preconditions.checkState(getLocationProviderManager(manager.getName()) == manager);
-
- mProviderManagers.remove(manager);
+ boolean removed = mProviderManagers.remove(manager);
+ Preconditions.checkArgument(removed);
manager.setMockProvider(null);
manager.setRealProvider(null);
manager.stopManager();
diff --git a/services/core/java/com/android/server/location/LocationProviderManager.java b/services/core/java/com/android/server/location/LocationProviderManager.java
index b4a172393ba6..f25c65192066 100644
--- a/services/core/java/com/android/server/location/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/LocationProviderManager.java
@@ -491,7 +491,7 @@ class LocationProviderManager extends
builder.setIntervalMillis(MIN_COARSE_INTERVAL_MS);
}
if (baseRequest.getMinUpdateIntervalMillis() < MIN_COARSE_INTERVAL_MS) {
- builder.clearMinUpdateIntervalMillis();
+ builder.setMinUpdateIntervalMillis(MIN_COARSE_INTERVAL_MS);
}
}
@@ -1197,19 +1197,19 @@ class LocationProviderManager extends
public void stopManager() {
synchronized (mLock) {
- mUserHelper.removeListener(mUserChangedListener);
- mSettingsHelper.removeOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
-
- mStarted = false;
-
final long identity = Binder.clearCallingIdentity();
try {
onEnabledChanged(UserHandle.USER_ALL);
removeRegistrationIf(key -> true);
- mEnabledListeners.clear();
} finally {
Binder.restoreCallingIdentity(identity);
}
+
+ mUserHelper.removeListener(mUserChangedListener);
+ mSettingsHelper.removeOnLocationEnabledChangedListener(mLocationEnabledChangedListener);
+
+ Preconditions.checkState(mEnabledListeners.isEmpty());
+ mStarted = false;
}
}
@@ -1408,6 +1408,7 @@ class LocationProviderManager extends
Location location;
synchronized (mLock) {
+ Preconditions.checkState(mStarted);
LastLocation lastLocation = mLastLocations.get(userId);
if (lastLocation == null) {
location = null;
@@ -1429,6 +1430,7 @@ class LocationProviderManager extends
public void injectLastLocation(Location location, int userId) {
synchronized (mLock) {
+ Preconditions.checkState(mStarted);
if (getLastLocationUnsafe(userId, PERMISSION_FINE, false, Long.MAX_VALUE) == null) {
setLastLocation(location, userId);
}
@@ -1476,6 +1478,7 @@ class LocationProviderManager extends
permissionLevel);
synchronized (mLock) {
+ Preconditions.checkState(mStarted);
final long ident = Binder.clearCallingIdentity();
try {
putRegistration(callback.asBinder(), registration);
@@ -1517,6 +1520,7 @@ class LocationProviderManager extends
permissionLevel);
synchronized (mLock) {
+ Preconditions.checkState(mStarted);
final long ident = Binder.clearCallingIdentity();
try {
putRegistration(listener.asBinder(), registration);
@@ -1535,6 +1539,7 @@ class LocationProviderManager extends
permissionLevel);
synchronized (mLock) {
+ Preconditions.checkState(mStarted);
final long identity = Binder.clearCallingIdentity();
try {
putRegistration(pendingIntent, registration);
@@ -1546,6 +1551,7 @@ class LocationProviderManager extends
public void unregisterLocationRequest(ILocationListener listener) {
synchronized (mLock) {
+ Preconditions.checkState(mStarted);
final long identity = Binder.clearCallingIdentity();
try {
removeRegistration(listener.asBinder());
@@ -1557,6 +1563,7 @@ class LocationProviderManager extends
public void unregisterLocationRequest(PendingIntent pendingIntent) {
synchronized (mLock) {
+ Preconditions.checkState(mStarted);
final long identity = Binder.clearCallingIdentity();
try {
removeRegistration(pendingIntent);
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/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index 3a262d6dfafd..06cebac501e7 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -65,6 +65,7 @@ public class LockdownVpnTracker {
@NonNull private final Context mContext;
@NonNull private final ConnectivityService mConnService;
+ @NonNull private final NotificationManager mNotificationManager;
@NonNull private final Handler mHandler;
@NonNull private final Vpn mVpn;
@NonNull private final VpnProfile mProfile;
@@ -93,6 +94,7 @@ public class LockdownVpnTracker {
mHandler = Objects.requireNonNull(handler);
mVpn = Objects.requireNonNull(vpn);
mProfile = Objects.requireNonNull(profile);
+ mNotificationManager = mContext.getSystemService(NotificationManager.class);
final Intent configIntent = new Intent(ACTION_VPN_SETTINGS);
mConfigIntent = PendingIntent.getActivity(mContext, 0 /* requestCode */, configIntent,
@@ -266,11 +268,11 @@ public class LockdownVpnTracker {
.setColor(mContext.getColor(
com.android.internal.R.color.system_notification_accent_color));
- NotificationManager.from(mContext).notify(null, SystemMessage.NOTE_VPN_STATUS,
+ mNotificationManager.notify(null /* tag */, SystemMessage.NOTE_VPN_STATUS,
builder.build());
}
private void hideNotification() {
- NotificationManager.from(mContext).cancel(null, SystemMessage.NOTE_VPN_STATUS);
+ mNotificationManager.cancel(null, SystemMessage.NOTE_VPN_STATUS);
}
}
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 4040f4189698..ea7779a4dc8f 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -110,6 +110,7 @@ abstract public class ManagedServices {
static final String ATT_IS_PRIMARY = "primary";
static final String ATT_VERSION = "version";
static final String ATT_DEFAULTS = "defaults";
+ static final String ATT_USER_SET = "user_set_services";
static final int DB_VERSION = 3;
@@ -150,7 +151,12 @@ abstract public class ManagedServices {
// List of approved packages or components (by user, then by primary/secondary) that are
// allowed to be bound as managed services. A package or component appearing in this list does
// not mean that we are currently bound to said package/component.
- private ArrayMap<Integer, ArrayMap<Boolean, ArraySet<String>>> mApproved = new ArrayMap<>();
+ protected ArrayMap<Integer, ArrayMap<Boolean, ArraySet<String>>> mApproved = new ArrayMap<>();
+
+ // List of packages or components (by user) that are configured to be enabled/disabled
+ // explicitly by the user
+ @GuardedBy("mApproved")
+ protected ArrayMap<Integer, ArraySet<String>> mUserSetServices = new ArrayMap<>();
// True if approved services are stored in xml, not settings.
private boolean mUseXml;
@@ -333,6 +339,12 @@ abstract public class ManagedServices {
}
}
}
+
+ pw.println(" Has user set:");
+ Set<Integer> userIds = mUserSetServices.keySet();
+ for (int userId : userIds) {
+ pw.println(" userId=" + userId + " value=" + mUserSetServices.get(userId));
+ }
}
pw.println(" All " + getCaption() + "s (" + mEnabledServicesForCurrentProfiles.size()
@@ -465,12 +477,20 @@ abstract public class ManagedServices {
for (int j = 0; j < M; j++) {
final boolean isPrimary = approvedByType.keyAt(j);
final Set<String> approved = approvedByType.valueAt(j);
- if (approved != null) {
- String allowedItems = String.join(ENABLED_SERVICES_SEPARATOR, approved);
+ final Set<String> userSet = mUserSetServices.get(approvedUserId);
+ if (approved != null || userSet != null) {
+ String allowedItems = approved == null
+ ? ""
+ : String.join(ENABLED_SERVICES_SEPARATOR, approved);
out.startTag(null, TAG_MANAGED_SERVICES);
out.attribute(null, ATT_APPROVED_LIST, allowedItems);
out.attribute(null, ATT_USER_ID, Integer.toString(approvedUserId));
out.attribute(null, ATT_IS_PRIMARY, Boolean.toString(isPrimary));
+ if (userSet != null) {
+ String userSetItems =
+ String.join(ENABLED_SERVICES_SEPARATOR, userSet);
+ out.attribute(null, ATT_USER_SET, userSetItems);
+ }
writeExtraAttributes(out, approvedUserId);
out.endTag(null, TAG_MANAGED_SERVICES);
@@ -559,11 +579,12 @@ abstract public class ManagedServices {
? userId : XmlUtils.readIntAttribute(parser, ATT_USER_ID, 0);
final boolean isPrimary =
XmlUtils.readBooleanAttribute(parser, ATT_IS_PRIMARY, true);
+ final String userSet = XmlUtils.readStringAttribute(parser, ATT_USER_SET);
readExtraAttributes(tag, parser, resolvedUserId);
if (allowedManagedServicePackages == null || allowedManagedServicePackages.test(
getPackageName(approved), resolvedUserId, getRequiredPermission())) {
if (mUm.getUserInfo(resolvedUserId) != null) {
- addApprovedList(approved, resolvedUserId, isPrimary);
+ addApprovedList(approved, resolvedUserId, isPrimary, userSet);
}
mUseXml = true;
}
@@ -632,9 +653,16 @@ abstract public class ManagedServices {
}
protected void addApprovedList(String approved, int userId, boolean isPrimary) {
+ addApprovedList(approved, userId, isPrimary, approved);
+ }
+
+ protected void addApprovedList(String approved, int userId, boolean isPrimary, String userSet) {
if (TextUtils.isEmpty(approved)) {
approved = "";
}
+ if (userSet == null) {
+ userSet = approved;
+ }
synchronized (mApproved) {
ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
if (approvedByType == null) {
@@ -655,6 +683,19 @@ abstract public class ManagedServices {
approvedList.add(approvedItem);
}
}
+
+ ArraySet<String> userSetList = mUserSetServices.get(userId);
+ if (userSetList == null) {
+ userSetList = new ArraySet<>();
+ mUserSetServices.put(userId, userSetList);
+ }
+ String[] userSetArray = userSet.split(ENABLED_SERVICES_SEPARATOR);
+ for (String pkgOrComponent : userSetArray) {
+ String approvedItem = getApprovedValue(pkgOrComponent);
+ if (approvedItem != null) {
+ userSetList.add(approvedItem);
+ }
+ }
}
}
@@ -664,8 +705,14 @@ abstract public class ManagedServices {
protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId,
boolean isPrimary, boolean enabled) {
+ setPackageOrComponentEnabled(pkgOrComponent, userId, isPrimary, enabled, true);
+ }
+
+ protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId,
+ boolean isPrimary, boolean enabled, boolean userSet) {
Slog.i(TAG,
- (enabled ? " Allowing " : "Disallowing ") + mConfig.caption + " " + pkgOrComponent);
+ (enabled ? " Allowing " : "Disallowing ") + mConfig.caption + " "
+ + pkgOrComponent + " (userSet: " + userSet + ")");
synchronized (mApproved) {
ArrayMap<Boolean, ArraySet<String>> allowedByType = mApproved.get(userId);
if (allowedByType == null) {
@@ -686,6 +733,16 @@ abstract public class ManagedServices {
approved.remove(approvedItem);
}
}
+ ArraySet<String> userSetServices = mUserSetServices.get(userId);
+ if (userSetServices == null) {
+ userSetServices = new ArraySet<>();
+ mUserSetServices.put(userId, userSetServices);
+ }
+ if (userSet) {
+ userSetServices.add(pkgOrComponent);
+ } else {
+ userSetServices.remove(pkgOrComponent);
+ }
}
rebindServices(false, userId);
@@ -761,6 +818,13 @@ abstract public class ManagedServices {
return false;
}
+ boolean isPackageOrComponentUserSet(String pkgOrComponent, int userId) {
+ synchronized (mApproved) {
+ ArraySet<String> services = mUserSetServices.get(userId);
+ return services != null && services.contains(pkgOrComponent);
+ }
+ }
+
protected boolean isPackageAllowed(String pkg, int userId) {
if (pkg == null) {
return false;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8ea432634e61..4f4f3c64b1b4 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -97,6 +97,7 @@ import static android.service.notification.NotificationListenerService.TRIM_FULL
import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
+import static com.android.internal.util.CollectionUtils.emptyIfNull;
import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_GROUP_PREFERENCES;
import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES;
@@ -304,6 +305,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.Set;
@@ -714,7 +716,7 @@ public class NotificationManagerService extends SystemService {
try {
getBinderService().setNotificationListenerAccessGrantedForUser(cn,
- userId, true);
+ userId, true, true);
} catch (RemoteException e) {
e.printStackTrace();
}
@@ -4822,9 +4824,9 @@ public class NotificationManagerService extends SystemService {
@Override
public void setNotificationListenerAccessGranted(ComponentName listener,
- boolean granted) throws RemoteException {
+ boolean granted, boolean userSet) throws RemoteException {
setNotificationListenerAccessGrantedForUser(
- listener, getCallingUserHandle().getIdentifier(), granted);
+ listener, getCallingUserHandle().getIdentifier(), granted, userSet);
}
@Override
@@ -4836,17 +4838,21 @@ public class NotificationManagerService extends SystemService {
@Override
public void setNotificationListenerAccessGrantedForUser(ComponentName listener, int userId,
- boolean granted) {
+ boolean granted, boolean userSet) {
Objects.requireNonNull(listener);
checkNotificationListenerAccess();
+ if (!userSet && isNotificationListenerAccessUserSet(listener)) {
+ // Don't override user's choice
+ return;
+ }
final long identity = Binder.clearCallingIdentity();
try {
if (mAllowedManagedServicePackages.test(
listener.getPackageName(), userId, mListeners.getRequiredPermission())) {
mConditionProviders.setPackageOrComponentEnabled(listener.flattenToString(),
- userId, false, granted);
+ userId, false, granted, userSet);
mListeners.setPackageOrComponentEnabled(listener.flattenToString(),
- userId, true, granted);
+ userId, true, granted, userSet);
getContext().sendBroadcastAsUser(new Intent(
ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED)
@@ -4861,6 +4867,11 @@ public class NotificationManagerService extends SystemService {
}
}
+ private boolean isNotificationListenerAccessUserSet(ComponentName listener) {
+ return mListeners.isPackageOrComponentUserSet(listener.flattenToString(),
+ getCallingUserHandle().getIdentifier());
+ }
+
@Override
public void setNotificationAssistantAccessGrantedForUser(ComponentName assistant,
int userId, boolean granted) {
@@ -8830,14 +8841,12 @@ public class NotificationManagerService extends SystemService {
public class NotificationAssistants extends ManagedServices {
static final String TAG_ENABLED_NOTIFICATION_ASSISTANTS = "enabled_assistants";
- private static final String ATT_USER_SET = "user_set";
private static final String TAG_ALLOWED_ADJUSTMENT_TYPES = "q_allowed_adjustments";
private static final String ATT_TYPES = "types";
private final Object mLock = new Object();
@GuardedBy("mLock")
- private ArrayMap<Integer, Boolean> mUserSetMap = new ArrayMap<>();
private Set<String> mAllowedAdjustments = new ArraySet<>();
@Override
@@ -9026,22 +9035,33 @@ public class NotificationManagerService extends SystemService {
boolean hasUserSet(int userId) {
synchronized (mLock) {
- return mUserSetMap.getOrDefault(userId, false);
+ ArraySet<String> userSetServices = mUserSetServices.get(userId);
+ if (userSetServices == null) {
+ // Legacy case - no data means user-set, unless no assistant is set
+ return !mApproved.isEmpty();
+ }
+ Map<Boolean, ArraySet<String>> approvedByType = emptyIfNull(mApproved.get(userId));
+ return userSetServices.containsAll(emptyIfNull(approvedByType.get(true)))
+ && userSetServices.containsAll(emptyIfNull(approvedByType.get(false)));
}
}
void setUserSet(int userId, boolean set) {
synchronized (mLock) {
- mUserSetMap.put(userId, set);
+ ArraySet<String> userSetServices = new ArraySet<>();
+ if (set) {
+ ArrayMap<Boolean, ArraySet<String>> approvedByType = mApproved.get(userId);
+ if (approvedByType != null) {
+ for (int i = 0; i < approvedByType.size(); i++) {
+ userSetServices.addAll(approvedByType.valueAt(i));
+ }
+ }
+ }
+ mUserSetServices.put(userId, userSetServices);
}
}
@Override
- protected void writeExtraAttributes(XmlSerializer out, int userId) throws IOException {
- out.attribute(null, ATT_USER_SET, Boolean.toString(hasUserSet(userId)));
- }
-
- @Override
protected void readExtraAttributes(String tag, XmlPullParser parser, int userId)
throws IOException {
boolean userSet = XmlUtils.readBooleanAttribute(parser, ATT_USER_SET, false);
@@ -9279,18 +9299,6 @@ public class NotificationManagerService extends SystemService {
super.setPackageOrComponentEnabled(pkgOrComponent, userId, isPrimary, enabled);
}
- @Override
- public void dump(PrintWriter pw, DumpFilter filter) {
- super.dump(pw, filter);
- pw.println(" Has user set:");
- synchronized (mLock) {
- Set<Integer> userIds = mUserSetMap.keySet();
- for (int userId : userIds) {
- pw.println(" userId=" + userId + " value=" + mUserSetMap.get(userId));
- }
- }
- }
-
private boolean isVerboseLogEnabled() {
return Log.isLoggable("notification_assistant", Log.VERBOSE);
}
@@ -9307,8 +9315,8 @@ public class NotificationManagerService extends SystemService {
@Override
protected void setPackageOrComponentEnabled(String pkgOrComponent, int userId,
- boolean isPrimary, boolean enabled) {
- super.setPackageOrComponentEnabled(pkgOrComponent, userId, isPrimary, enabled);
+ boolean isPrimary, boolean enabled, boolean userSet) {
+ super.setPackageOrComponentEnabled(pkgOrComponent, userId, isPrimary, enabled, userSet);
getContext().sendBroadcastAsUser(
new Intent(ACTION_NOTIFICATION_LISTENER_ENABLED_CHANGED)
diff --git a/services/core/java/com/android/server/notification/NotificationShellCmd.java b/services/core/java/com/android/server/notification/NotificationShellCmd.java
index 73272a012671..78c60d559ea9 100644
--- a/services/core/java/com/android/server/notification/NotificationShellCmd.java
+++ b/services/core/java/com/android/server/notification/NotificationShellCmd.java
@@ -214,7 +214,8 @@ public class NotificationShellCmd extends ShellCommand {
if (peekNextArg() != null) {
userId = Integer.parseInt(getNextArgRequired());
}
- mBinderService.setNotificationListenerAccessGrantedForUser(cn, userId, true);
+ mBinderService.setNotificationListenerAccessGrantedForUser(
+ cn, userId, true, true);
}
break;
case "disallow_listener": {
@@ -227,7 +228,8 @@ public class NotificationShellCmd extends ShellCommand {
if (peekNextArg() != null) {
userId = Integer.parseInt(getNextArgRequired());
}
- mBinderService.setNotificationListenerAccessGrantedForUser(cn, userId, false);
+ mBinderService.setNotificationListenerAccessGrantedForUser(
+ cn, userId, false, true);
}
break;
case "allow_assistant": {
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index c0329b2b2fe6..efbdfeaaeb93 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -918,7 +918,7 @@ class InstantAppRegistry {
try {
for (String grantedPermission : appInfo.getGrantedPermissions()) {
final boolean propagatePermission =
- mService.mSettings.canPropagatePermissionToInstantApp(grantedPermission);
+ mPermissionManager.canPropagatePermissionToInstantApp(grantedPermission);
if (propagatePermission && pkg.getRequestedPermissions().contains(
grantedPermission)) {
mService.grantRuntimePermission(pkg.getPackageName(), grantedPermission,
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index e63a05aa6b73..9329271382bc 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -375,7 +375,7 @@ import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
-import com.android.server.pm.permission.BasePermission;
+import com.android.server.pm.permission.Permission;
import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.policy.PermissionPolicyInternal;
@@ -2742,7 +2742,6 @@ public class PackageManagerService extends IPackageManager.Stub
new UserDataPreparer(installer, installLock, context, onlyCore),
lock),
(i, pm) -> new Settings(Environment.getDataDirectory(),
- i.getPermissionManagerServiceInternal().getPermissionSettings(),
RuntimePermissionsPersistence.createInstance(),
i.getPermissionManagerServiceInternal(), lock),
(i, pm) -> AppsFilter.create(pm.mPmInternal, i),
@@ -3173,6 +3172,8 @@ public class PackageManagerService extends IPackageManager.Stub
/* excludePreCreated= */ false));
t.traceEnd();
+ mPermissionManager.readLegacyPermissionsTEMP(mSettings.mPermissions);
+
// Clean up orphaned packages for which the code path doesn't exist
// and they are an update to a system app - caused by bug/32321269
final int packageSettingCount = mSettings.mPackages.size();
@@ -3597,7 +3598,7 @@ public class PackageManagerService extends IPackageManager.Stub
+ ((SystemClock.uptimeMillis()-startTime)/1000f)
+ " seconds");
- mPermissionManager.readStateFromPackageSettingsTEMP();
+ mPermissionManager.readLegacyPermissionStateTEMP();
// If the platform SDK has changed since the last time we booted,
// we need to re-grant app permission to catch any new ones that
// appear. This is really a hack, and means that apps can in some
@@ -11433,7 +11434,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (verifyPackageUpdateLPr(orig, pkg)) {
Slog.i(TAG, "Adopting permissions from " + origName + " to "
+ pkg.getPackageName());
- mSettings.mPermissions.transferPermissions(origName, pkg.getPackageName());
+ mPermissionManager.transferPermissions(origName, pkg.getPackageName());
}
}
}
@@ -17943,7 +17944,7 @@ public class PackageManagerService extends IPackageManager.Stub
final int N = ArrayUtils.size(parsedPackage.getPermissions());
for (int i = N - 1; i >= 0; i--) {
final ParsedPermission perm = parsedPackage.getPermissions().get(i);
- final BasePermission bp = mPermissionManager.getPermissionTEMP(perm.getName());
+ final Permission bp = mPermissionManager.getPermissionTEMP(perm.getName());
// Don't allow anyone but the system to define ephemeral permissions.
if ((perm.getProtectionLevel() & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0
@@ -18712,6 +18713,19 @@ public class PackageManagerService extends IPackageManager.Stub
final String packageName = versionedPackage.getPackageName();
final long versionCode = versionedPackage.getLongVersionCode();
final String internalPackageName;
+
+ try {
+ if (mInjector.getLocalService(ActivityTaskManagerInternal.class)
+ .isBaseOfLockedTask(packageName)) {
+ observer.onPackageDeleted(
+ packageName, PackageManager.DELETE_FAILED_APP_PINNED, null);
+ EventLog.writeEvent(0x534e4554, "127605586", -1, "");
+ return;
+ }
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+
synchronized (mLock) {
// Normalize package name to handle renamed packages and static libs
internalPackageName = resolveInternalPackageNameLPr(packageName, versionCode);
@@ -19592,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
@@ -24231,9 +24245,9 @@ public class PackageManagerService extends IPackageManager.Stub
boolean readPermissionStateForUser(@UserIdInt int userId) {
synchronized (mPackages) {
- mPermissionManager.writeStateToPackageSettingsTEMP();
+ mPermissionManager.writeLegacyPermissionStateTEMP();
mSettings.readPermissionStateForUserSyncLPr(userId);
- mPermissionManager.readStateFromPackageSettingsTEMP();
+ mPermissionManager.readLegacyPermissionStateTEMP();
return mPmInternal.isPermissionUpgradeNeeded(userId);
}
}
@@ -25738,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);
}
}
}
@@ -26376,16 +26390,28 @@ public class PackageManagerService extends IPackageManager.Stub
}
/**
- * Temporary method that wraps mSettings.writeLPr() and calls
- * mPermissionManager.writeStateToPackageSettingsTEMP() beforehand.
+ * Temporary method that wraps mSettings.writeLPr() and calls mPermissionManager's
+ * writeLegacyPermissionsTEMP() and writeLegacyPermissionStateTEMP() beforehand.
*
* TODO(zhanghai): This should be removed once we finish migration of permission storage.
*/
private void writeSettingsLPrTEMP() {
- mPermissionManager.writeStateToPackageSettingsTEMP();
+ mPermissionManager.writeLegacyPermissionsTEMP(mSettings.mPermissions);
+ mPermissionManager.writeLegacyPermissionStateTEMP();
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/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index c7304c2695c9..cd9a4e72672f 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -107,11 +107,10 @@ import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
-import com.android.server.pm.permission.BasePermission;
import com.android.server.pm.permission.LegacyPermissionDataProvider;
+import com.android.server.pm.permission.LegacyPermissionSettings;
import com.android.server.pm.permission.LegacyPermissionState;
import com.android.server.pm.permission.LegacyPermissionState.PermissionState;
-import com.android.server.pm.permission.PermissionSettings;
import com.android.server.utils.TimingsTraceAndSlog;
import libcore.io.IoUtils;
@@ -420,7 +419,7 @@ public final class Settings {
public final KeySetManagerService mKeySetManagerService = new KeySetManagerService(mPackages);
/** Settings and other information about permissions */
- final PermissionSettings mPermissions;
+ final LegacyPermissionSettings mPermissions;
private final LegacyPermissionDataProvider mPermissionDataProvider;
@@ -440,11 +439,10 @@ public final class Settings {
mKernelMappingFilename = null;
}
- Settings(File dataDir, PermissionSettings permissionSettings,
- RuntimePermissionsPersistence runtimePermissionsPersistence,
+ Settings(File dataDir, RuntimePermissionsPersistence runtimePermissionsPersistence,
LegacyPermissionDataProvider permissionDataProvider, Object lock) {
mLock = lock;
- mPermissions = permissionSettings;
+ mPermissions = new LegacyPermissionSettings(lock);
mRuntimePermissionsPersistence = new RuntimePermissionPersistence(
runtimePermissionsPersistence);
mPermissionDataProvider = permissionDataProvider;
@@ -489,10 +487,6 @@ public final class Settings {
mRenamedPackages.remove(pkgName);
}
- public boolean canPropagatePermissionToInstantApp(String permName) {
- return mPermissions.canPropagatePermissionToInstantApp(permName);
- }
-
/** Gets and optionally creates a new shared user id. */
SharedUserSetting getSharedUserLPw(String name, int pkgFlags, int pkgPrivateFlags,
boolean create) throws PackageManagerException {
@@ -2128,23 +2122,14 @@ public final class Settings {
String tagName = parser.getName();
if (tagName.equals(TAG_ITEM)) {
String name = parser.getAttributeValue(null, ATTR_NAME);
-
- BasePermission bp = mPermissions.getPermission(name);
- if (bp == null) {
- Slog.w(PackageManagerService.TAG, "Unknown permission: " + name);
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
-
String grantedStr = parser.getAttributeValue(null, ATTR_GRANTED);
final boolean granted = grantedStr == null
|| Boolean.parseBoolean(grantedStr);
-
String flagsStr = parser.getAttributeValue(null, ATTR_FLAGS);
final int flags = (flagsStr != null)
? Integer.parseInt(flagsStr, 16) : 0;
-
- permissionsState.putInstallPermissionState(new PermissionState(bp, granted, flags));
+ permissionsState.putInstallPermissionState(new PermissionState(name, granted,
+ flags));
} else {
Slog.w(PackageManagerService.TAG, "Unknown element under <permissions>: "
+ parser.getName());
@@ -2867,10 +2852,6 @@ public final class Settings {
}
}
- void writePermissionLPr(XmlSerializer serializer, BasePermission bp) throws IOException {
- bp.writeLPr(serializer);
- }
-
boolean readLPw(@NonNull List<UserInfo> users) {
FileInputStream str = null;
if (mBackupSettingsFilename.exists()) {
@@ -4813,13 +4794,7 @@ public final class Settings {
&& !permissionNames.contains(perm)) {
continue;
}
- pw.print(prefix); pw.print(" "); pw.print(perm);
- final BasePermission bp = mPermissions.getPermission(perm);
- if (bp != null && bp.isHardOrSoftRestricted()) {
- pw.println(": restricted=true");
- } else {
- pw.println();
- }
+ pw.print(prefix); pw.print(" "); pw.println(perm);
}
}
@@ -5024,7 +4999,9 @@ public final class Settings {
void dumpPermissionsLPr(PrintWriter pw, String packageName, ArraySet<String> permissionNames,
DumpState dumpState) {
- mPermissions.dumpPermissions(pw, packageName, permissionNames,
+ LegacyPermissionSettings.dumpPermissions(pw, packageName, permissionNames,
+ mPermissionDataProvider.getLegacyPermissions(),
+ mPermissionDataProvider.getAllAppOpPermissionPackages(),
(mReadExternalStorageEnforced == Boolean.TRUE), dumpState);
}
@@ -5544,18 +5521,11 @@ public final class Settings {
int permissionsSize = permissions.size();
for (int i = 0; i < permissionsSize; i++) {
RuntimePermissionsState.PermissionState permission = permissions.get(i);
-
String name = permission.getName();
- BasePermission basePermission = mPermissions.getPermission(name);
- if (basePermission == null) {
- Slog.w(PackageManagerService.TAG, "Unknown permission:" + name);
- continue;
- }
boolean granted = permission.isGranted();
int flags = permission.getFlags();
-
- permissionsState.putRuntimePermissionState(new PermissionState(basePermission,
- granted, flags), userId);
+ permissionsState.putRuntimePermissionState(new PermissionState(name, granted,
+ flags), userId);
}
}
@@ -5650,23 +5620,14 @@ public final class Settings {
switch (parser.getName()) {
case TAG_ITEM: {
String name = parser.getAttributeValue(null, ATTR_NAME);
- BasePermission bp = mPermissions.getPermission(name);
- if (bp == null) {
- Slog.w(PackageManagerService.TAG, "Unknown permission:" + name);
- XmlUtils.skipCurrentTag(parser);
- continue;
- }
-
String grantedStr = parser.getAttributeValue(null, ATTR_GRANTED);
final boolean granted = grantedStr == null
|| Boolean.parseBoolean(grantedStr);
-
String flagsStr = parser.getAttributeValue(null, ATTR_FLAGS);
final int flags = (flagsStr != null)
? Integer.parseInt(flagsStr, 16) : 0;
-
- permissionsState.putRuntimePermissionState(new PermissionState(bp, granted,
- flags), userId);
+ permissionsState.putRuntimePermissionState(new PermissionState(name,
+ granted, flags), userId);
}
break;
}
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermission.java b/services/core/java/com/android/server/pm/permission/LegacyPermission.java
new file mode 100644
index 000000000000..a19a05ae021c
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermission.java
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.permission;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PermissionInfo;
+import android.util.Log;
+
+import com.android.server.pm.DumpState;
+import com.android.server.pm.PackageManagerService;
+
+import libcore.util.EmptyArray;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Legacy permission definition.
+ */
+//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+public final class LegacyPermission {
+ /**
+ * The permission is defined in a manifest.
+ */
+ public static final int TYPE_MANIFEST = 0;
+
+ /**
+ * The permission is defined in a system config.
+ */
+ public static final int TYPE_CONFIG = 1;
+
+ /**
+ * The permission is defined dynamically.
+ */
+ public static final int TYPE_DYNAMIC = 2;
+
+ /**
+ * @hide
+ */
+ @IntDef({
+ TYPE_MANIFEST,
+ TYPE_CONFIG,
+ TYPE_DYNAMIC,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PermissionType {}
+
+ private static final String ATTR_NAME = "name";
+ private static final String ATTR_PACKAGE = "package";
+ private static final String TAG_ITEM = "item";
+
+ @NonNull
+ private final PermissionInfo mPermissionInfo;
+ @PermissionType
+ private final int mType;
+ private final int mUid;
+ @NonNull
+ private final int[] mGids;
+
+ /**
+ * Create a new instance of this class.
+ *
+ * @param permissionInfo the {@link PermissionInfo} for the permission
+ * @param type the type of the permission
+ * @param uid the UID defining the permission
+ * @param gids the GIDs associated with the permission
+ */
+ public LegacyPermission(@NonNull PermissionInfo permissionInfo, @PermissionType int type,
+ int uid, @NonNull int[] gids) {
+ mPermissionInfo = permissionInfo;
+ mType = type;
+ mUid = uid;
+ mGids = gids;
+ }
+
+ private LegacyPermission(@NonNull String name, @NonNull String packageName,
+ @PermissionType int type) {
+ mPermissionInfo = new PermissionInfo();
+ mPermissionInfo.name = name;
+ mPermissionInfo.packageName = packageName;
+ // Default to most conservative protection level.
+ mPermissionInfo.protectionLevel = PermissionInfo.PROTECTION_SIGNATURE;
+ mType = type;
+ mUid = 0;
+ mGids = EmptyArray.INT;
+ }
+
+ /**
+ * Get the {@link PermissionInfo} for this mission.
+ *
+ * @return the {@link PermissionInfo}
+ */
+ @NonNull
+ public PermissionInfo getPermissionInfo() {
+ return mPermissionInfo;
+ }
+
+ /**
+ * Get the type of this mission.
+ *
+ * @return the type
+ */
+ public int getType() {
+ return mType;
+ }
+
+ /**
+ * @hide
+ */
+ public static boolean read(@NonNull Map<String, LegacyPermission> out,
+ @NonNull XmlPullParser parser) {
+ final String tagName = parser.getName();
+ if (!tagName.equals(TAG_ITEM)) {
+ return false;
+ }
+ final String name = parser.getAttributeValue(null, ATTR_NAME);
+ final String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
+ final String ptype = parser.getAttributeValue(null, "type");
+ if (name == null || packageName == null) {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Error in package manager settings: permissions has" + " no name at "
+ + parser.getPositionDescription());
+ return false;
+ }
+ final boolean dynamic = "dynamic".equals(ptype);
+ LegacyPermission bp = out.get(name);
+ // If the permission is builtin, do not clobber it.
+ if (bp == null || bp.mType != TYPE_CONFIG) {
+ bp = new LegacyPermission(name.intern(), packageName,
+ dynamic ? TYPE_DYNAMIC : TYPE_MANIFEST);
+ }
+ bp.mPermissionInfo.protectionLevel = readInt(parser, null, "protection",
+ PermissionInfo.PROTECTION_NORMAL);
+ bp.mPermissionInfo.protectionLevel = PermissionInfo.fixProtectionLevel(
+ bp.mPermissionInfo.protectionLevel);
+ if (dynamic) {
+ bp.mPermissionInfo.icon = readInt(parser, null, "icon", 0);
+ bp.mPermissionInfo.nonLocalizedLabel = parser.getAttributeValue(null, "label");
+ }
+ out.put(bp.mPermissionInfo.name, bp);
+ return true;
+ }
+
+ private static int readInt(@NonNull XmlPullParser parser, @Nullable String namespace,
+ @NonNull String name, int defaultValue) {
+ final String value = parser.getAttributeValue(namespace, name);
+ if (value == null) {
+ return defaultValue;
+ }
+ try {
+ return Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Error in package manager settings: attribute " + name
+ + " has bad integer value " + value + " at "
+ + parser.getPositionDescription());
+ return defaultValue;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void write(@NonNull XmlSerializer serializer) throws IOException {
+ if (mPermissionInfo.packageName == null) {
+ return;
+ }
+ serializer.startTag(null, TAG_ITEM);
+ serializer.attribute(null, ATTR_NAME, mPermissionInfo.name);
+ serializer.attribute(null, ATTR_PACKAGE, mPermissionInfo.packageName);
+ if (mPermissionInfo.protectionLevel != PermissionInfo.PROTECTION_NORMAL) {
+ serializer.attribute(null, "protection",
+ Integer.toString(mPermissionInfo.protectionLevel));
+ }
+ if (mType == TYPE_DYNAMIC) {
+ serializer.attribute(null, "type", "dynamic");
+ if (mPermissionInfo.icon != 0) {
+ serializer.attribute(null, "icon", Integer.toString(mPermissionInfo.icon));
+ }
+ if (mPermissionInfo.nonLocalizedLabel != null) {
+ serializer.attribute(null, "label", mPermissionInfo.nonLocalizedLabel.toString());
+ }
+ }
+ serializer.endTag(null, TAG_ITEM);
+ }
+
+ /**
+ * @hide
+ */
+ public boolean dump(@NonNull PrintWriter pw, @NonNull String packageName,
+ @NonNull Set<String> permissionNames, boolean readEnforced, boolean printedSomething,
+ @NonNull DumpState dumpState) {
+ if (packageName != null && !packageName.equals(mPermissionInfo.packageName)) {
+ return false;
+ }
+ if (permissionNames != null && !permissionNames.contains(mPermissionInfo.name)) {
+ return false;
+ }
+ if (!printedSomething) {
+ if (dumpState.onTitlePrinted()) {
+ pw.println();
+ }
+ pw.println("Permissions:");
+ }
+ pw.print(" Permission ["); pw.print(mPermissionInfo.name); pw.print("] (");
+ pw.print(Integer.toHexString(System.identityHashCode(this)));
+ pw.println("):");
+ pw.print(" sourcePackage="); pw.println(mPermissionInfo.packageName);
+ pw.print(" uid="); pw.print(mUid);
+ pw.print(" gids="); pw.print(Arrays.toString(mGids));
+ pw.print(" type="); pw.print(mType);
+ pw.print(" prot=");
+ pw.println(PermissionInfo.protectionToString(mPermissionInfo.protectionLevel));
+ if (mPermissionInfo != null) {
+ pw.print(" perm="); pw.println(mPermissionInfo);
+ if ((mPermissionInfo.flags & PermissionInfo.FLAG_INSTALLED) == 0
+ || (mPermissionInfo.flags & PermissionInfo.FLAG_REMOVED) != 0) {
+ pw.print(" flags=0x"); pw.println(Integer.toHexString(mPermissionInfo.flags));
+ }
+ }
+ if (Objects.equals(mPermissionInfo.name,
+ android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
+ pw.print(" enforced=");
+ pw.println(readEnforced);
+ }
+ return true;
+ }
+}
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionDataProvider.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionDataProvider.java
index 346a2c527fcb..0e790b1899ed 100644
--- a/services/core/java/com/android/server/pm/permission/LegacyPermissionDataProvider.java
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionDataProvider.java
@@ -19,12 +19,32 @@ package com.android.server.pm.permission;
import android.annotation.AppIdInt;
import android.annotation.NonNull;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
/**
* An interface for legacy code to read permission data in order to maintain compatibility.
*/
//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
public interface LegacyPermissionDataProvider {
/**
+ * Get all the legacy permissions currently registered in the system.
+ *
+ * @return the legacy permissions
+ */
+ @NonNull
+ List<LegacyPermission> getLegacyPermissions();
+
+ /**
+ * Get all the package names requesting app op permissions.
+ *
+ * @return a map of app op permission names to package names requesting them
+ */
+ @NonNull
+ Map<String, Set<String>> getAllAppOpPermissionPackages();
+
+ /**
* Get the legacy permission state of an app ID, either a package or a shared user.
*
* @param appId the app ID
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionSettings.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionSettings.java
new file mode 100644
index 000000000000..cc0b79872ba0
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionSettings.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.permission;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.XmlUtils;
+import com.android.server.pm.DumpState;
+import com.android.server.pm.PackageManagerService;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Legacy permission settings for migration.
+ */
+public class LegacyPermissionSettings {
+ /**
+ * All of the permissions known to the system. The mapping is from permission
+ * name to permission object.
+ */
+ @GuardedBy("mLock")
+ private final ArrayMap<String, LegacyPermission> mPermissions = new ArrayMap<>();
+
+ /**
+ * All permission trees known to the system. The mapping is from permission tree
+ * name to permission object.
+ */
+ @GuardedBy("mLock")
+ private final ArrayMap<String, LegacyPermission> mPermissionTrees = new ArrayMap<>();
+
+ @NonNull
+ private final Object mLock;
+
+ public LegacyPermissionSettings(@NonNull Object lock) {
+ mLock = lock;
+ }
+
+ @NonNull
+ public List<LegacyPermission> getPermissions() {
+ synchronized (mLock) {
+ return new ArrayList<>(mPermissions.values());
+ }
+ }
+
+ @NonNull
+ public List<LegacyPermission> getPermissionTrees() {
+ synchronized (mLock) {
+ return new ArrayList<>(mPermissionTrees.values());
+ }
+ }
+
+ public void replacePermissions(@NonNull List<LegacyPermission> permissions) {
+ synchronized (mLock) {
+ mPermissions.clear();
+ final int permissionsSize = permissions.size();
+ for (int i = 0; i < permissionsSize; i++) {
+ final LegacyPermission permission = permissions.get(i);
+ mPermissions.put(permission.getPermissionInfo().name, permission);
+ }
+ }
+ }
+
+ public void replacePermissionTrees(@NonNull List<LegacyPermission> permissionTrees) {
+ synchronized (mLock) {
+ mPermissionTrees.clear();
+ final int permissionsSize = permissionTrees.size();
+ for (int i = 0; i < permissionsSize; i++) {
+ final LegacyPermission permissionTree = permissionTrees.get(i);
+ mPermissionTrees.put(permissionTree.getPermissionInfo().name, permissionTree);
+ }
+ }
+ }
+
+ public void readPermissions(@NonNull XmlPullParser parser) throws IOException,
+ XmlPullParserException {
+ synchronized (mLock) {
+ readPermissions(mPermissions, parser);
+ }
+ }
+
+ public void readPermissionTrees(@NonNull XmlPullParser parser) throws IOException,
+ XmlPullParserException {
+ synchronized (mLock) {
+ readPermissions(mPermissionTrees, parser);
+ }
+ }
+
+ public static void readPermissions(@NonNull ArrayMap<String, LegacyPermission> out,
+ @NonNull XmlPullParser parser) throws IOException, XmlPullParserException {
+ int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
+ }
+
+ if (!LegacyPermission.read(out, parser)) {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Unknown element reading permissions: " + parser.getName() + " at "
+ + parser.getPositionDescription());
+ }
+ XmlUtils.skipCurrentTag(parser);
+ }
+ }
+
+ public void writePermissions(@NonNull XmlSerializer serializer) throws IOException {
+ synchronized (mLock) {
+ for (LegacyPermission bp : mPermissions.values()) {
+ bp.write(serializer);
+ }
+ }
+ }
+
+ public void writePermissionTrees(@NonNull XmlSerializer serializer) throws IOException {
+ synchronized (mLock) {
+ for (LegacyPermission bp : mPermissionTrees.values()) {
+ bp.write(serializer);
+ }
+ }
+ }
+
+ public static void dumpPermissions(@NonNull PrintWriter pw, @Nullable String packageName,
+ @Nullable ArraySet<String> permissionNames, @NonNull List<LegacyPermission> permissions,
+ @NonNull Map<String, Set<String>> appOpPermissionPackages,
+ boolean externalStorageEnforced, @NonNull DumpState dumpState) {
+ boolean printedSomething = false;
+ final int permissionsSize = permissions.size();
+ for (int i = 0; i < permissionsSize; i++) {
+ final LegacyPermission permission = permissions.get(i);
+ printedSomething = permission.dump(pw, packageName, permissionNames,
+ externalStorageEnforced, printedSomething, dumpState);
+ }
+ if (packageName == null && permissionNames == null) {
+ boolean firstEntry = true;
+ for (final Map.Entry<String, Set<String>> entry : appOpPermissionPackages.entrySet()) {
+ if (firstEntry) {
+ firstEntry = false;
+ if (dumpState.onTitlePrinted()) {
+ pw.println();
+ }
+ pw.println("AppOp Permissions:");
+ }
+ pw.print(" AppOp Permission ");
+ pw.print(entry.getKey());
+ pw.println(":");
+ for (final String appOpPackageName : entry.getValue()) {
+ pw.print(" ");
+ pw.println(appOpPackageName);
+ }
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionState.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionState.java
index 63f69cede59c..0e60367c243b 100644
--- a/services/core/java/com/android/server/pm/permission/LegacyPermissionState.java
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionState.java
@@ -252,7 +252,7 @@ public final class LegacyPermissionState {
*/
public static final class PermissionState {
@NonNull
- private final BasePermission mPermission;
+ private final String mName;
private final boolean mGranted;
@@ -261,40 +261,30 @@ public final class LegacyPermissionState {
/**
* Create a new instance of this class.
*
- * @param permission the {@link BasePermission} for the permission
+ * @param name the name of the permission
* @param granted whether the permission is granted
* @param flags the permission flags
*/
- public PermissionState(@NonNull BasePermission permission, boolean granted, int flags) {
- mPermission = permission;
+ public PermissionState(@NonNull String name, boolean granted, int flags) {
+ mName = name;
mGranted = granted;
mFlags = flags;
}
private PermissionState(@NonNull PermissionState other) {
- mPermission = other.mPermission;
+ mName = other.mName;
mGranted = other.mGranted;
mFlags = other.mFlags;
}
/**
- * Get the {@link BasePermission} for the permission.
- *
- * @return the {@link BasePermission}
- */
- @NonNull
- public BasePermission getPermission() {
- return mPermission;
- }
-
- /**
* Get the permission name.
*
* @return the permission name
*/
@NonNull
public String getName() {
- return mPermission.getName();
+ return mName;
}
/**
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/Permission.java
index 155d71673e06..4e8ddac88529 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/Permission.java
@@ -19,6 +19,7 @@ package com.android.server.pm.permission;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.UserIdInt;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PermissionInfo;
@@ -28,31 +29,25 @@ import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;
-import com.android.server.pm.DumpState;
import com.android.server.pm.PackageManagerService;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import libcore.util.EmptyArray;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
-import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.Arrays;
import java.util.Collection;
-import java.util.Map;
import java.util.Objects;
-import java.util.Set;
-public final class BasePermission {
- private static final String TAG = "PackageManager";
+/**
+ * Permission definition.
+ */
+public final class Permission {
+ private static final String TAG = "Permission";
- public static final int TYPE_MANIFEST = 0;
- public static final int TYPE_CONFIG = 1;
- public static final int TYPE_DYNAMIC = 2;
+ public static final int TYPE_MANIFEST = LegacyPermission.TYPE_MANIFEST;
+ public static final int TYPE_CONFIG = LegacyPermission.TYPE_CONFIG;
+ public static final int TYPE_DYNAMIC = LegacyPermission.TYPE_DYNAMIC;
@IntDef({
TYPE_MANIFEST,
TYPE_CONFIG,
@@ -70,18 +65,13 @@ public final class BasePermission {
@Retention(RetentionPolicy.SOURCE)
public @interface ProtectionLevel {}
- private static final String ATTR_NAME = "name";
- private static final String ATTR_PACKAGE = "package";
- private static final String TAG_ITEM = "item";
-
- private boolean mPermissionDefinitionChanged;
-
@NonNull
private PermissionInfo mPermissionInfo;
private boolean mReconciled;
- private final @PermissionType int mType;
+ @PermissionType
+ private final int mType;
/** UID that owns the definition of this permission */
private int mUid;
@@ -96,7 +86,10 @@ public final class BasePermission {
*/
private boolean mGidsPerUser;
- public BasePermission(@NonNull String name, String packageName, @PermissionType int type) {
+ private boolean mDefinitionChanged;
+
+ public Permission(@NonNull String name, @NonNull String packageName,
+ @PermissionType int type) {
mPermissionInfo = new PermissionInfo();
mPermissionInfo.name = name;
mPermissionInfo.packageName = packageName;
@@ -105,10 +98,27 @@ public final class BasePermission {
mType = type;
}
- @Override
- public String toString() {
- return "BasePermission{" + Integer.toHexString(System.identityHashCode(this)) + " "
- + mPermissionInfo.name + "}";
+ public Permission(@NonNull PermissionInfo permissionInfo, @PermissionType int type) {
+ mPermissionInfo = permissionInfo;
+ mType = type;
+ }
+
+ @NonNull
+ public PermissionInfo getPermissionInfo() {
+ return mPermissionInfo;
+ }
+
+ public void setPermissionInfo(@Nullable PermissionInfo permissionInfo) {
+ if (permissionInfo != null) {
+ mPermissionInfo = permissionInfo;
+ } else {
+ final PermissionInfo newPermissionInfo = new PermissionInfo();
+ newPermissionInfo.name = mPermissionInfo.name;
+ newPermissionInfo.packageName = mPermissionInfo.packageName;
+ newPermissionInfo.protectionLevel = mPermissionInfo.protectionLevel;
+ mPermissionInfo = newPermissionInfo;
+ }
+ mReconciled = permissionInfo != null;
}
@NonNull
@@ -120,14 +130,11 @@ public final class BasePermission {
return mPermissionInfo.protectionLevel;
}
+ @NonNull
public String getPackageName() {
return mPermissionInfo.packageName;
}
- public boolean isPermissionDefinitionChanged() {
- return mPermissionDefinitionChanged;
- }
-
public int getType() {
return mType;
}
@@ -136,34 +143,26 @@ public final class BasePermission {
return mUid;
}
- public void setGids(@NonNull int[] gids, boolean gidsPerUser) {
- mGids = gids;
- mGidsPerUser = gidsPerUser;
+ public boolean hasGids() {
+ return mGids.length != 0;
}
- public void setPermissionInfo(@Nullable PermissionInfo permissionInfo) {
- if (permissionInfo != null) {
- mPermissionInfo = permissionInfo;
- } else {
- final PermissionInfo newPermissionInfo = new PermissionInfo();
- newPermissionInfo.name = mPermissionInfo.name;
- newPermissionInfo.packageName = mPermissionInfo.packageName;
- newPermissionInfo.protectionLevel = mPermissionInfo.protectionLevel;
- mPermissionInfo = newPermissionInfo;
- }
- mReconciled = permissionInfo != null;
+ @NonNull
+ public int[] getRawGids() {
+ return mGids;
}
- public void setPermissionDefinitionChanged(boolean shouldOverride) {
- mPermissionDefinitionChanged = shouldOverride;
+ public boolean areGidsPerUser() {
+ return mGidsPerUser;
}
- public boolean hasGids() {
- return mGids.length != 0;
+ public void setGids(@NonNull int[] gids, boolean gidsPerUser) {
+ mGids = gids;
+ mGidsPerUser = gidsPerUser;
}
@NonNull
- public int[] computeGids(int userId) {
+ public int[] computeGids(@UserIdInt int userId) {
if (mGidsPerUser) {
final int[] userGids = new int[mGids.length];
for (int i = 0; i < mGids.length; i++) {
@@ -176,19 +175,28 @@ public final class BasePermission {
}
}
- public int calculateFootprint(BasePermission perm) {
- if (mUid == perm.mUid) {
- return perm.mPermissionInfo.name.length() + perm.mPermissionInfo.calculateFootprint();
+ public boolean isDefinitionChanged() {
+ return mDefinitionChanged;
+ }
+
+ public void setDefinitionChanged(boolean definitionChanged) {
+ mDefinitionChanged = definitionChanged;
+ }
+
+ public int calculateFootprint(@NonNull Permission permission) {
+ if (mUid == permission.mUid) {
+ return permission.mPermissionInfo.name.length()
+ + permission.mPermissionInfo.calculateFootprint();
}
return 0;
}
- public boolean isPermission(ParsedPermission perm) {
+ public boolean isPermission(@NonNull ParsedPermission parsedPermission) {
if (mPermissionInfo == null) {
return false;
}
- return Objects.equals(mPermissionInfo.packageName, perm.getPackageName())
- && Objects.equals(mPermissionInfo.name, perm.getName());
+ return Objects.equals(mPermissionInfo.packageName, parsedPermission.getPackageName())
+ && Objects.equals(mPermissionInfo.name, parsedPermission.getName());
}
public boolean isDynamic() {
@@ -323,8 +331,8 @@ public final class BasePermission {
return (mPermissionInfo.protectionLevel & PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO) != 0;
}
- public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) {
- if (!origPackageName.equals(mPermissionInfo.packageName)) {
+ public void transfer(@NonNull String oldPackageName, @NonNull String newPackageName) {
+ if (!oldPackageName.equals(mPermissionInfo.packageName)) {
return;
}
final PermissionInfo newPermissionInfo = new PermissionInfo();
@@ -339,28 +347,29 @@ public final class BasePermission {
}
public boolean addToTree(@ProtectionLevel int protectionLevel,
- @NonNull PermissionInfo permissionInfo, @NonNull BasePermission tree) {
+ @NonNull PermissionInfo permissionInfo, @NonNull Permission permissionTree) {
final boolean changed =
(mPermissionInfo.protectionLevel != protectionLevel
|| !mReconciled
- || mUid != tree.mUid
+ || mUid != permissionTree.mUid
|| !Objects.equals(mPermissionInfo.packageName,
- tree.mPermissionInfo.packageName)
+ permissionTree.mPermissionInfo.packageName)
|| !comparePermissionInfos(mPermissionInfo, permissionInfo));
mPermissionInfo = new PermissionInfo(permissionInfo);
- mPermissionInfo.packageName = tree.mPermissionInfo.packageName;
+ mPermissionInfo.packageName = permissionTree.mPermissionInfo.packageName;
mPermissionInfo.protectionLevel = protectionLevel;
mReconciled = true;
- mUid = tree.mUid;
+ mUid = permissionTree.mUid;
return changed;
}
- public void updateDynamicPermission(Collection<BasePermission> permissionTrees) {
- if (PackageManagerService.DEBUG_SETTINGS) Log.v(TAG, "Dynamic permission: name="
- + getName() + " pkg=" + getPackageName()
- + " info=" + mPermissionInfo);
+ public void updateDynamicPermission(@NonNull Collection<Permission> permissionTrees) {
+ if (PackageManagerService.DEBUG_SETTINGS) {
+ Log.v(TAG, "Dynamic permission: name=" + getName() + " pkg=" + getPackageName()
+ + " info=" + mPermissionInfo);
+ }
if (mType == TYPE_DYNAMIC) {
- final BasePermission tree = findPermissionTree(permissionTrees, mPermissionInfo.name);
+ final Permission tree = findPermissionTree(permissionTrees, mPermissionInfo.name);
if (tree != null) {
mPermissionInfo.packageName = tree.mPermissionInfo.packageName;
mReconciled = true;
@@ -369,75 +378,83 @@ public final class BasePermission {
}
}
- static BasePermission createOrUpdate(PackageManagerInternal packageManagerInternal,
- @Nullable BasePermission bp, @NonNull PermissionInfo p,
- @NonNull AndroidPackage pkg, Collection<BasePermission> permissionTrees,
+ public static boolean isOverridingSystemPermission(@Nullable Permission permission,
+ @NonNull PermissionInfo permissionInfo,
+ @NonNull PackageManagerInternal packageManagerInternal) {
+ if (permission == null || Objects.equals(permission.mPermissionInfo.packageName,
+ permissionInfo.packageName)) {
+ return false;
+ }
+ if (!permission.mReconciled) {
+ return false;
+ }
+ final AndroidPackage currentPackage = packageManagerInternal.getPackage(
+ permission.mPermissionInfo.packageName);
+ if (currentPackage == null) {
+ return false;
+ }
+ return currentPackage.isSystem();
+ }
+
+ @NonNull
+ public static Permission createOrUpdate(@Nullable Permission permission,
+ @NonNull PermissionInfo permissionInfo, @NonNull AndroidPackage pkg,
+ @NonNull Collection<Permission> permissionTrees, boolean isOverridingSystemPermission,
boolean chatty) {
// Allow system apps to redefine non-system permissions
boolean ownerChanged = false;
- if (bp != null && !Objects.equals(bp.mPermissionInfo.packageName, p.packageName)) {
- final boolean currentOwnerIsSystem;
- if (!bp.mReconciled) {
- currentOwnerIsSystem = false;
- } else {
- AndroidPackage currentPackage = packageManagerInternal.getPackage(
- bp.mPermissionInfo.packageName);
- if (currentPackage == null) {
- currentOwnerIsSystem = false;
- } else {
- currentOwnerIsSystem = currentPackage.isSystem();
- }
- }
-
+ if (permission != null && !Objects.equals(permission.mPermissionInfo.packageName,
+ permissionInfo.packageName)) {
if (pkg.isSystem()) {
- if (bp.mType == BasePermission.TYPE_CONFIG && !bp.mReconciled) {
+ if (permission.mType == Permission.TYPE_CONFIG && !permission.mReconciled) {
// It's a built-in permission and no owner, take ownership now
- p.flags |= PermissionInfo.FLAG_INSTALLED;
- bp.mPermissionInfo = p;
- bp.mReconciled = true;
- bp.mUid = pkg.getUid();
- } else if (!currentOwnerIsSystem) {
- String msg = "New decl " + pkg + " of permission "
- + p.name + " is system; overriding " + bp.mPermissionInfo.packageName;
- PackageManagerService.reportSettingsProblem(Log.WARN, msg);
+ permissionInfo.flags |= PermissionInfo.FLAG_INSTALLED;
+ permission.mPermissionInfo = permissionInfo;
+ permission.mReconciled = true;
+ permission.mUid = pkg.getUid();
+ } else if (!isOverridingSystemPermission) {
+ Slog.w(TAG, "New decl " + pkg + " of permission "
+ + permissionInfo.name + " is system; overriding "
+ + permission.mPermissionInfo.packageName);
ownerChanged = true;
- bp = null;
+ permission = null;
}
}
}
- if (bp == null) {
- bp = new BasePermission(p.name, p.packageName, TYPE_MANIFEST);
+ if (permission == null) {
+ permission = new Permission(permissionInfo.name, permissionInfo.packageName,
+ TYPE_MANIFEST);
}
- boolean wasNormal = bp.isNormal();
+ boolean wasNormal = permission.isNormal();
StringBuilder r = null;
- if (!bp.mReconciled) {
- if (bp.mPermissionInfo.packageName == null
- || bp.mPermissionInfo.packageName.equals(p.packageName)) {
- final BasePermission tree = findPermissionTree(permissionTrees, p.name);
+ if (!permission.mReconciled) {
+ if (permission.mPermissionInfo.packageName == null
+ || permission.mPermissionInfo.packageName.equals(permissionInfo.packageName)) {
+ final Permission tree = findPermissionTree(permissionTrees, permissionInfo.name);
if (tree == null
- || tree.mPermissionInfo.packageName.equals(p.packageName)) {
- p.flags |= PermissionInfo.FLAG_INSTALLED;
- bp.mPermissionInfo = p;
- bp.mReconciled = true;
- bp.mUid = pkg.getUid();
+ || tree.mPermissionInfo.packageName.equals(permissionInfo.packageName)) {
+ permissionInfo.flags |= PermissionInfo.FLAG_INSTALLED;
+ permission.mPermissionInfo = permissionInfo;
+ permission.mReconciled = true;
+ permission.mUid = pkg.getUid();
if (chatty) {
if (r == null) {
r = new StringBuilder(256);
} else {
r.append(' ');
}
- r.append(p.name);
+ r.append(permissionInfo.name);
}
} else {
- Slog.w(TAG, "Permission " + p.name + " from package "
- + p.packageName + " ignored: base tree "
+ Slog.w(TAG, "Permission " + permissionInfo.name + " from package "
+ + permissionInfo.packageName + " ignored: base tree "
+ tree.mPermissionInfo.name + " is from package "
+ tree.mPermissionInfo.packageName);
}
} else {
- Slog.w(TAG, "Permission " + p.name + " from package "
- + p.packageName + " ignored: original from "
- + bp.mPermissionInfo.packageName);
+ Slog.w(TAG, "Permission " + permissionInfo.name + " from package "
+ + permissionInfo.packageName + " ignored: original from "
+ + permission.mPermissionInfo.packageName);
}
} else if (chatty) {
if (r == null) {
@@ -446,42 +463,47 @@ public final class BasePermission {
r.append(' ');
}
r.append("DUP:");
- r.append(p.name);
+ r.append(permissionInfo.name);
}
- if (bp.isRuntime() && (ownerChanged || wasNormal)) {
+ if (permission.isRuntime() && (ownerChanged || wasNormal)) {
// If this is a runtime permission and the owner has changed, or this was a normal
// permission, then permission state should be cleaned up
- bp.mPermissionDefinitionChanged = true;
+ permission.mDefinitionChanged = true;
}
if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) {
Log.d(TAG, " Permissions: " + r);
}
- return bp;
+ return permission;
}
- static BasePermission enforcePermissionTree(
- Collection<BasePermission> permissionTrees, String permName, int callingUid) {
- if (permName != null) {
- BasePermission bp = findPermissionTree(permissionTrees, permName);
- if (bp != null) {
- if (bp.mUid == UserHandle.getAppId(callingUid)) {
- return bp;
+ @NonNull
+ public static Permission enforcePermissionTree(@NonNull Collection<Permission> permissionTrees,
+ @NonNull String permissionName, int callingUid) {
+ if (permissionName != null) {
+ final Permission permissionTree = Permission.findPermissionTree(permissionTrees,
+ permissionName);
+ if (permissionTree != null) {
+ if (permissionTree.getUid() == UserHandle.getAppId(callingUid)) {
+ return permissionTree;
}
throw new SecurityException("Calling uid " + callingUid
+ " is not allowed to add to permission tree "
- + bp.mPermissionInfo.name + " owned by uid " + bp.mUid);
+ + permissionTree.getName() + " owned by uid "
+ + permissionTree.getUid());
}
}
- throw new SecurityException("No permission tree found for " + permName);
+ throw new SecurityException("No permission tree found for " + permissionName);
}
- private static BasePermission findPermissionTree(
- Collection<BasePermission> permissionTrees, String permName) {
- for (BasePermission bp : permissionTrees) {
- if (permName.startsWith(bp.mPermissionInfo.name)
- && permName.length() > bp.mPermissionInfo.name.length()
- && permName.charAt(bp.mPermissionInfo.name.length()) == '.') {
- return bp;
+ @Nullable
+ private static Permission findPermissionTree(@NonNull Collection<Permission> permissionTrees,
+ @NonNull String permissionName) {
+ for (final Permission permissionTree : permissionTrees) {
+ final String permissionTreeName = permissionTree.getName();
+ if (permissionName.startsWith(permissionTreeName)
+ && permissionName.length() > permissionTreeName.length()
+ && permissionName.charAt(permissionTreeName.length()) == '.') {
+ return permissionTree;
}
}
return null;
@@ -512,7 +534,7 @@ public final class BasePermission {
@NonNull
public PermissionInfo generatePermissionInfo(int flags, int targetSdkVersion) {
- PermissionInfo permissionInfo;
+ final PermissionInfo permissionInfo;
if (mPermissionInfo != null) {
permissionInfo = new PermissionInfo(mPermissionInfo);
if ((flags & PackageManager.GET_META_DATA) != PackageManager.GET_META_DATA) {
@@ -539,79 +561,6 @@ public final class BasePermission {
return permissionInfo;
}
- public static boolean readLPw(@NonNull Map<String, BasePermission> out,
- @NonNull XmlPullParser parser) {
- final String tagName = parser.getName();
- if (!tagName.equals(TAG_ITEM)) {
- return false;
- }
- final String name = parser.getAttributeValue(null, ATTR_NAME);
- final String packageName = parser.getAttributeValue(null, ATTR_PACKAGE);
- final String ptype = parser.getAttributeValue(null, "type");
- if (name == null || packageName == null) {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Error in package manager settings: permissions has" + " no name at "
- + parser.getPositionDescription());
- return false;
- }
- final boolean dynamic = "dynamic".equals(ptype);
- BasePermission bp = out.get(name);
- // If the permission is builtin, do not clobber it.
- if (bp == null || bp.mType != TYPE_CONFIG) {
- bp = new BasePermission(name.intern(), packageName,
- dynamic ? TYPE_DYNAMIC : TYPE_MANIFEST);
- }
- bp.mPermissionInfo.protectionLevel = readInt(parser, null, "protection",
- PermissionInfo.PROTECTION_NORMAL);
- bp.mPermissionInfo.protectionLevel = PermissionInfo.fixProtectionLevel(
- bp.mPermissionInfo.protectionLevel);
- if (dynamic) {
- bp.mPermissionInfo.icon = readInt(parser, null, "icon", 0);
- bp.mPermissionInfo.nonLocalizedLabel = parser.getAttributeValue(null, "label");
- }
- out.put(bp.mPermissionInfo.name, bp);
- return true;
- }
-
- private static int readInt(XmlPullParser parser, String ns, String name, int defValue) {
- String v = parser.getAttributeValue(ns, name);
- try {
- if (v == null) {
- return defValue;
- }
- return Integer.parseInt(v);
- } catch (NumberFormatException e) {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Error in package manager settings: attribute " + name
- + " has bad integer value " + v + " at "
- + parser.getPositionDescription());
- }
- return defValue;
- }
-
- public void writeLPr(@NonNull XmlSerializer serializer) throws IOException {
- if (mPermissionInfo.packageName == null) {
- return;
- }
- serializer.startTag(null, TAG_ITEM);
- serializer.attribute(null, ATTR_NAME, mPermissionInfo.name);
- serializer.attribute(null, ATTR_PACKAGE, mPermissionInfo.packageName);
- if (mPermissionInfo.protectionLevel != PermissionInfo.PROTECTION_NORMAL) {
- serializer.attribute(null, "protection",
- Integer.toString(mPermissionInfo.protectionLevel));
- }
- if (mType == TYPE_DYNAMIC) {
- serializer.attribute(null, "type", "dynamic");
- if (mPermissionInfo.icon != 0) {
- serializer.attribute(null, "icon", Integer.toString(mPermissionInfo.icon));
- }
- if (mPermissionInfo.nonLocalizedLabel != null) {
- serializer.attribute(null, "label", mPermissionInfo.nonLocalizedLabel.toString());
- }
- }
- serializer.endTag(null, TAG_ITEM);
- }
-
private static boolean comparePermissionInfos(PermissionInfo pi1, PermissionInfo pi2) {
if (pi1.icon != pi2.icon) return false;
if (pi1.logo != pi2.logo) return false;
@@ -627,42 +576,4 @@ public final class BasePermission {
//if (pi1.descriptionRes != pi2.descriptionRes) return false;
return true;
}
-
- public boolean dumpPermissionsLPr(@NonNull PrintWriter pw, @NonNull String packageName,
- @NonNull Set<String> permissionNames, boolean readEnforced,
- boolean printedSomething, @NonNull DumpState dumpState) {
- if (packageName != null && !packageName.equals(mPermissionInfo.packageName)) {
- return false;
- }
- if (permissionNames != null && !permissionNames.contains(mPermissionInfo.name)) {
- return false;
- }
- if (!printedSomething) {
- if (dumpState.onTitlePrinted())
- pw.println();
- pw.println("Permissions:");
- }
- pw.print(" Permission ["); pw.print(mPermissionInfo.name); pw.print("] (");
- pw.print(Integer.toHexString(System.identityHashCode(this)));
- pw.println("):");
- pw.print(" sourcePackage="); pw.println(mPermissionInfo.packageName);
- pw.print(" uid="); pw.print(mUid);
- pw.print(" gids="); pw.print(Arrays.toString(computeGids(UserHandle.USER_SYSTEM)));
- pw.print(" type="); pw.print(mType);
- pw.print(" prot=");
- pw.println(PermissionInfo.protectionToString(mPermissionInfo.protectionLevel));
- if (mPermissionInfo != null) {
- pw.print(" perm="); pw.println(mPermissionInfo);
- if ((mPermissionInfo.flags & PermissionInfo.FLAG_INSTALLED) == 0
- || (mPermissionInfo.flags & PermissionInfo.FLAG_REMOVED) != 0) {
- pw.print(" flags=0x"); pw.println(Integer.toHexString(mPermissionInfo.flags));
- }
- }
- if (Objects.equals(mPermissionInfo.name,
- android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
- pw.print(" enforced=");
- pw.println(readEnforced);
- }
- return true;
- }
}
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 da4ef63d6945..81e8c2286755 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -224,6 +224,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private PermissionControllerManager mPermissionControllerManager;
/** Map of OneTimePermissionUserManagers keyed by userId */
+ @GuardedBy("mLock")
+ @NonNull
private final SparseArray<OneTimePermissionUserManager> mOneTimePermissionUserManagers =
new SparseArray<>();
@@ -252,12 +254,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
/** Internal storage for permissions and related settings */
@GuardedBy("mLock")
- private final PermissionSettings mSettings;
+ @NonNull
+ private final PermissionRegistry mRegistry = new PermissionRegistry();
/** Injector that can be used to facilitate testing. */
private final Injector mInjector;
@GuardedBy("mLock")
+ @Nullable
private ArraySet<String> mPrivappPermissionsViolations;
@GuardedBy("mLock")
@@ -267,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.
*
@@ -291,7 +288,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@GuardedBy("mLock")
private CheckPermissionDelegate mCheckPermissionDelegate;
- @GuardedBy("mLock")
+ @NonNull
private final OnPermissionChangeListeners mOnPermissionChangeListeners;
@GuardedBy("mLock")
@@ -309,7 +306,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// purposes. It may make sense to keep as an abstraction, but, the methods
// necessary to be overridden may be different than what was initially needed
// for the split.
- private PermissionCallback mDefaultPermissionCallback = new PermissionCallback() {
+ private final PermissionCallback mDefaultPermissionCallback = new PermissionCallback() {
@Override
public void onGidsChanged(int appId, int userId) {
mHandler.post(() -> killUid(appId, userId, KILL_APP_REASON_GIDS_CHANGED));
@@ -387,7 +384,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
mLock = externalLock;
mPackageManagerInt = LocalServices.getService(PackageManagerInternal.class);
mUserManagerInt = LocalServices.getService(UserManagerInternal.class);
- mSettings = new PermissionSettings(mLock);
mAppOpsManager = context.getSystemService(AppOpsManager.class);
mHandlerThread = new ServiceThread(TAG,
@@ -409,10 +405,10 @@ public class PermissionManagerService extends IPermissionManager.Stub {
synchronized (mLock) {
for (int i=0; i<permConfig.size(); i++) {
final SystemConfig.PermissionEntry perm = permConfig.valueAt(i);
- BasePermission bp = mSettings.getPermissionLocked(perm.name);
+ Permission bp = mRegistry.getPermission(perm.name);
if (bp == null) {
- bp = new BasePermission(perm.name, "android", BasePermission.TYPE_CONFIG);
- mSettings.putPermissionLocked(perm.name, bp);
+ bp = new Permission(perm.name, "android", Permission.TYPE_CONFIG);
+ mRegistry.addPermission(bp);
}
if (perm.gids != null) {
bp.setGids(perm.gids, perm.perUser);
@@ -484,13 +480,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
- @Nullable
- BasePermission getPermission(String permName) {
- synchronized (mLock) {
- return mSettings.getPermissionLocked(permName);
- }
- }
-
@Override
public String[] getAppOpPermissionPackages(String permName) {
return getAppOpPermissionPackagesInternal(permName, getCallingUid());
@@ -501,7 +490,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return null;
}
synchronized (mLock) {
- final ArraySet<String> pkgs = mSettings.mAppOpPermissionPackages.get(permName);
+ final ArraySet<String> pkgs = mRegistry.getAppOpPermissionPackages(permName);
if (pkgs == null) {
return null;
}
@@ -518,9 +507,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return ParceledListSlice.emptyList();
}
synchronized (mLock) {
- final int n = mSettings.mPermissionGroups.size();
- final ArrayList<PermissionGroupInfo> out = new ArrayList<>(n);
- for (ParsedPermissionGroup pg : mSettings.mPermissionGroups.values()) {
+ final List<PermissionGroupInfo> out = new ArrayList<>();
+ for (ParsedPermissionGroup pg : mRegistry.getPermissionGroups()) {
out.add(PackageInfoUtils.generatePermissionGroupInfo(pg, flags));
}
return new ParceledListSlice<>(out);
@@ -538,7 +526,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
synchronized (mLock) {
return PackageInfoUtils.generatePermissionGroupInfo(
- mSettings.mPermissionGroups.get(groupName), flags);
+ mRegistry.getPermissionGroup(groupName), flags);
}
}
@@ -555,7 +543,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final int targetSdkVersion = getPermissionInfoCallingTargetSdkVersion(opPackage,
callingUid);
synchronized (mLock) {
- final BasePermission bp = mSettings.getPermissionLocked(permName);
+ final Permission bp = mRegistry.getPermission(permName);
if (bp == null) {
return null;
}
@@ -585,11 +573,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return null;
}
synchronized (mLock) {
- if (groupName != null && !mSettings.mPermissionGroups.containsKey(groupName)) {
+ if (groupName != null && mRegistry.getPermissionGroup(groupName) == null) {
return null;
}
final ArrayList<PermissionInfo> out = new ArrayList<PermissionInfo>(10);
- for (BasePermission bp : mSettings.mPermissions.values()) {
+ for (Permission bp : mRegistry.getPermissions()) {
if (Objects.equals(bp.getGroup(), groupName)) {
out.add(bp.generatePermissionInfo(flags));
}
@@ -607,24 +595,23 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (info.labelRes == 0 && info.nonLocalizedLabel == null) {
throw new SecurityException("Label must be specified in permission");
}
- final BasePermission tree = mSettings.enforcePermissionTree(info.name, callingUid);
final boolean added;
final boolean changed;
synchronized (mLock) {
- BasePermission bp = mSettings.getPermissionLocked(info.name);
+ final Permission tree = mRegistry.enforcePermissionTree(info.name, callingUid);
+ Permission bp = mRegistry.getPermission(info.name);
added = bp == null;
int fixedLevel = PermissionInfo.fixProtectionLevel(info.protectionLevel);
if (added) {
enforcePermissionCapLocked(info, tree);
- bp = new BasePermission(info.name, tree.getPackageName(),
- BasePermission.TYPE_DYNAMIC);
+ bp = new Permission(info.name, tree.getPackageName(), Permission.TYPE_DYNAMIC);
} else if (!bp.isDynamic()) {
throw new SecurityException("Not allowed to modify non-dynamic permission "
+ info.name);
}
changed = bp.addToTree(fixedLevel, info, tree);
if (added) {
- mSettings.putPermissionLocked(info.name, bp);
+ mRegistry.addPermission(bp);
}
}
if (changed) {
@@ -639,9 +626,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
throw new SecurityException("Instant applications don't have access to this method");
}
- final BasePermission tree = mSettings.enforcePermissionTree(permName, callingUid);
synchronized (mLock) {
- final BasePermission bp = mSettings.getPermissionLocked(permName);
+ mRegistry.enforcePermissionTree(permName, callingUid);
+ final Permission bp = mRegistry.getPermission(permName);
if (bp == null) {
return;
}
@@ -650,9 +637,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
Slog.wtf(TAG, "Not allowed to modify non-dynamic permission "
+ permName);
}
- mSettings.removePermissionLocked(permName);
- mPackageManagerInt.writeSettings(false);
+ mRegistry.removePermission(permName);
}
+ mPackageManagerInt.writeSettings(false);
}
@Override
@@ -683,7 +670,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
synchronized (mLock) {
- if (mSettings.getPermissionLocked(permName) == null) {
+ if (mRegistry.getPermission(permName) == null) {
return 0;
}
@@ -808,14 +795,16 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
- final BasePermission bp;
+ final boolean isRuntimePermission;
final boolean permissionUpdated;
synchronized (mLock) {
- bp = mSettings.getPermissionLocked(permName);
+ final Permission bp = mRegistry.getPermission(permName);
if (bp == null) {
throw new IllegalArgumentException("Unknown permission: " + permName);
}
+ isRuntimePermission = bp.isRuntime();
+
if (bp.isInstallerExemptIgnored()) {
flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
}
@@ -834,14 +823,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
permissionUpdated = uidState.updatePermissionFlags(bp, flagMask, flagValues);
}
- if (permissionUpdated && bp.isRuntime()) {
+ if (permissionUpdated && isRuntimePermission) {
notifyRuntimePermissionStateChanged(packageName, userId);
}
if (permissionUpdated && callback != null) {
// Install and runtime permissions are stored in different places,
// so figure out what permission changed and persist the change.
- if (!bp.isRuntime()) {
- int userUid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid()));
+ if (!isRuntimePermission) {
+ int userUid = UserHandle.getUid(userId, pkg.getUid());
callback.onInstallPermissionUpdatedNotifyListener(userUid);
} else {
callback.onPermissionUpdatedNotifyListener(new int[]{userId}, false, pkg.getUid());
@@ -963,6 +952,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)) {
@@ -970,7 +960,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
if (isInstantApp) {
- return mSettings.isPermissionInstant(permissionName);
+ final Permission permission = mRegistry.getPermission(permissionName);
+ return permission != null && permission.isInstant();
}
return true;
@@ -1032,6 +1023,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);
@@ -1097,9 +1089,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS,
"addOnPermissionsChangeListener");
- synchronized (mLock) {
- mOnPermissionChangeListeners.addListenerLocked(listener);
- }
+ mOnPermissionChangeListeners.addListener(listener);
}
@Override
@@ -1107,9 +1097,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
@@ -1231,21 +1219,23 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private boolean checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(
@NonNull String permName) {
+ final boolean isImmutablyRestrictedPermission;
synchronized (mLock) {
- final BasePermission bp = mSettings.getPermissionLocked(permName);
+ final Permission bp = mRegistry.getPermission(permName);
if (bp == null) {
Slog.w(TAG, "No such permissions: " + permName);
return false;
}
- if (bp.isHardOrSoftRestricted() && bp.isImmutablyRestricted()
- && mContext.checkCallingOrSelfPermission(
- Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Cannot modify whitelisting of an immutably "
- + "restricted permission: " + permName);
- }
- return true;
+ isImmutablyRestrictedPermission = bp.isHardOrSoftRestricted()
+ && bp.isImmutablyRestricted();
+ }
+ if (isImmutablyRestrictedPermission && mContext.checkCallingOrSelfPermission(
+ Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Cannot modify whitelisting of an immutably "
+ + "restricted permission: " + permName);
}
+ return true;
}
@Override
@@ -1473,36 +1463,33 @@ public class PermissionManagerService extends IPermissionManager.Stub {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
- final BasePermission bp;
+ final boolean isSoftRestrictedPermission;
synchronized (mLock) {
- bp = mSettings.getPermissionLocked(permName);
- }
- if (bp == null) {
- throw new IllegalArgumentException("Unknown permission: " + permName);
- }
-
- if (!(bp.isRuntime() || bp.isDevelopment())) {
- throw new SecurityException("Permission " + permName + " requested by "
- + pkg.getPackageName() + " is not a changeable permission type");
+ final Permission permission = mRegistry.getPermission(permName);
+ isSoftRestrictedPermission = permission != null && permission.isSoftRestricted();
}
+ final boolean mayGrantSoftRestrictedPermission = isSoftRestrictedPermission
+ && SoftRestrictedPermissionPolicy.forPermission(mContext,
+ pkg.toAppInfoWithoutState(), pkg, UserHandle.of(userId), permName)
+ .mayGrantPermission();
- // If a permission review is required for legacy apps we represent
- // their permissions as always granted runtime ones since we need
- // to keep the review required permission flag per user while an
- // install permission's state is shared across all users.
- if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M && bp.isRuntime()) {
- return;
- }
+ final boolean isRuntimePermission;
+ final boolean isDevelopmentPermission;
+ final boolean permissionHasGids;
+ synchronized (mLock) {
+ final Permission bp = mRegistry.getPermission(permName);
+ if (bp == null) {
+ throw new IllegalArgumentException("Unknown permission: " + permName);
+ }
- if (bp.isSoftRestricted() && !SoftRestrictedPermissionPolicy.forPermission(mContext,
- pkg.toAppInfoWithoutState(), pkg, UserHandle.of(userId), permName)
- .mayGrantPermission()) {
- Log.e(TAG, "Cannot grant soft restricted permission " + permName + " for package "
- + packageName);
- return;
- }
+ isRuntimePermission = bp.isRuntime();
+ isDevelopmentPermission = bp.isDevelopment();
+ permissionHasGids = bp.hasGids();
+ if (!(isRuntimePermission || isDevelopmentPermission)) {
+ throw new SecurityException("Permission " + permName + " requested by "
+ + pkg.getPackageName() + " is not a changeable permission type");
+ }
- synchronized (mLock) {
final UidPermissionState uidState = getUidStateLocked(pkg, userId);
if (uidState == null) {
Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
@@ -1516,6 +1503,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
+ " has not requested permission " + permName);
}
+ // If a permission review is required for legacy apps we represent
+ // their permissions as always granted runtime ones since we need
+ // to keep the review required permission flag per user while an
+ // install permission's state is shared across all users.
+ if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.M && bp.isRuntime()) {
+ return;
+ }
+
final int flags = uidState.getPermissionFlags(permName);
if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
Log.e(TAG, "Cannot grant system fixed permission "
@@ -1535,6 +1530,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return;
}
+ if (bp.isSoftRestricted() && !mayGrantSoftRestrictedPermission) {
+ Log.e(TAG, "Cannot grant soft restricted permission " + permName + " for package "
+ + packageName);
+ return;
+ }
+
if (bp.isDevelopment()) {
// Development permissions must be handled specially, since they are not
// normal runtime permissions. For now they apply to all users.
@@ -1560,23 +1561,23 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
- if (bp.isRuntime()) {
+ if (isRuntimePermission) {
logPermission(MetricsEvent.ACTION_PERMISSION_GRANTED, permName, packageName);
}
- final int uid = UserHandle.getUid(userId, UserHandle.getAppId(pkg.getUid()));
+ final int uid = UserHandle.getUid(userId, pkg.getUid());
if (callback != null) {
- if (bp.isDevelopment()) {
+ if (isDevelopmentPermission) {
callback.onInstallPermissionGranted();
} else {
callback.onPermissionGranted(uid, userId);
}
- if (bp.hasGids()) {
+ if (permissionHasGids) {
callback.onGidsChanged(UserHandle.getAppId(pkg.getUid()), userId);
}
}
- if (bp.isRuntime()) {
+ if (isRuntimePermission) {
notifyRuntimePermissionStateChanged(packageName, userId);
}
}
@@ -1627,17 +1628,22 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (mPackageManagerInt.filterAppAccess(pkg, callingUid, userId)) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
- final BasePermission bp = mSettings.getPermission(permName);
- if (bp == null) {
- throw new IllegalArgumentException("Unknown permission: " + permName);
- }
-
- if (!(bp.isRuntime() || bp.isDevelopment())) {
- throw new SecurityException("Permission " + permName + " requested by "
- + pkg.getPackageName() + " is not a changeable permission type");
- }
+ final boolean isRuntimePermission;
+ final boolean isDevelopmentPermission;
synchronized (mLock) {
+ final Permission bp = mRegistry.getPermission(permName);
+ if (bp == null) {
+ throw new IllegalArgumentException("Unknown permission: " + permName);
+ }
+
+ isRuntimePermission = bp.isRuntime();
+ isDevelopmentPermission = bp.isDevelopment();
+ if (!(isRuntimePermission || isDevelopmentPermission)) {
+ throw new SecurityException("Permission " + permName + " requested by "
+ + pkg.getPackageName() + " is not a changeable permission type");
+ }
+
final UidPermissionState uidState = getUidStateLocked(pkg, userId);
if (uidState == null) {
Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
@@ -1680,20 +1686,20 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
- if (bp.isRuntime()) {
+ if (isRuntimePermission) {
logPermission(MetricsEvent.ACTION_PERMISSION_REVOKED, permName, packageName);
}
if (callback != null) {
- if (bp.isDevelopment()) {
+ if (isDevelopmentPermission) {
mDefaultPermissionCallback.onInstallPermissionRevoked();
} else {
- callback.onPermissionRevoked(UserHandle.getUid(userId,
- UserHandle.getAppId(pkg.getUid())), userId, reason);
+ callback.onPermissionRevoked(UserHandle.getUid(userId, pkg.getUid()), userId,
+ reason);
}
}
- if (bp.isRuntime()) {
+ if (isRuntimePermission) {
notifyRuntimePermissionStateChanged(packageName, userId);
}
}
@@ -1808,16 +1814,18 @@ public class PermissionManagerService extends IPermissionManager.Stub {
for (int i = 0; i < permissionCount; i++) {
final String permName = pkg.getRequestedPermissions().get(i);
- final BasePermission bp;
+
+ final boolean isRuntimePermission;
synchronized (mLock) {
- bp = mSettings.getPermissionLocked(permName);
- }
- if (bp == null) {
- continue;
- }
+ final Permission permission = mRegistry.getPermission(permName);
+ if (permission == null) {
+ continue;
+ }
- if (bp.isRemoved()) {
- continue;
+ if (permission.isRemoved()) {
+ continue;
+ }
+ isRuntimePermission = permission.isRuntime();
}
// If shared user we just reset the state to which only this app contributed.
@@ -1847,7 +1855,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// permission as requiring a review as this is the initial state.
final int uid = mPackageManagerInt.getPackageUid(packageName, 0, userId);
final int targetSdk = mPackageManagerInt.getUidTargetSdkVersion(uid);
- final int flags = (targetSdk < Build.VERSION_CODES.M && bp.isRuntime())
+ final int flags = (targetSdk < Build.VERSION_CODES.M && isRuntimePermission)
? FLAG_PERMISSION_REVIEW_REQUIRED | FLAG_PERMISSION_REVOKED_COMPAT
: 0;
@@ -1856,7 +1864,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
false, delayingPermCallback);
// Below is only runtime permission handling.
- if (!bp.isRuntime()) {
+ if (!isRuntimePermission) {
continue;
}
@@ -2093,13 +2101,15 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return false;
}
- BasePermission permission = getPermission(permName);
- if (permission == null) {
- return false;
- }
- if (permission.isHardRestricted()
- && (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) == 0) {
- return false;
+ synchronized (mLock) {
+ final Permission permission = mRegistry.getPermission(permName);
+ if (permission == null) {
+ return false;
+ }
+ if (permission.isHardRestricted()
+ && (flags & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) == 0) {
+ return false;
+ }
}
final long token = Binder.clearCallingIdentity();
@@ -2178,8 +2188,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private void restoreRuntimePermissions(@NonNull byte[] backup, @NonNull UserHandle user) {
synchronized (mLock) {
mHasNoDelayedPermBackup.delete(user.getIdentifier());
- mPermissionControllerManager.stageAndApplyRuntimePermissionsBackup(backup, user);
}
+ mPermissionControllerManager.stageAndApplyRuntimePermissionsBackup(backup, user);
}
/**
@@ -2198,18 +2208,16 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (mHasNoDelayedPermBackup.get(user.getIdentifier(), false)) {
return;
}
-
- mPermissionControllerManager.applyStagedRuntimePermissionBackup(packageName, user,
- mContext.getMainExecutor(), (hasMoreBackup) -> {
- if (hasMoreBackup) {
- return;
- }
-
- synchronized (mLock) {
- mHasNoDelayedPermBackup.put(user.getIdentifier(), true);
- }
- });
}
+ mPermissionControllerManager.applyStagedRuntimePermissionBackup(packageName, user,
+ mContext.getMainExecutor(), (hasMoreBackup) -> {
+ if (hasMoreBackup) {
+ return;
+ }
+ synchronized (mLock) {
+ mHasNoDelayedPermBackup.put(user.getIdentifier(), true);
+ }
+ });
}
private void addOnRuntimePermissionStateChangedListener(@NonNull
@@ -2347,10 +2355,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final int callingUid = Binder.getCallingUid();
for (int permNum = 0; permNum < numPermissions; permNum++) {
- String permName = permissionsToRevoke.get(permNum);
- BasePermission bp = mSettings.getPermission(permName);
- if (bp == null || !bp.isRuntime()) {
- continue;
+ final String permName = permissionsToRevoke.get(permNum);
+ synchronized (mLock) {
+ final Permission bp = mRegistry.getPermission(permName);
+ if (bp == null || !bp.isRuntime()) {
+ continue;
+ }
}
for (int userIdNum = 0; userIdNum < numUserIds; userIdNum++) {
final int userId = userIds[userIdNum];
@@ -2388,7 +2398,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
}
- bp.setPermissionDefinitionChanged(false);
}
}
@@ -2401,13 +2410,15 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// Assume by default that we did not install this permission into the system.
p.setFlags(p.getFlags() & ~PermissionInfo.FLAG_INSTALLED);
+ final PermissionInfo permissionInfo;
+ final Permission oldPermission;
synchronized (mLock) {
// Now that permission groups have a special meaning, we ignore permission
// groups for legacy apps to prevent unexpected behavior. In particular,
// permissions for one app being granted to someone just because they happen
// to be in a group defined by another app (before this had no implications).
if (pkg.getTargetSdkVersion() > Build.VERSION_CODES.LOLLIPOP_MR1) {
- p.setParsedPermissionGroup(mSettings.mPermissionGroups.get(p.getGroup()));
+ p.setParsedPermissionGroup(mRegistry.getPermissionGroup(p.getGroup()));
// Warn for a permission in an unknown group.
if (DEBUG_PERMISSIONS
&& p.getGroup() != null && p.getParsedPermissionGroup() == null) {
@@ -2416,27 +2427,30 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
- final PermissionInfo permissionInfo = PackageInfoUtils.generatePermissionInfo(p,
+ permissionInfo = PackageInfoUtils.generatePermissionInfo(p,
PackageManager.GET_META_DATA);
- final BasePermission bp;
+ oldPermission = p.isTree() ? mRegistry.getPermissionTree(p.getName())
+ : mRegistry.getPermission(p.getName());
+ }
+ // TODO(zhanghai): Maybe we should store whether a permission is owned by system inside
+ // itself.
+ final boolean isOverridingSystemPermission = Permission.isOverridingSystemPermission(
+ oldPermission, permissionInfo, mPackageManagerInt);
+ synchronized (mLock) {
+ final Permission permission = Permission.createOrUpdate(oldPermission,
+ permissionInfo, pkg, mRegistry.getPermissionTrees(),
+ isOverridingSystemPermission, chatty);
if (p.isTree()) {
- bp = BasePermission.createOrUpdate(
- mPackageManagerInt,
- mSettings.getPermissionTreeLocked(p.getName()), permissionInfo, pkg,
- mSettings.getAllPermissionTreesLocked(), chatty);
- mSettings.putPermissionTreeLocked(p.getName(), bp);
+ mRegistry.addPermissionTree(permission);
} else {
- bp = BasePermission.createOrUpdate(
- mPackageManagerInt,
- mSettings.getPermissionLocked(p.getName()),
- permissionInfo, pkg, mSettings.getAllPermissionTreesLocked(), chatty);
- mSettings.putPermissionLocked(p.getName(), bp);
+ mRegistry.addPermission(permission);
}
- if (bp.isInstalled()) {
+ if (permission.isInstalled()) {
p.setFlags(p.getFlags() | PermissionInfo.FLAG_INSTALLED);
}
- if (bp.isPermissionDefinitionChanged()) {
+ if (permission.isDefinitionChanged()) {
definitionChangedPermissions.add(p.getName());
+ permission.setDefinitionChanged(false);
}
}
}
@@ -2444,45 +2458,46 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
private void addAllPermissionGroups(AndroidPackage pkg, boolean chatty) {
- final int N = ArrayUtils.size(pkg.getPermissionGroups());
- StringBuilder r = null;
- for (int i=0; i<N; i++) {
- final ParsedPermissionGroup pg = pkg.getPermissionGroups().get(i);
- final ParsedPermissionGroup cur = mSettings.mPermissionGroups.get(pg.getName());
- final String curPackageName = (cur == null) ? null : cur.getPackageName();
- final boolean isPackageUpdate = pg.getPackageName().equals(curPackageName);
- if (cur == null || isPackageUpdate) {
- mSettings.mPermissionGroups.put(pg.getName(), pg);
- if (chatty && DEBUG_PACKAGE_SCANNING) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
- }
- if (isPackageUpdate) {
- r.append("UPD:");
+ synchronized (mLock) {
+ final int N = ArrayUtils.size(pkg.getPermissionGroups());
+ StringBuilder r = null;
+ for (int i = 0; i < N; i++) {
+ final ParsedPermissionGroup pg = pkg.getPermissionGroups().get(i);
+ final ParsedPermissionGroup cur = mRegistry.getPermissionGroup(pg.getName());
+ final String curPackageName = (cur == null) ? null : cur.getPackageName();
+ final boolean isPackageUpdate = pg.getPackageName().equals(curPackageName);
+ if (cur == null || isPackageUpdate) {
+ mRegistry.addPermissionGroup(pg);
+ if (chatty && DEBUG_PACKAGE_SCANNING) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
+ }
+ if (isPackageUpdate) {
+ r.append("UPD:");
+ }
+ r.append(pg.getName());
}
- r.append(pg.getName());
- }
- } else {
- Slog.w(TAG, "Permission group " + pg.getName() + " from package "
- + pg.getPackageName() + " ignored: original from "
- + cur.getPackageName());
- if (chatty && DEBUG_PACKAGE_SCANNING) {
- if (r == null) {
- r = new StringBuilder(256);
- } else {
- r.append(' ');
+ } else {
+ Slog.w(TAG, "Permission group " + pg.getName() + " from package "
+ + pg.getPackageName() + " ignored: original from "
+ + cur.getPackageName());
+ if (chatty && DEBUG_PACKAGE_SCANNING) {
+ if (r == null) {
+ r = new StringBuilder(256);
+ } else {
+ r.append(' ');
+ }
+ r.append("DUP:");
+ r.append(pg.getName());
}
- r.append("DUP:");
- r.append(pg.getName());
}
}
+ if (r != null && DEBUG_PACKAGE_SCANNING) {
+ Log.d(TAG, " Permission Groups: " + r);
+ }
}
- if (r != null && DEBUG_PACKAGE_SCANNING) {
- Log.d(TAG, " Permission Groups: " + r);
- }
-
}
private void removeAllPermissions(AndroidPackage pkg, boolean chatty) {
@@ -2491,9 +2506,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
StringBuilder r = null;
for (int i=0; i<N; i++) {
ParsedPermission p = pkg.getPermissions().get(i);
- BasePermission bp = mSettings.mPermissions.get(p.getName());
+ Permission bp = mRegistry.getPermission(p.getName());
if (bp == null) {
- bp = mSettings.mPermissionTrees.get(p.getName());
+ bp = mRegistry.getPermissionTree(p.getName());
}
if (bp != null && bp.isPermission(p)) {
bp.setPermissionInfo(null);
@@ -2507,11 +2522,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
if (p.isAppOp()) {
- ArraySet<String> appOpPkgs =
- mSettings.mAppOpPermissionPackages.get(p.getName());
- if (appOpPkgs != null) {
- appOpPkgs.remove(pkg.getPackageName());
- }
+ // TODO(zhanghai): Should we just remove the entry for this permission directly?
+ mRegistry.removeAppOpPermissionPackage(p.getName(), pkg.getPackageName());
}
}
if (r != null) {
@@ -2521,15 +2533,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
N = pkg.getRequestedPermissions().size();
r = null;
for (int i=0; i<N; i++) {
- String perm = pkg.getRequestedPermissions().get(i);
- if (mSettings.isPermissionAppOp(perm)) {
- ArraySet<String> appOpPkgs = mSettings.mAppOpPermissionPackages.get(perm);
- if (appOpPkgs != null) {
- appOpPkgs.remove(pkg.getPackageName());
- if (appOpPkgs.isEmpty()) {
- mSettings.mAppOpPermissionPackages.remove(perm);
- }
- }
+ final String permissionName = pkg.getRequestedPermissions().get(i);
+ final Permission permission = mRegistry.getPermission(permissionName);
+ if (permission != null && permission.isAppOp()) {
+ mRegistry.removeAppOpPermissionPackage(permissionName,
+ pkg.getPackageName());
}
}
if (r != null) {
@@ -2567,7 +2575,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final Set<String> instantPermissions =
new ArraySet<>(uidState.getGrantedPermissions());
instantPermissions.removeIf(permissionName -> {
- BasePermission permission = mSettings.getPermission(permissionName);
+ Permission permission = mRegistry.getPermission(permissionName);
if (permission == null) {
return true;
}
@@ -2585,11 +2593,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@NonNull
private int[] getPermissionGids(@NonNull String permissionName, @UserIdInt int userId) {
- BasePermission permission = mSettings.getPermission(permissionName);
- if (permission == null) {
- return EmptyArray.INT;
+ synchronized (mLock) {
+ Permission permission = mRegistry.getPermission(permissionName);
+ if (permission == null) {
+ return EmptyArray.INT;
+ }
+ return permission.computeGids(userId);
}
- return permission.computeGids(userId);
}
/**
@@ -2638,12 +2648,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
for (int i = 0; i < requestedPermissionsSize; i++) {
final String permissionName = pkg.getRequestedPermissions().get(i);
- final BasePermission permission = mSettings.getPermission(permissionName);
+ final Permission permission;
+ synchronized (mLock) {
+ permission = mRegistry.getPermission(permissionName);
+ }
if (permission == null) {
continue;
}
- if (permission.isSignature() && shouldGrantSignaturePermission(pkg, ps,
- permission)) {
+ if (permission.isSignature() && shouldGrantSignaturePermission(pkg, ps, permission)) {
shouldGrantSignaturePermission.add(permissionName);
}
}
@@ -2683,7 +2695,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
for (String permissionName : uidRequestedPermissions) {
- BasePermission permission = mSettings.getPermission(permissionName);
+ Permission permission = mRegistry.getPermission(permissionName);
if (permission == null) {
continue;
}
@@ -2725,12 +2737,10 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// the runtime ones are written only if changed. The only cases of
// changed runtime permissions here are promotion of an install to
// runtime and revocation of a runtime from a shared user.
- synchronized (mLock) {
- if (revokeUnusedSharedUserPermissionsLocked(
- ps.getSharedUser().getPackages(), uidState)) {
- updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
- runtimePermissionsRevoked = true;
- }
+ if (revokeUnusedSharedUserPermissionsLocked(
+ ps.getSharedUser().getPackages(), uidState)) {
+ updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
+ runtimePermissionsRevoked = true;
}
}
}
@@ -2741,7 +2751,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
for (int i = 0; i < requestedPermissionsSize; i++) {
final String permName = requestedPermissions.get(i);
- final BasePermission bp = mSettings.getPermission(permName);
+ final Permission bp = mRegistry.getPermission(permName);
final boolean appSupportsRuntimePermissions =
pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M;
String legacyActivityRecognitionPermission = null;
@@ -2834,7 +2844,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// Keep track of app op permissions.
if (bp.isAppOp()) {
- mSettings.addAppOpPackage(perm, pkg.getPackageName());
+ mRegistry.addAppOpPermissionPackage(perm, pkg.getPackageName());
}
boolean shouldGrantNormalPermission = true;
@@ -3049,6 +3059,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();
@@ -3057,7 +3068,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
for (String permission : ps.getGrantedPermissions()) {
if (!pkg.getImplicitPermissions().contains(permission)) {
- BasePermission bp = mSettings.getPermissionLocked(permission);
+ Permission bp = mRegistry.getPermission(permission);
if (bp != null && bp.isRuntime()) {
int flags = ps.getPermissionFlags(permission);
@@ -3101,6 +3112,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) {
@@ -3131,11 +3143,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
+ " for " + pkgName);
}
- ps.grantPermission(mSettings.getPermissionLocked(newPerm));
+ ps.grantPermission(mRegistry.getPermission(newPerm));
}
// Add permission flags
- ps.updatePermissionFlags(mSettings.getPermission(newPerm), flags, flags);
+ ps.updatePermissionFlags(mRegistry.getPermission(newPerm), flags, flags);
}
/**
@@ -3172,6 +3184,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,
@@ -3206,7 +3219,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
ArraySet<String> sourcePerms = newToSplitPerms.get(newPerm);
if (sourcePerms != null) {
- BasePermission bp = mSettings.getPermissionLocked(newPerm);
+ Permission bp = mRegistry.getPermission(newPerm);
if (bp.isRuntime()) {
if (!newPerm.equals(Manifest.permission.ACTIVITY_RECOGNITION)) {
@@ -3221,7 +3234,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
for (int sourcePermNum = 0; sourcePermNum < sourcePerms.size();
sourcePermNum++) {
final String sourcePerm = sourcePerms.valueAt(sourcePermNum);
- BasePermission sourceBp = mSettings.getPermissionLocked(sourcePerm);
+ Permission sourceBp = mRegistry.getPermission(sourcePerm);
if (!sourceBp.isRuntime()) {
inheritsFromInstallPerm = true;
break;
@@ -3344,7 +3357,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
private boolean shouldGrantSignaturePermission(@NonNull AndroidPackage pkg,
- @NonNull PackageSetting pkgSetting, @NonNull BasePermission bp) {
+ @NonNull PackageSetting pkgSetting, @NonNull Permission bp) {
// expect single system package
String systemPackageName = ArrayUtils.firstOrNull(mPackageManagerInt.getKnownPackageNames(
PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM));
@@ -3510,7 +3523,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@NonNull
private PackageParser.SigningDetails getSourcePackageSigningDetails(
- @NonNull BasePermission bp) {
+ @NonNull Permission bp) {
final PackageSetting ps = getSourcePackageSetting(bp);
if (ps == null) {
return PackageParser.SigningDetails.UNKNOWN;
@@ -3519,13 +3532,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Nullable
- private PackageSetting getSourcePackageSetting(@NonNull BasePermission bp) {
+ private PackageSetting getSourcePackageSetting(@NonNull Permission bp) {
final String sourcePackageName = bp.getPackageName();
return mPackageManagerInt.getPackageSetting(sourcePackageName);
}
private boolean canGrantPrivilegedPermission(@NonNull AndroidPackage pkg,
- boolean isUpdatedSystemApp, @NonNull BasePermission permission) {
+ boolean isUpdatedSystemApp, @NonNull Permission permission) {
if (!pkg.isPrivileged()) {
return false;
}
@@ -3563,11 +3576,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);
}
}
}
@@ -3671,15 +3686,16 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final boolean instantApp = mPackageManagerInt.isInstantApp(pkg.getPackageName(), userId);
for (String permission : pkg.getRequestedPermissions()) {
- final BasePermission bp;
+ final boolean shouldGrantPermission;
synchronized (mLock) {
- bp = mSettings.getPermissionLocked(permission);
- }
- if (bp != null && (bp.isRuntime() || bp.isDevelopment())
- && (!instantApp || bp.isInstant())
- && (supportsRuntimePermissions || !bp.isRuntimeOnly())
- && (grantedPermissions == null
- || ArrayUtils.contains(grantedPermissions, permission))) {
+ final Permission bp = mRegistry.getPermission(permission);
+ shouldGrantPermission = bp != null && (bp.isRuntime() || bp.isDevelopment())
+ && (!instantApp || bp.isInstant())
+ && (supportsRuntimePermissions || !bp.isRuntimeOnly())
+ && (grantedPermissions == null
+ || ArrayUtils.contains(grantedPermissions, permission));
+ }
+ if (shouldGrantPermission) {
final int flags = getPermissionFlagsInternal(permission, pkg.getPackageName(),
callingUid, userId);
if (supportsRuntimePermissions) {
@@ -3713,14 +3729,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
for (int j = 0; j < permissionCount; j++) {
final String permissionName = pkg.getRequestedPermissions().get(j);
- final BasePermission bp = mSettings.getPermissionLocked(permissionName);
-
- if (bp == null || !bp.isHardOrSoftRestricted()) {
- continue;
- }
-
final boolean isGranted;
synchronized (mLock) {
+ final Permission bp = mRegistry.getPermission(permissionName);
+ if (bp == null || !bp.isHardOrSoftRestricted()) {
+ continue;
+ }
+
final UidPermissionState uidState = getUidStateLocked(pkg, userId);
if (uidState == null) {
Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName()
@@ -3874,11 +3889,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
int affectedUserId = UserHandle.USER_NULL;
// Update permissions
for (String eachPerm : deletedPs.pkg.getRequestedPermissions()) {
- BasePermission bp = mSettings.getPermission(eachPerm);
- if (bp == null) {
- continue;
- }
-
// Check if another package in the shared user needs the permission.
boolean used = false;
final List<AndroidPackage> pkgs = sus.getPackages();
@@ -3922,6 +3932,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
continue;
}
+ Permission bp = mRegistry.getPermission(eachPerm);
+ if (bp == null) {
+ continue;
+ }
+
// TODO(zhanghai): Why are we only killing the UID when GIDs changed, instead of any
// permission change?
if (uidState.removePermissionState(bp.getName()) && bp.hasGids()) {
@@ -3948,7 +3963,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final int requestedPermCount = pkg.getRequestedPermissions().size();
for (int j = 0; j < requestedPermCount; j++) {
String permission = pkg.getRequestedPermissions().get(j);
- BasePermission bp = mSettings.getPermissionLocked(permission);
+ Permission bp = mRegistry.getPermission(permission);
if (bp != null) {
usedPermissions.add(permission);
}
@@ -3963,7 +3978,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
for (int i = permissionStatesSize - 1; i >= 0; i--) {
PermissionState permissionState = permissionStates.get(i);
if (!usedPermissions.contains(permissionState.getName())) {
- BasePermission bp = mSettings.getPermissionLocked(permissionState.getName());
+ Permission bp = mRegistry.getPermission(permissionState.getName());
if (bp != null) {
if (uidState.removePermissionState(bp.getName())
&& permissionState.isRuntime()) {
@@ -4026,35 +4041,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 (BasePermission bp : mSettings.getAllPermissionsLocked()) {
- 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.
*/
@@ -4127,8 +4113,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) {
@@ -4180,13 +4164,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
boolean changed = false;
- Set<BasePermission> needsUpdate = null;
+ Set<Permission> needsUpdate = null;
synchronized (mLock) {
- final Iterator<BasePermission> it = mSettings.mPermissions.values().iterator();
- while (it.hasNext()) {
- final BasePermission bp = it.next();
+ for (final Permission bp : mRegistry.getPermissions()) {
if (bp.isDynamic()) {
- bp.updateDynamicPermission(mSettings.mPermissionTrees.values());
+ bp.updateDynamicPermission(mRegistry.getPermissionTrees());
}
if (!packageName.equals(bp.getPackageName())) {
// Not checking sourcePackageSetting because it can be null when
@@ -4198,13 +4180,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// Set to changed for either install or uninstall
changed = true;
if (needsUpdate == null) {
- needsUpdate = new ArraySet<>(mSettings.mPermissions.size());
+ needsUpdate = new ArraySet<>();
}
needsUpdate.add(bp);
}
}
if (needsUpdate != null) {
- for (final BasePermission bp : needsUpdate) {
+ for (final Permission bp : needsUpdate) {
// If the target package is being uninstalled, we need to revoke this permission
// From all other packages
if (pkg == null || !hasPermission(pkg, bp.getName())) {
@@ -4236,7 +4218,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
});
}
- mSettings.removePermissionLocked(bp.getName());
+ synchronized (mLock) {
+ mRegistry.removePermission(bp.getName());
+ }
continue;
}
final AndroidPackage sourcePkg =
@@ -4250,7 +4234,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
Slog.w(TAG, "Removing dangling permission: " + bp.getName()
+ " from package " + bp.getPackageName());
- mSettings.removePermissionLocked(bp.getName());
+ mRegistry.removePermission(bp.getName());
}
}
}
@@ -4316,11 +4300,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
boolean changed = false;
- Set<BasePermission> needsUpdate = null;
+ Set<Permission> needsUpdate = null;
synchronized (mLock) {
- final Iterator<BasePermission> it = mSettings.mPermissionTrees.values().iterator();
+ final Iterator<Permission> it = mRegistry.getPermissionTrees().iterator();
while (it.hasNext()) {
- final BasePermission bp = it.next();
+ final Permission bp = it.next();
if (!packageName.equals(bp.getPackageName())) {
// Not checking sourcePackageSetting because it can be null when
// the permission source package is the target package and the target package is
@@ -4336,13 +4320,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
it.remove();
}
if (needsUpdate == null) {
- needsUpdate = new ArraySet<>(mSettings.mPermissionTrees.size());
+ needsUpdate = new ArraySet<>();
}
needsUpdate.add(bp);
}
}
if (needsUpdate != null) {
- for (final BasePermission bp : needsUpdate) {
+ for (final Permission bp : needsUpdate) {
final AndroidPackage sourcePkg =
mPackageManagerInt.getPackage(bp.getPackageName());
final PackageSetting sourcePs =
@@ -4354,7 +4338,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
Slog.w(TAG, "Removing dangling permission tree: " + bp.getName()
+ " from package " + bp.getPackageName());
- mSettings.removePermissionLocked(bp.getName());
+ mRegistry.removePermission(bp.getName());
}
}
}
@@ -4535,17 +4519,17 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return builder.toString();
}
- @GuardedBy({"mSettings.mLock", "mLock"})
- private int calculateCurrentPermissionFootprintLocked(BasePermission tree) {
+ @GuardedBy("mLock")
+ private int calculateCurrentPermissionFootprintLocked(@NonNull Permission permissionTree) {
int size = 0;
- for (BasePermission perm : mSettings.mPermissions.values()) {
- size += tree.calculateFootprint(perm);
+ for (final Permission permission : mRegistry.getPermissions()) {
+ size += permissionTree.calculateFootprint(permission);
}
return size;
}
- @GuardedBy({"mSettings.mLock", "mLock"})
- private void enforcePermissionCapLocked(PermissionInfo info, BasePermission tree) {
+ @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.
if (tree.getUid() != Process.SYSTEM_UID) {
@@ -4558,9 +4542,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);
@@ -4628,29 +4615,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);
@@ -4670,7 +4649,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
- private void readStateFromPackageSettings() {
+ private void readLegacyPermissionState() {
final int[] userIds = getAllUserIds();
mPackageManagerInt.forEachPackageSetting(ps -> {
final int appId = ps.getAppId();
@@ -4684,24 +4663,31 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final UidPermissionState uidState = userState.getOrCreateUidState(appId);
uidState.reset();
uidState.setMissing(legacyState.isMissing(userId));
- readStateFromPermissionStates(uidState,
+ readLegacyPermissionStatesLocked(uidState,
legacyState.getInstallPermissionStates());
- readStateFromPermissionStates(uidState,
+ readLegacyPermissionStatesLocked(uidState,
legacyState.getRuntimePermissionStates(userId));
}
}
});
}
- private void readStateFromPermissionStates(@NonNull UidPermissionState uidState,
+ @GuardedBy("mLock")
+ private void readLegacyPermissionStatesLocked(@NonNull UidPermissionState uidState,
@NonNull Collection<LegacyPermissionState.PermissionState> permissionStates) {
for (final LegacyPermissionState.PermissionState permissionState : permissionStates) {
- uidState.putPermissionState(permissionState.getPermission(),
- permissionState.isGranted(), permissionState.getFlags());
+ final String permissionName = permissionState.getName();
+ final Permission permission = mRegistry.getPermission(permissionName);
+ if (permission == null) {
+ Slog.w(TAG, "Unknown permission: " + permissionName);
+ continue;
+ }
+ uidState.putPermissionState(permission, permissionState.isGranted(),
+ permissionState.getFlags());
}
}
- private void writeStateToPackageSettings() {
+ private void writeLegacyPermissionState() {
final int[] userIds;
synchronized (mLock) {
userIds = mState.getUserIds();
@@ -4738,12 +4724,10 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final PermissionState permissionState = permissionStates.get(i);
final LegacyPermissionState.PermissionState legacyPermissionState =
- new LegacyPermissionState.PermissionState(
- permissionState.getPermission(),
+ new LegacyPermissionState.PermissionState(permissionState.getName(),
permissionState.isGranted(), permissionState.getFlags());
if (permissionState.isRuntime()) {
- legacyState.putRuntimePermissionState(legacyPermissionState,
- userId);
+ legacyState.putRuntimePermissionState(legacyPermissionState, userId);
} else {
legacyState.putInstallPermissionState(legacyPermissionState);
}
@@ -4753,6 +4737,108 @@ public class PermissionManagerService extends IPermissionManager.Stub {
});
}
+ private void readLegacyPermissions(@NonNull LegacyPermissionSettings legacyPermissionSettings) {
+ for (int readPermissionOrPermissionTree = 0; readPermissionOrPermissionTree < 2;
+ readPermissionOrPermissionTree++) {
+ final List<LegacyPermission> legacyPermissions = readPermissionOrPermissionTree == 0
+ ? legacyPermissionSettings.getPermissions()
+ : legacyPermissionSettings.getPermissionTrees();
+ synchronized (mLock) {
+ final int legacyPermissionsSize = legacyPermissions.size();
+ for (int i = 0; i < legacyPermissionsSize; i++) {
+ final LegacyPermission legacyPermission = legacyPermissions.get(i);
+ final Permission permission = new Permission(
+ legacyPermission.getPermissionInfo(), legacyPermission.getType());
+ if (readPermissionOrPermissionTree == 0) {
+ // Config permissions are currently read in PermissionManagerService
+ // constructor. The old behavior was to add other attributes to the config
+ // permission in LegacyPermission.read(), so equivalently we can add the
+ // GIDs to the new permissions here, since config permissions created in
+ // PermissionManagerService constructor get only their names and GIDs there.
+ final Permission configPermission = mRegistry.getPermission(
+ permission.getName());
+ if (configPermission != null
+ && configPermission.getType() == Permission.TYPE_CONFIG) {
+ permission.setGids(configPermission.getRawGids(),
+ configPermission.areGidsPerUser());
+ }
+ mRegistry.addPermission(permission);
+ } else {
+ mRegistry.addPermissionTree(permission);
+ }
+ }
+ }
+ }
+ }
+
+ private void writeLegacyPermissions(
+ @NonNull LegacyPermissionSettings legacyPermissionSettings) {
+ for (int writePermissionOrPermissionTree = 0; writePermissionOrPermissionTree < 2;
+ writePermissionOrPermissionTree++) {
+ final List<LegacyPermission> legacyPermissions = new ArrayList<>();
+ synchronized (mLock) {
+ final Collection<Permission> permissions = writePermissionOrPermissionTree == 0
+ ? mRegistry.getPermissions() : mRegistry.getPermissionTrees();
+ for (final Permission permission : permissions) {
+ // We don't need to provide UID and GIDs, which are only retrieved when dumping.
+ final LegacyPermission legacyPermission = new LegacyPermission(
+ permission.getPermissionInfo(), permission.getType(), 0,
+ EmptyArray.INT);
+ legacyPermissions.add(legacyPermission);
+ }
+ }
+ if (writePermissionOrPermissionTree == 0) {
+ legacyPermissionSettings.replacePermissions(legacyPermissions);
+ } else {
+ legacyPermissionSettings.replacePermissionTrees(legacyPermissions);
+ }
+ }
+ }
+
+ private void transferPermissions(@NonNull String oldPackageName,
+ @NonNull String newPackageName) {
+ synchronized (mLock) {
+ mRegistry.transferPermissions(oldPackageName, newPackageName);
+ }
+ }
+
+ private boolean canPropagatePermissionToInstantApp(@NonNull String permissionName) {
+ synchronized (mLock) {
+ final Permission bp = mRegistry.getPermission(permissionName);
+ return bp != null && (bp.isRuntime() || bp.isDevelopment()) && bp.isInstant();
+ }
+ }
+
+ @NonNull
+ private List<LegacyPermission> getLegacyPermissions() {
+ synchronized (mLock) {
+ final List<LegacyPermission> legacyPermissions = new ArrayList<>();
+ for (final Permission permission : mRegistry.getPermissions()) {
+ final LegacyPermission legacyPermission = new LegacyPermission(
+ permission.getPermissionInfo(), permission.getType(), permission.getUid(),
+ permission.getRawGids());
+ legacyPermissions.add(legacyPermission);
+ }
+ return legacyPermissions;
+ }
+ }
+
+ @NonNull
+ private Map<String, Set<String>> getAllAppOpPermissionPackages() {
+ synchronized (mLock) {
+ final ArrayMap<String, ArraySet<String>> appOpPermissionPackages =
+ mRegistry.getAllAppOpPermissionPackages();
+ final Map<String, Set<String>> deepClone = new ArrayMap<>();
+ final int appOpPermissionPackagesSize = appOpPermissionPackages.size();
+ for (int i = 0; i < appOpPermissionPackagesSize; i++) {
+ final String appOpPermission = appOpPermissionPackages.keyAt(i);
+ final ArraySet<String> packageNames = appOpPermissionPackages.valueAt(i);
+ deepClone.put(appOpPermission, new ArraySet<>(packageNames));
+ }
+ return deepClone;
+ }
+ }
+
@NonNull
private LegacyPermissionState getLegacyPermissionState(@AppIdInt int appId) {
final LegacyPermissionState legacyState = new LegacyPermissionState();
@@ -4772,9 +4858,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final PermissionState permissionState = permissionStates.get(i);
final LegacyPermissionState.PermissionState legacyPermissionState =
- new LegacyPermissionState.PermissionState(
- permissionState.getPermission(), permissionState.isGranted(),
- permissionState.getFlags());
+ new LegacyPermissionState.PermissionState(permissionState.getName(),
+ permissionState.isGranted(), permissionState.getFlags());
if (permissionState.isRuntime()) {
legacyState.putRuntimePermissionState(legacyPermissionState, userId);
} else if (userId == UserHandle.USER_SYSTEM) {
@@ -4842,12 +4927,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
PermissionManagerService.this.removeAllPermissions(pkg, chatty);
}
@Override
- public void readStateFromPackageSettingsTEMP() {
- PermissionManagerService.this.readStateFromPackageSettings();
+ public void readLegacyPermissionStateTEMP() {
+ PermissionManagerService.this.readLegacyPermissionState();
}
@Override
- public void writeStateToPackageSettingsTEMP() {
- PermissionManagerService.this.writeStateToPackageSettings();
+ public void writeLegacyPermissionStateTEMP() {
+ PermissionManagerService.this.writeLegacyPermissionState();
}
@Override
public void onUserRemoved(@UserIdInt int userId) {
@@ -4950,17 +5035,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
- public void enforceGrantRevokeRuntimePermissionPermissions(String message) {
- PermissionManagerService.this.enforceGrantRevokeRuntimePermissionPermissions(message);
- }
- @Override
- public PermissionSettings getPermissionSettings() {
- return mSettings;
- }
- @Override
- public BasePermission getPermissionTEMP(String permName) {
- synchronized (PermissionManagerService.this.mLock) {
- return mSettings.getPermissionLocked(permName);
+ public Permission getPermissionTEMP(String permName) {
+ synchronized (mLock) {
+ return mRegistry.getPermission(permName);
}
}
@@ -4970,13 +5047,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
synchronized (mLock) {
- int numTotalPermissions = mSettings.mPermissions.size();
-
- for (int i = 0; i < numTotalPermissions; i++) {
- BasePermission bp = mSettings.mPermissions.valueAt(i);
-
- if (bp.getProtection() == protection) {
- matchingPermissions.add(bp.generatePermissionInfo(0));
+ for (final Permission permission : mRegistry.getPermissions()) {
+ if (permission.getProtection() == protection) {
+ matchingPermissions.add(permission.generatePermissionInfo(0));
}
}
}
@@ -4990,13 +5063,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
synchronized (mLock) {
- int numTotalPermissions = mSettings.mPermissions.size();
-
- for (int i = 0; i < numTotalPermissions; i++) {
- BasePermission bp = mSettings.mPermissions.valueAt(i);
-
- if ((bp.getProtectionFlags() & protectionFlags) == protectionFlags) {
- matchingPermissions.add(bp.generatePermissionInfo(0));
+ for (final Permission permission : mRegistry.getPermissions()) {
+ if ((permission.getProtectionFlags() & protectionFlags) == protectionFlags) {
+ matchingPermissions.add(permission.generatePermissionInfo(0));
}
}
}
@@ -5187,25 +5256,62 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
- public void retainHardAndSoftRestrictedPermissions(@NonNull List<String> permissions) {
+ public void retainHardAndSoftRestrictedPermissions(@NonNull List<String> permissionNames) {
synchronized (mLock) {
- Iterator<String> iterator = permissions.iterator();
+ Iterator<String> iterator = permissionNames.iterator();
while (iterator.hasNext()) {
- String permission = iterator.next();
- BasePermission basePermission = mSettings.mPermissions.get(permission);
- if (basePermission == null || !basePermission.isHardOrSoftRestricted()) {
+ final String permissionName = iterator.next();
+ final Permission permission = mRegistry.getPermission(permissionName);
+ if (permission == null || !permission.isHardOrSoftRestricted()) {
iterator.remove();
}
}
}
}
+ @Override
+ public void readLegacyPermissionsTEMP(
+ @NonNull LegacyPermissionSettings legacyPermissionSettings) {
+ PermissionManagerService.this.readLegacyPermissions(legacyPermissionSettings);
+ }
+
+ @Override
+ public void writeLegacyPermissionsTEMP(
+ @NonNull LegacyPermissionSettings legacyPermissionSettings) {
+ PermissionManagerService.this.writeLegacyPermissions(legacyPermissionSettings);
+ }
+
+ @Override
+ public void transferPermissions(@NonNull String oldPackageName,
+ @NonNull String newPackageName) {
+ PermissionManagerService.this.transferPermissions(oldPackageName, newPackageName);
+ }
+
+ @Override
+ public boolean canPropagatePermissionToInstantApp(@NonNull String permissionName) {
+ return PermissionManagerService.this.canPropagatePermissionToInstantApp(permissionName);
+ }
+
+ @NonNull
+ @Override
+ public List<LegacyPermission> getLegacyPermissions() {
+ return PermissionManagerService.this.getLegacyPermissions();
+ }
+
+ @NonNull
+ @Override
+ public Map<String, Set<String>> getAllAppOpPermissionPackages() {
+ return PermissionManagerService.this.getAllAppOpPermissionPackages();
+ }
+
@NonNull
+ @Override
public LegacyPermissionState getLegacyPermissionState(@AppIdInt int appId) {
return PermissionManagerService.this.getLegacyPermissionState(appId);
}
@NonNull
+ @Override
public int[] getGidsForUid(int uid) {
return PermissionManagerService.this.getGidsForUid(uid);
}
@@ -5231,12 +5337,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/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 20e9c5dcb521..df81bac99a21 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -280,21 +280,21 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
public abstract void removeAllPermissions(@NonNull AndroidPackage pkg, boolean chatty);
/**
- * Read permission state from package settings.
+ * Read legacy permission state from package settings.
*
* TODO(zhanghai): This is a temporary method because we should not expose
* {@code PackageSetting} which is a implementation detail that permission should not know.
* Instead, it should retrieve the legacy state via a defined API.
*/
- public abstract void readStateFromPackageSettingsTEMP();
+ public abstract void readLegacyPermissionStateTEMP();
/**
- * Write permission state to package settings.
+ * Write legacy permission state to package settings.
*
* TODO(zhanghai): This is a temporary method and should be removed once we migrated persistence
* for permission.
*/
- public abstract void writeStateToPackageSettingsTEMP();
+ public abstract void writeLegacyPermissionStateTEMP();
/**
* Notify that a user has been removed and its permission state should be removed as well.
@@ -367,16 +367,14 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
public abstract void enforceCrossUserPermission(int callingUid, int userId,
boolean requireFullPermission, boolean checkShell,
boolean requirePermissionWhenSameUser, @NonNull String message);
- public abstract void enforceGrantRevokeRuntimePermissionPermissions(@NonNull String message);
-
- public abstract @NonNull PermissionSettings getPermissionSettings();
/** Grants default browser permissions to the given package */
public abstract void grantDefaultPermissionsToDefaultBrowser(
@NonNull String packageName, @UserIdInt int userId);
/** HACK HACK methods to allow for partial migration of data to the PermissionManager class */
- public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName);
+ @Nullable
+ public abstract Permission getPermissionTEMP(@NonNull String permName);
/** Get all permissions that have a certain protection */
public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtection(
@@ -536,5 +534,39 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
* Removes invalid permissions which are not {@link PermissionInfo#FLAG_HARD_RESTRICTED} or
* {@link PermissionInfo#FLAG_SOFT_RESTRICTED} from the input.
*/
- public abstract void retainHardAndSoftRestrictedPermissions(@NonNull List<String> permissions);
+ public abstract void retainHardAndSoftRestrictedPermissions(
+ @NonNull List<String> permissionNames);
+
+ /**
+ * Read legacy permissions from legacy permission settings.
+ *
+ * TODO(zhanghai): This is a temporary method because we should not expose
+ * {@code LegacyPermissionSettings} which is a implementation detail that permission should not
+ * know. Instead, it should retrieve the legacy permissions via a defined API.
+ */
+ public abstract void readLegacyPermissionsTEMP(
+ @NonNull LegacyPermissionSettings legacyPermissionSettings);
+
+ /**
+ * Write legacy permissions to legacy permission settings.
+ *
+ * TODO(zhanghai): This is a temporary method and should be removed once we migrated persistence
+ * for permission.
+ */
+ public abstract void writeLegacyPermissionsTEMP(
+ @NonNull LegacyPermissionSettings legacyPermissionSettings);
+
+ /**
+ * Transfers ownership of permissions from one package to another.
+ */
+ public abstract void transferPermissions(@NonNull String oldPackageName,
+ @NonNull String newPackageName);
+
+ /**
+ * Check whether a permission can be propagated to instant app.
+ *
+ * @param permissionName the name of the permission
+ * @return whether the permission can be propagated
+ */
+ public abstract boolean canPropagatePermissionToInstantApp(@NonNull String permissionName);
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionRegistry.java b/services/core/java/com/android/server/pm/permission/PermissionRegistry.java
new file mode 100644
index 000000000000..0e3fda7b937a
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/PermissionRegistry.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm.permission;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.parsing.component.ParsedPermissionGroup;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+
+import java.util.Collection;
+
+/**
+ * Permission registry for permissions, permission trees, permission groups and related things.
+ */
+public class PermissionRegistry {
+ /**
+ * All of the permissions known to the system. The mapping is from permission
+ * name to permission object.
+ */
+ private final ArrayMap<String, Permission> mPermissions = new ArrayMap<>();
+
+ /**
+ * All permission trees known to the system. The mapping is from permission tree
+ * name to permission object.
+ */
+ private final ArrayMap<String, Permission> mPermissionTrees = new ArrayMap<>();
+
+ /**
+ * All permisson groups know to the system. The mapping is from permission group
+ * name to permission group object.
+ */
+ private final ArrayMap<String, ParsedPermissionGroup> mPermissionGroups = new ArrayMap<>();
+
+ /**
+ * Set of packages that request a particular app op. The mapping is from permission
+ * name to package names.
+ */
+ private final ArrayMap<String, ArraySet<String>> mAppOpPermissionPackages = new ArrayMap<>();
+
+ @NonNull
+ public Collection<Permission> getPermissions() {
+ return mPermissions.values();
+ }
+
+ @Nullable
+ public Permission getPermission(@NonNull String permissionName) {
+ return mPermissions.get(permissionName);
+ }
+
+ public void addPermission(@NonNull Permission permission) {
+ mPermissions.put(permission.getName(), permission);
+ }
+
+ public void removePermission(@NonNull String permissionName) {
+ mPermissions.remove(permissionName);
+ }
+
+ @NonNull
+ public Collection<Permission> getPermissionTrees() {
+ return mPermissionTrees.values();
+ }
+
+ @Nullable
+ public Permission getPermissionTree(@NonNull String permissionTreeName) {
+ return mPermissionTrees.get(permissionTreeName);
+ }
+
+ public void addPermissionTree(@NonNull Permission permissionTree) {
+ mPermissionTrees.put(permissionTree.getName(), permissionTree);
+ }
+
+ /**
+ * Transfers ownership of permissions from one package to another.
+ */
+ public void transferPermissions(@NonNull String oldPackageName,
+ @NonNull String newPackageName) {
+ for (int i = 0; i < 2; i++) {
+ ArrayMap<String, Permission> permissions = i == 0 ? mPermissionTrees : mPermissions;
+ for (final Permission permission : permissions.values()) {
+ permission.transfer(oldPackageName, newPackageName);
+ }
+ }
+ }
+
+ @NonNull
+ public Collection<ParsedPermissionGroup> getPermissionGroups() {
+ return mPermissionGroups.values();
+ }
+
+ @Nullable
+ public ParsedPermissionGroup getPermissionGroup(@NonNull String permissionGroupName) {
+ return mPermissionGroups.get(permissionGroupName);
+ }
+
+ public void addPermissionGroup(@NonNull ParsedPermissionGroup permissionGroup) {
+ mPermissionGroups.put(permissionGroup.getName(), permissionGroup);
+ }
+
+ @NonNull
+ public ArrayMap<String, ArraySet<String>> getAllAppOpPermissionPackages() {
+ return mAppOpPermissionPackages;
+ }
+
+ @Nullable
+ public ArraySet<String> getAppOpPermissionPackages(@NonNull String permissionName) {
+ return mAppOpPermissionPackages.get(permissionName);
+ }
+
+ public void addAppOpPermissionPackage(@NonNull String permissionName,
+ @NonNull String packageName) {
+ ArraySet<String> packageNames = mAppOpPermissionPackages.get(permissionName);
+ if (packageNames == null) {
+ packageNames = new ArraySet<>();
+ mAppOpPermissionPackages.put(permissionName, packageNames);
+ }
+ packageNames.add(packageName);
+ }
+
+ public void removeAppOpPermissionPackage(@NonNull String permissionName,
+ @NonNull String packageName) {
+ final ArraySet<String> packageNames = mAppOpPermissionPackages.get(permissionName);
+ if (packageNames == null) {
+ return;
+ }
+ final boolean removed = packageNames.remove(packageName);
+ if (removed && packageNames.isEmpty()) {
+ mAppOpPermissionPackages.remove(permissionName);
+ }
+ }
+
+ /**
+ * Returns the permission tree for the given permission.
+ * @throws SecurityException If the calling UID is not allowed to add permissions to the
+ * found permission tree.
+ */
+ @NonNull
+ public Permission enforcePermissionTree(@NonNull String permissionName, int callingUid) {
+ return Permission.enforcePermissionTree(mPermissionTrees.values(), permissionName,
+ callingUid);
+ }
+}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionSettings.java b/services/core/java/com/android/server/pm/permission/PermissionSettings.java
deleted file mode 100644
index eea8ac737b86..000000000000
--- a/services/core/java/com/android/server/pm/permission/PermissionSettings.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.pm.permission;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.pm.parsing.component.ParsedPermissionGroup;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.XmlUtils;
-import com.android.server.pm.DumpState;
-import com.android.server.pm.PackageManagerService;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.Collection;
-
-/**
- * Permissions and other related data. This class is not meant for
- * direct access outside of the permission package with the sole exception
- * of package settings. Instead, it should be reference either from the
- * permission manager or package settings.
- */
-public class PermissionSettings {
-
- /**
- * All of the permissions known to the system. The mapping is from permission
- * name to permission object.
- */
- @GuardedBy("mLock")
- final ArrayMap<String, BasePermission> mPermissions =
- new ArrayMap<String, BasePermission>();
-
- /**
- * All permission trees known to the system. The mapping is from permission tree
- * name to permission object.
- */
- @GuardedBy("mLock")
- final ArrayMap<String, BasePermission> mPermissionTrees =
- new ArrayMap<String, BasePermission>();
-
- /**
- * All permisson groups know to the system. The mapping is from permission group
- * name to permission group object.
- */
- @GuardedBy("mLock")
- final ArrayMap<String, ParsedPermissionGroup> mPermissionGroups =
- new ArrayMap<>();
-
- /**
- * Set of packages that request a particular app op. The mapping is from permission
- * name to package names.
- */
- @GuardedBy("mLock")
- final ArrayMap<String, ArraySet<String>> mAppOpPermissionPackages = new ArrayMap<>();
-
- private final Object mLock;
-
- PermissionSettings(@NonNull Object lock) {
- mLock = lock;
- }
-
- public @Nullable BasePermission getPermission(@NonNull String permName) {
- synchronized (mLock) {
- return getPermissionLocked(permName);
- }
- }
-
- public void addAppOpPackage(String permName, String packageName) {
- synchronized (mLock) {
- ArraySet<String> pkgs = mAppOpPermissionPackages.get(permName);
- if (pkgs == null) {
- pkgs = new ArraySet<>();
- mAppOpPermissionPackages.put(permName, pkgs);
- }
- pkgs.add(packageName);
- }
- }
-
- /**
- * Transfers ownership of permissions from one package to another.
- */
- public void transferPermissions(String origPackageName, String newPackageName) {
- synchronized (mLock) {
- for (int i=0; i<2; i++) {
- ArrayMap<String, BasePermission> permissions =
- i == 0 ? mPermissionTrees : mPermissions;
- for (BasePermission bp : permissions.values()) {
- bp.transfer(origPackageName, newPackageName);
- }
- }
- }
- }
-
- public boolean canPropagatePermissionToInstantApp(String permName) {
- synchronized (mLock) {
- final BasePermission bp = mPermissions.get(permName);
- return (bp != null && (bp.isRuntime() || bp.isDevelopment()) && bp.isInstant());
- }
- }
-
- public void readPermissions(XmlPullParser parser) throws IOException, XmlPullParserException {
- synchronized (mLock) {
- readPermissions(mPermissions, parser);
- }
- }
-
- public void readPermissionTrees(XmlPullParser parser)
- throws IOException, XmlPullParserException {
- synchronized (mLock) {
- readPermissions(mPermissionTrees, parser);
- }
- }
-
- public void writePermissions(XmlSerializer serializer) throws IOException {
- synchronized (mLock) {
- for (BasePermission bp : mPermissions.values()) {
- bp.writeLPr(serializer);
- }
- }
- }
-
- public void writePermissionTrees(XmlSerializer serializer) throws IOException {
- synchronized (mLock) {
- for (BasePermission bp : mPermissionTrees.values()) {
- bp.writeLPr(serializer);
- }
- }
- }
-
- public static void readPermissions(ArrayMap<String, BasePermission> out, XmlPullParser parser)
- throws IOException, XmlPullParserException {
- int outerDepth = parser.getDepth();
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
- continue;
- }
-
- if (!BasePermission.readLPw(out, parser)) {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Unknown element reading permissions: " + parser.getName() + " at "
- + parser.getPositionDescription());
- }
- XmlUtils.skipCurrentTag(parser);
- }
- }
-
- public void dumpPermissions(PrintWriter pw, String packageName,
- ArraySet<String> permissionNames, boolean externalStorageEnforced,
- DumpState dumpState) {
- synchronized (mLock) {
- boolean printedSomething = false;
- for (BasePermission bp : mPermissions.values()) {
- printedSomething = bp.dumpPermissionsLPr(pw, packageName, permissionNames,
- externalStorageEnforced, printedSomething, dumpState);
- }
- if (packageName == null && permissionNames == null) {
- for (int iperm = 0; iperm<mAppOpPermissionPackages.size(); iperm++) {
- if (iperm == 0) {
- if (dumpState.onTitlePrinted())
- pw.println();
- pw.println("AppOp Permissions:");
- }
- pw.print(" AppOp Permission ");
- pw.print(mAppOpPermissionPackages.keyAt(iperm));
- pw.println(":");
- ArraySet<String> pkgs = mAppOpPermissionPackages.valueAt(iperm);
- for (int ipkg=0; ipkg<pkgs.size(); ipkg++) {
- pw.print(" "); pw.println(pkgs.valueAt(ipkg));
- }
- }
- }
- }
- }
-
- @GuardedBy("mLock")
- @Nullable BasePermission getPermissionLocked(@NonNull String permName) {
- return mPermissions.get(permName);
- }
-
- @GuardedBy("mLock")
- @Nullable BasePermission getPermissionTreeLocked(@NonNull String permName) {
- return mPermissionTrees.get(permName);
- }
-
- @GuardedBy("mLock")
- void putPermissionLocked(@NonNull String permName, @NonNull BasePermission permission) {
- mPermissions.put(permName, permission);
- }
-
- @GuardedBy("mLock")
- void putPermissionTreeLocked(@NonNull String permName, @NonNull BasePermission permission) {
- mPermissionTrees.put(permName, permission);
- }
-
- @GuardedBy("mLock")
- void removePermissionLocked(@NonNull String permName) {
- mPermissions.remove(permName);
- }
-
- @GuardedBy("mLock")
- void removePermissionTreeLocked(@NonNull String permName) {
- mPermissionTrees.remove(permName);
- }
-
- @GuardedBy("mLock")
- @NonNull Collection<BasePermission> getAllPermissionsLocked() {
- return mPermissions.values();
- }
-
- @GuardedBy("mLock")
- @NonNull Collection<BasePermission> getAllPermissionTreesLocked() {
- return mPermissionTrees.values();
- }
-
- /**
- * Returns the permission tree for the given permission.
- * @throws SecurityException If the calling UID is not allowed to add permissions to the
- * found permission tree.
- */
- @Nullable BasePermission enforcePermissionTree(@NonNull String permName, int callingUid) {
- synchronized (mLock) {
- return BasePermission.enforcePermissionTree(
- mPermissionTrees.values(), permName, callingUid);
- }
- }
-
- /**
- * Check whether a permission is runtime.
- *
- * @see BasePermission#isRuntime()
- */
- public boolean isPermissionRuntime(@NonNull String permName) {
- synchronized (mLock) {
- final BasePermission bp = mPermissions.get(permName);
- return (bp != null && bp.isRuntime());
- }
- }
-
- public boolean isPermissionInstant(String permName) {
- synchronized (mLock) {
- final BasePermission bp = mPermissions.get(permName);
- return (bp != null && bp.isInstant());
- }
- }
-
- boolean isPermissionAppOp(String permName) {
- synchronized (mLock) {
- final BasePermission bp = mPermissions.get(permName);
- return (bp != null && bp.isAppOp());
- }
- }
-
-}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionState.java b/services/core/java/com/android/server/pm/permission/PermissionState.java
index 59b204f7dfff..12f29d091134 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionState.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionState.java
@@ -27,7 +27,7 @@ import com.android.internal.annotations.GuardedBy;
public final class PermissionState {
@NonNull
- private final BasePermission mPermission;
+ private final Permission mPermission;
private final Object mLock = new Object();
@@ -40,7 +40,7 @@ public final class PermissionState {
@GuardedBy("mLock")
private int mFlags;
- public PermissionState(@NonNull BasePermission permission) {
+ public PermissionState(@NonNull Permission permission) {
mPermission = permission;
}
@@ -52,7 +52,7 @@ public final class PermissionState {
}
@NonNull
- public BasePermission getPermission() {
+ public Permission getPermission() {
return mPermission;
}
diff --git a/services/core/java/com/android/server/pm/permission/UidPermissionState.java b/services/core/java/com/android/server/pm/permission/UidPermissionState.java
index 9727a5452440..04d82e872ae6 100644
--- a/services/core/java/com/android/server/pm/permission/UidPermissionState.java
+++ b/services/core/java/com/android/server/pm/permission/UidPermissionState.java
@@ -125,7 +125,7 @@ public final class UidPermissionState {
}
@NonNull
- private PermissionState getOrCreatePermissionState(@NonNull BasePermission permission) {
+ private PermissionState getOrCreatePermissionState(@NonNull Permission permission) {
if (mPermissions == null) {
mPermissions = new ArrayMap<>();
}
@@ -158,7 +158,7 @@ public final class UidPermissionState {
* @param granted whether the permission is granted
* @param flags the permission flags
*/
- public void putPermissionState(@NonNull BasePermission permission, boolean granted, int flags) {
+ public void putPermissionState(@NonNull Permission permission, boolean granted, int flags) {
final String name = permission.getName();
if (mPermissions == null) {
mPermissions = new ArrayMap<>();
@@ -230,7 +230,7 @@ public final class UidPermissionState {
* @param permission the permission to grant
* @return whether the permission grant state changed
*/
- public boolean grantPermission(@NonNull BasePermission permission) {
+ public boolean grantPermission(@NonNull Permission permission) {
final PermissionState permissionState = getOrCreatePermissionState(permission);
return permissionState.grant();
}
@@ -241,7 +241,7 @@ public final class UidPermissionState {
* @param permission the permission to revoke
* @return whether the permission grant state changed
*/
- public boolean revokePermission(@NonNull BasePermission permission) {
+ public boolean revokePermission(@NonNull Permission permission) {
final String name = permission.getName();
final PermissionState permissionState = getPermissionState(name);
if (permissionState == null) {
@@ -276,7 +276,7 @@ public final class UidPermissionState {
* @param flagValues the new values for the masked flags
* @return whether the permission flags changed
*/
- public boolean updatePermissionFlags(@NonNull BasePermission permission, int flagMask,
+ public boolean updatePermissionFlags(@NonNull Permission permission, int flagMask,
int flagValues) {
if (flagMask == 0) {
return false;
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/timezonedetector/TimeZoneDetectorCallbackImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java
index 941be0ede1b9..1357608ef9d4 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorCallbackImpl.java
@@ -168,7 +168,7 @@ public final class TimeZoneDetectorCallbackImpl implements TimeZoneDetectorStrat
// that support new types of auto detection on the same hardware.
if (isAutoDetectionSupported()) {
final boolean autoDetectionEnabled = configuration.isAutoDetectionEnabled();
- setAutoDetectionEnabled(autoDetectionEnabled);
+ setAutoDetectionEnabledIfRequired(autoDetectionEnabled);
// Avoid writing the geo detection enabled setting for devices that do not support geo
// time zone detection: if we wrote it down then we'd set the value explicitly, which
@@ -176,7 +176,7 @@ public final class TimeZoneDetectorCallbackImpl implements TimeZoneDetectorStrat
// releases that support geo detection on the same hardware.
if (isGeoDetectionSupported()) {
final boolean geoTzDetectionEnabled = configuration.isGeoDetectionEnabled();
- setGeoDetectionEnabled(userId, geoTzDetectionEnabled);
+ setGeoDetectionEnabledIfRequired(userId, geoTzDetectionEnabled);
}
}
}
@@ -198,8 +198,14 @@ public final class TimeZoneDetectorCallbackImpl implements TimeZoneDetectorStrat
return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME_ZONE, 1 /* default */) > 0;
}
- private void setAutoDetectionEnabled(boolean enabled) {
- Settings.Global.putInt(mCr, Settings.Global.AUTO_TIME_ZONE, enabled ? 1 : 0);
+ private void setAutoDetectionEnabledIfRequired(boolean enabled) {
+ // This check is racey, but the whole settings update process is racey. This check prevents
+ // a ConfigurationChangeListener callback triggering due to ContentObserver's still
+ // triggering *sometimes* for no-op updates. Because callbacks are async this is necessary
+ // for stable behavior during tests.
+ if (isAutoDetectionEnabled() != enabled) {
+ Settings.Global.putInt(mCr, Settings.Global.AUTO_TIME_ZONE, enabled ? 1 : 0);
+ }
}
private boolean isLocationEnabled(@UserIdInt int userId) {
@@ -213,9 +219,12 @@ public final class TimeZoneDetectorCallbackImpl implements TimeZoneDetectorStrat
(geoDetectionEnabledByDefault ? 1 : 0) /* defaultValue */, userId) != 0;
}
- private void setGeoDetectionEnabled(@UserIdInt int userId, boolean enabled) {
- Settings.Secure.putIntForUser(mCr, Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED,
- enabled ? 1 : 0, userId);
+ private void setGeoDetectionEnabledIfRequired(@UserIdInt int userId, boolean enabled) {
+ // See comment in setAutoDetectionEnabledIfRequired. http://b/171953500
+ if (isGeoDetectionEnabled(userId) != enabled) {
+ Settings.Secure.putIntForUser(mCr, Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED,
+ enabled ? 1 : 0, userId);
+ }
}
private boolean deviceHasTelephonyNetwork() {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 25b2523b1a3e..910a1a2c69b2 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1195,12 +1195,7 @@ class ActivityStarter {
}
}
- // Only allow app switching to be resumed if activity is not a restricted background
- // activity, otherwise any background activity started in background task can stop
- // home button protection mode.
- if (!restrictedBgActivity) {
- mService.onStartActivitySetDidAppSwitch();
- }
+ mService.onStartActivitySetDidAppSwitch();
mController.doPendingActivityLaunches(false);
mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,
@@ -1265,20 +1260,6 @@ class ActivityStarter {
return false;
}
- // Always allow home application to start activities.
- if (mService.mHomeProcess != null && callingUid == mService.mHomeProcess.mUid) {
- if (DEBUG_ACTIVITY_STARTS) {
- Slog.d(TAG, "Activity start allowed for home app callingUid (" + callingUid + ")");
- }
- return false;
- }
-
- // App switching will be allowed if BAL app switching flag is not enabled, or if
- // its app switching rule allows it.
- // This is used to block background activity launch even if the app is still
- // visible to user after user clicking home button.
- final boolean appSwitchAllowed = mService.getBalAppSwitchesAllowed();
-
// don't abort if the callingUid has a visible window or is a persistent system process
final int callingUidProcState = mService.getUidState(callingUid);
final boolean callingUidHasAnyVisibleWindow =
@@ -1288,8 +1269,7 @@ class ActivityStarter {
|| callingUidProcState == ActivityManager.PROCESS_STATE_BOUND_TOP;
final boolean isCallingUidPersistentSystemProcess =
callingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
- if ((appSwitchAllowed && callingUidHasAnyVisibleWindow)
- || isCallingUidPersistentSystemProcess) {
+ if (callingUidHasAnyVisibleWindow || isCallingUidPersistentSystemProcess) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "Activity start allowed: callingUidHasAnyVisibleWindow = " + callingUid
+ ", isCallingUidPersistentSystemProcess = "
@@ -1315,7 +1295,6 @@ class ActivityStarter {
|| realCallingUidProcState <= ActivityManager.PROCESS_STATE_PERSISTENT_UI;
if (realCallingUid != callingUid) {
// don't abort if the realCallingUid has a visible window
- // TODO(b/171459802): We should check appSwitchAllowed also
if (realCallingUidHasAnyVisibleWindow) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "Activity start allowed: realCallingUid (" + realCallingUid
@@ -1397,7 +1376,7 @@ class ActivityStarter {
// don't abort if the callerApp or other processes of that uid are allowed in any way
if (callerApp != null) {
// first check the original calling process
- if (callerApp.areBackgroundActivityStartsAllowed(appSwitchAllowed)) {
+ if (callerApp.areBackgroundActivityStartsAllowed()) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "Background activity start allowed: callerApp process (pid = "
+ callerApp.getPid() + ", uid = " + callerAppUid + ") is allowed");
@@ -1410,8 +1389,7 @@ class ActivityStarter {
if (uidProcesses != null) {
for (int i = uidProcesses.size() - 1; i >= 0; i--) {
final WindowProcessController proc = uidProcesses.valueAt(i);
- if (proc != callerApp
- && proc.areBackgroundActivityStartsAllowed(appSwitchAllowed)) {
+ if (proc != callerApp && proc.areBackgroundActivityStartsAllowed()) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG,
"Background activity start allowed: process " + proc.getPid()
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index c7d716d8290a..eb86d37225bc 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -565,4 +565,10 @@ public abstract class ActivityTaskManagerInternal {
/** Set all associated companion app that belongs to an userId. */
public abstract void setCompanionAppPackages(int userId, Set<String> companionAppPackages);
+
+ /**
+ * @param packageName The package to check
+ * @return Whether the package is the base of any locked task
+ */
+ public abstract boolean isBaseOfLockedTask(String packageName);
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index a02701f8ad00..608d37395b28 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -161,11 +161,9 @@ import android.app.WindowConfiguration;
import android.app.admin.DevicePolicyCache;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
-import android.app.compat.CompatChanges;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.EnterPipRequestedItem;
import android.app.usage.UsageStatsManagerInternal;
-import android.compat.annotation.ChangeId;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -344,12 +342,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
/** This activity is being relaunched due to a free-resize operation. */
public static final int RELAUNCH_REASON_FREE_RESIZE = 2;
- /**
- * Apps are blocked from starting activities in the foreground after the user presses home.
- */
- @ChangeId
- public static final long BLOCK_ACTIVITY_STARTS_AFTER_HOME = 159433730L;
-
Context mContext;
/**
@@ -2635,35 +2627,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
throw new SecurityException(msg);
}
- /**
- * Return true if app switch protection will be handled by background activity launch logic.
- */
- boolean getBalAppSwitchesProtectionEnabled() {
- return CompatChanges.isChangeEnabled(BLOCK_ACTIVITY_STARTS_AFTER_HOME);
- }
-
- /**
- * Return true if app switching is allowed.
- */
- boolean getBalAppSwitchesAllowed() {
- if (getBalAppSwitchesProtectionEnabled()) {
- // Apps no longer able to start BAL again until app switching is resumed.
- return mAppSwitchesAllowedTime == 0;
- } else {
- // Legacy behavior, BAL logic won't block app switching.
- return true;
- }
- }
-
boolean checkAppSwitchAllowedLocked(int sourcePid, int sourceUid,
int callingPid, int callingUid, String name) {
-
- // Background activity launch logic replaces app switching protection, so allow
- // apps to start activity here now.
- if (getBalAppSwitchesProtectionEnabled()) {
- return true;
- }
-
if (mAppSwitchesAllowedTime < SystemClock.uptimeMillis()) {
return true;
}
@@ -4698,10 +4663,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mAppSwitchesAllowedTime = SystemClock.uptimeMillis() + APP_SWITCH_DELAY_TIME;
mLastStopAppSwitchesTime = SystemClock.uptimeMillis();
mDidAppSwitch = false;
- // If BAL app switching enabled, app switches are blocked not delayed.
- if (!getBalAppSwitchesProtectionEnabled()) {
- getActivityStartController().schedulePendingActivityLaunches(APP_SWITCH_DELAY_TIME);
- }
+ getActivityStartController().schedulePendingActivityLaunches(APP_SWITCH_DELAY_TIME);
}
}
@@ -7470,5 +7432,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mCompanionAppUidsMap.put(userId, result);
}
}
+
+
+ @Override
+ public boolean isBaseOfLockedTask(String packageName) {
+ synchronized (mGlobalLock) {
+ return getLockTaskController().isBaseOfLockedTask(packageName);
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 26c5d70a2c45..6453ddf80faa 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1084,23 +1084,24 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return token;
}
- SurfaceControl addShellRoot(@NonNull IWindow client, int windowType) {
- ShellRoot root = mShellRoots.get(windowType);
+ SurfaceControl addShellRoot(@NonNull IWindow client,
+ @WindowManager.ShellRootLayer int shellRootLayer) {
+ ShellRoot root = mShellRoots.get(shellRootLayer);
if (root != null) {
if (root.getClient() == client) {
return root.getSurfaceControl();
}
root.clear();
- mShellRoots.remove(windowType);
+ mShellRoots.remove(shellRootLayer);
}
- root = new ShellRoot(client, this, windowType);
+ root = new ShellRoot(client, this, shellRootLayer);
SurfaceControl rootLeash = root.getSurfaceControl();
if (rootLeash == null) {
// Root didn't finish initializing, so don't add it.
root.clear();
return null;
}
- mShellRoots.put(windowType, root);
+ mShellRoots.put(shellRootLayer, root);
SurfaceControl out = new SurfaceControl(rootLeash, "DisplayContent.addShellRoot");
return out;
}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 470c2b1581d0..4a54196b71de 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -45,6 +45,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.LOGTAG_INPUT_FOCUS;
import android.graphics.Rect;
import android.os.Handler;
@@ -54,6 +55,7 @@ import android.os.Process;
import android.os.Trace;
import android.os.UserHandle;
import android.util.ArrayMap;
+import android.util.EventLog;
import android.util.Slog;
import android.view.InputApplicationHandle;
import android.view.InputChannel;
@@ -503,13 +505,14 @@ final class InputMonitor {
}
if (!focus.mWinAnimator.hasSurface()) {
- ProtoLog.d(WM_DEBUG_FOCUS_LIGHT,
- "Focus not requested for window=%s because it has no surface",
- focus);
+ Slog.v(TAG_WM, "Focus not requested for window=%" + focus
+ + " because it has no surface.");
return;
}
mInputTransaction.setFocusedWindow(focus.mInputWindowHandle.token, mDisplayId);
+ EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
+ "Focus request " + focus, "reason=UpdateInputWindows");
mDisplayContent.mLastRequestedFocus = focus;
ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Focus requested for window=%s", focus);
}
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index e90436ef3b91..b33c2f2823a5 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -871,6 +871,21 @@ public class LockTaskController {
}
/**
+ * @param packageName The package to check
+ * @return Whether the package is the base of any locked task
+ */
+ boolean isBaseOfLockedTask(String packageName) {
+ for (int i = 0; i < mLockTaskModeTasks.size(); i++) {
+ final Intent bi = mLockTaskModeTasks.get(i).getBaseIntent();
+ if (bi != null && packageName.equals(bi.getComponent()
+ .getPackageName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Gets the cached value of LockTask feature flags for a specific user.
*/
private int getLockTaskFeaturesForUser(int userId) {
diff --git a/services/core/java/com/android/server/wm/ShellRoot.java b/services/core/java/com/android/server/wm/ShellRoot.java
index 759f341c0fe0..62c0527dfe1b 100644
--- a/services/core/java/com/android/server/wm/ShellRoot.java
+++ b/services/core/java/com/android/server/wm/ShellRoot.java
@@ -16,7 +16,10 @@
package com.android.server.wm;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+import static android.view.WindowManager.SHELL_ROOT_LAYER_DIVIDER;
+import static android.view.WindowManager.SHELL_ROOT_LAYER_PIP;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
@@ -31,6 +34,7 @@ import android.view.DisplayInfo;
import android.view.IWindow;
import android.view.SurfaceControl;
import android.view.WindowInfo;
+import android.view.WindowManager;
import android.view.animation.Animation;
/**
@@ -39,6 +43,7 @@ import android.view.animation.Animation;
public class ShellRoot {
private static final String TAG = "ShellRoot";
private final DisplayContent mDisplayContent;
+ private final int mShellRootLayer;
private IWindow mClient;
private WindowToken mToken;
private final IBinder.DeathRecipient mDeathRecipient;
@@ -46,17 +51,31 @@ public class ShellRoot {
private IWindow mAccessibilityWindow;
private IBinder.DeathRecipient mAccessibilityWindowDeath;
- ShellRoot(@NonNull IWindow client, @NonNull DisplayContent dc, final int windowType) {
+ ShellRoot(@NonNull IWindow client, @NonNull DisplayContent dc,
+ @WindowManager.ShellRootLayer final int shellRootLayer) {
mDisplayContent = dc;
- mDeathRecipient = () -> mDisplayContent.removeShellRoot(windowType);
+ mShellRootLayer = shellRootLayer;
+ mDeathRecipient = () -> mDisplayContent.removeShellRoot(shellRootLayer);
try {
client.asBinder().linkToDeath(mDeathRecipient, 0);
} catch (RemoteException e) {
- Slog.e(TAG, "Unable to add shell root for layer " + windowType + " on display "
+ Slog.e(TAG, "Unable to add shell root layer " + shellRootLayer + " on display "
+ dc.getDisplayId(), e);
return;
}
mClient = client;
+ int windowType;
+ switch (shellRootLayer) {
+ case SHELL_ROOT_LAYER_DIVIDER:
+ windowType = TYPE_DOCK_DIVIDER;
+ break;
+ case SHELL_ROOT_LAYER_PIP:
+ windowType = TYPE_APPLICATION_OVERLAY;
+ break;
+ default:
+ throw new IllegalArgumentException(shellRootLayer
+ + " is not an acceptable shell root layer.");
+ }
mToken = new WindowToken(
dc.mWmService, client.asBinder(), windowType, true, dc, true, false);
mSurfaceControl = mToken.makeChildSurface(null)
@@ -111,10 +130,16 @@ public class ShellRoot {
}
WindowInfo getWindowInfo() {
- if (mToken.windowType != TYPE_DOCK_DIVIDER) {
+ if (mShellRootLayer != SHELL_ROOT_LAYER_DIVIDER
+ && mShellRootLayer != SHELL_ROOT_LAYER_PIP) {
+ return null;
+ }
+ if (mShellRootLayer == SHELL_ROOT_LAYER_DIVIDER
+ && !mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated()) {
return null;
}
- if (!mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated()) {
+ if (mShellRootLayer == SHELL_ROOT_LAYER_PIP
+ && mDisplayContent.getDefaultTaskDisplayArea().getRootPinnedTask() == null) {
return null;
}
if (mAccessibilityWindow == null) {
@@ -125,13 +150,25 @@ public class ShellRoot {
windowInfo.type = mToken.windowType;
windowInfo.layer = mToken.getWindowLayerFromType();
windowInfo.token = mAccessibilityWindow.asBinder();
- windowInfo.title = "Splitscreen Divider";
windowInfo.focused = false;
- windowInfo.inPictureInPicture = false;
windowInfo.hasFlagWatchOutsideTouch = false;
final Rect regionRect = new Rect();
- mDisplayContent.getDockedDividerController().getTouchRegion(regionRect);
- windowInfo.regionInScreen.set(regionRect);
+
+
+ // DividerView
+ if (mShellRootLayer == SHELL_ROOT_LAYER_DIVIDER) {
+ windowInfo.inPictureInPicture = false;
+ mDisplayContent.getDockedDividerController().getTouchRegion(regionRect);
+ windowInfo.regionInScreen.set(regionRect);
+ windowInfo.title = "Splitscreen Divider";
+ }
+ // PipMenuView
+ if (mShellRootLayer == SHELL_ROOT_LAYER_PIP) {
+ windowInfo.inPictureInPicture = true;
+ mDisplayContent.getDefaultTaskDisplayArea().getRootPinnedTask().getBounds(regionRect);
+ windowInfo.regionInScreen.set(regionRect);
+ windowInfo.title = "Picture-in-Picture menu";
+ }
return windowInfo;
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 5bc5b47d5cfc..9273bf71f673 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -125,7 +125,6 @@ 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;
@@ -2847,13 +2846,18 @@ class Task extends WindowContainer<WindowContainer> {
getResolvedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
}
- // Do not allow non-resizable non-pinned tasks to be in a multi-window mode - they should
- // use their parent's windowing mode, or fullscreen.
- if (!isResizeable() && windowingMode != WINDOWING_MODE_PINNED
- && WindowConfiguration.inMultiWindowMode(windowingMode)) {
- windowingMode = WindowConfiguration.inMultiWindowMode(parentWindowingMode)
- ? WINDOWING_MODE_FULLSCREEN : parentWindowingMode;
- getResolvedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
+ // Do not allow non-resizable tasks to be in a multi-window mode, unless it is in pinned
+ // windowing mode or is in size compat freeform mode
+ if (!isResizeable()) {
+ final int candidateWindowingMode =
+ windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : parentWindowingMode;
+ if (WindowConfiguration.inMultiWindowMode(candidateWindowingMode)
+ && candidateWindowingMode != WINDOWING_MODE_PINNED
+ && (candidateWindowingMode != WINDOWING_MODE_FREEFORM
+ || !mStackSupervisor.mService.mSizeCompatFreeform)) {
+ getResolvedOverrideConfiguration().windowConfiguration.setWindowingMode(
+ WINDOWING_MODE_FULLSCREEN);
+ }
}
if (isLeafTask()) {
@@ -4122,6 +4126,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() {
@@ -4838,6 +4846,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
@@ -4986,7 +5005,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/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 70f43635a37c..c806c94358cb 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -206,6 +206,7 @@ import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DisplayMetrics;
+import android.util.EventLog;
import android.util.MergedConfiguration;
import android.util.Slog;
import android.util.SparseArray;
@@ -407,6 +408,7 @@ public class WindowManagerService extends IWindowManager.Stub
*/
private static final String DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY =
"persist.wm.disable_custom_task_animation";
+ static final int LOGTAG_INPUT_FOCUS = 62001;
/**
* @see #DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY
@@ -4032,7 +4034,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
- public SurfaceControl addShellRoot(int displayId, IWindow client, int windowType) {
+ public SurfaceControl addShellRoot(int displayId, IWindow client,
+ @WindowManager.ShellRootLayer int shellRootLayer) {
if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
@@ -4044,7 +4047,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (dc == null) {
return null;
}
- return dc.addShellRoot(client, windowType);
+ return dc.addShellRoot(client, shellRootLayer);
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -4052,7 +4055,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
@Override
- public void setShellRootAccessibilityWindow(int displayId, int windowType, IWindow target) {
+ public void setShellRootAccessibilityWindow(int displayId,
+ @WindowManager.ShellRootLayer int shellRootLayer, IWindow target) {
if (mContext.checkCallingOrSelfPermission(MANAGE_APP_TOKENS)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Must hold permission " + MANAGE_APP_TOKENS);
@@ -4064,7 +4068,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (dc == null) {
return;
}
- ShellRoot root = dc.mShellRoots.get(windowType);
+ ShellRoot root = dc.mShellRoots.get(shellRootLayer);
if (root == null) {
return;
}
@@ -8346,6 +8350,9 @@ public class WindowManagerService extends IWindowManager.Stub
final int displayId = embeddedWindow.mDisplayId;
if (grantFocus) {
t.setFocusedWindow(targetInputToken, displayId).apply();
+ EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
+ "Focus request " + embeddedWindow.getName(),
+ "reason=grantEmbeddedWindowFocus(true)");
} else {
// Search for a new focus target
DisplayContent displayContent = mRoot.getDisplayContent(displayId);
@@ -8359,6 +8366,9 @@ public class WindowManagerService extends IWindowManager.Stub
}
t.requestFocusTransfer(newFocusTarget.mInputWindowHandle.token, targetInputToken,
displayId).apply();
+ EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
+ "Transfer focus request " + newFocusTarget,
+ "reason=grantEmbeddedWindowFocus(false)");
}
ProtoLog.v(WM_DEBUG_FOCUS, "grantEmbeddedWindowFocus win=%s grantFocus=%s",
embeddedWindow.getName(), grantFocus);
@@ -8392,9 +8402,15 @@ public class WindowManagerService extends IWindowManager.Stub
if (grantFocus) {
t.requestFocusTransfer(targetInputToken, hostWindow.mInputChannel.getToken(),
hostWindow.getDisplayId()).apply();
+ EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
+ "Transfer focus request " + embeddedWindow.getName(),
+ "reason=grantEmbeddedWindowFocus(true)");
} else {
t.requestFocusTransfer(hostWindow.mInputChannel.getToken(), targetInputToken,
hostWindow.getDisplayId()).apply();
+ EventLog.writeEvent(LOGTAG_INPUT_FOCUS,
+ "Transfer focus request " + hostWindow,
+ "reason=grantEmbeddedWindowFocus(false)");
}
ProtoLog.v(WM_DEBUG_FOCUS, "grantEmbeddedWindowFocus win=%s grantFocus=%s",
embeddedWindow.getName(), grantFocus);
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 51857dcd323b..7d54ea95579e 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -104,13 +104,55 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
@Override
public void applyTransaction(WindowContainerTransaction t) {
- applyTransaction(t, null /*callback*/, null /*transition*/);
+ enforceTaskPermission("applyTransaction()");
+ if (t == null) {
+ throw new IllegalArgumentException("Null transaction passed to applySyncTransaction");
+ }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ applyTransaction(t, -1 /*syncId*/, null /*transition*/);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
@Override
public int applySyncTransaction(WindowContainerTransaction t,
IWindowContainerTransactionCallback callback) {
- return applyTransaction(t, callback, null /*transition*/);
+ enforceTaskPermission("applySyncTransaction()");
+ if (t == null) {
+ throw new IllegalArgumentException("Null transaction passed to applySyncTransaction");
+ }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ synchronized (mGlobalLock) {
+ /**
+ * If callback is non-null we are looking to synchronize this transaction by
+ * collecting all the results in to a SurfaceFlinger transaction and then delivering
+ * that to the given transaction ready callback. See {@link BLASTSyncEngine} for the
+ * details of the operation. But at a high level we create a sync operation with a
+ * given ID and an associated callback. Then we notify each WindowContainer in this
+ * WindowContainer transaction that it is participating in a sync operation with
+ * that ID. Once everything is notified we tell the BLASTSyncEngine "setSyncReady"
+ * which means that we have added everything to the set. At any point after this,
+ * all the WindowContainers will eventually finish applying their changes and notify
+ * the BLASTSyncEngine which will deliver the Transaction to the callback.
+ */
+ int syncId = -1;
+ if (callback != null) {
+ syncId = startSyncWithOrganizer(callback);
+ }
+ applyTransaction(t, syncId, null /*transition*/);
+ if (syncId >= 0) {
+ setSyncReady(syncId);
+ }
+ return syncId;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
@Override
@@ -131,7 +173,7 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
if (t == null) {
t = new WindowContainerTransaction();
}
- applyTransaction(t, null /*callback*/, transition);
+ applyTransaction(t, -1 /*syncId*/, transition);
return transition;
}
} finally {
@@ -148,10 +190,16 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
try {
synchronized (mGlobalLock) {
int syncId = -1;
- if (t != null) {
- syncId = applyTransaction(t, callback, null /*transition*/);
+ if (t != null && callback != null) {
+ syncId = startSyncWithOrganizer(callback);
}
getTransitionController().finishTransition(transitionToken);
+ if (t != null) {
+ applyTransaction(t, syncId, null /*transition*/);
+ }
+ if (syncId >= 0) {
+ setSyncReady(syncId);
+ }
return syncId;
}
} finally {
@@ -160,154 +208,114 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
}
/**
- * @param callback If non-null, this will be a sync-transaction.
+ * @param syncId If non-null, this will be a sync-transaction.
* @param transition A transition to collect changes into.
- * @return a BLAST sync-id if this is a non-transition, sync transaction.
*/
- private int applyTransaction(@NonNull WindowContainerTransaction t,
- @Nullable IWindowContainerTransactionCallback callback,
+ private void applyTransaction(@NonNull WindowContainerTransaction t, int syncId,
@Nullable Transition transition) {
- enforceTaskPermission("applySyncTransaction()");
- int syncId = -1;
- if (t == null) {
- throw new IllegalArgumentException(
- "Null transaction passed to applySyncTransaction");
- }
- final long ident = Binder.clearCallingIdentity();
+ int effects = 0;
+ ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Apply window transaction, syncId=%d", syncId);
+ mService.deferWindowLayout();
try {
- synchronized (mGlobalLock) {
- int effects = 0;
+ ArraySet<WindowContainer> haveConfigChanges = new ArraySet<>();
+ Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries =
+ t.getChanges().entrySet().iterator();
+ while (entries.hasNext()) {
+ final Map.Entry<IBinder, WindowContainerTransaction.Change> entry = entries.next();
+ final WindowContainer wc = WindowContainer.fromBinder(entry.getKey());
+ if (wc == null || !wc.isAttached()) {
+ Slog.e(TAG, "Attempt to operate on detached container: " + wc);
+ continue;
+ }
+ // Make sure we add to the syncSet before performing
+ // operations so we don't end up splitting effects between the WM
+ // pending transaction and the BLASTSync transaction.
+ if (syncId >= 0) {
+ addToSyncSet(syncId, wc);
+ }
- /**
- * If callback is non-null we are looking to synchronize this transaction by
- * collecting all the results in to a SurfaceFlinger transaction and then delivering
- * that to the given transaction ready callback. See {@link BLASTSyncEngine} for the
- * details of the operation. But at a high level we create a sync operation with a
- * given ID and an associated callback. Then we notify each WindowContainer in this
- * WindowContainer transaction that it is participating in a sync operation with
- * that ID. Once everything is notified we tell the BLASTSyncEngine "setSyncReady"
- * which means that we have added everything to the set. At any point after this,
- * all the WindowContainers will eventually finish applying their changes and notify
- * the BLASTSyncEngine which will deliver the Transaction to the callback.
- */
- if (callback != null) {
- syncId = startSyncWithOrganizer(callback);
+ int containerEffect = applyWindowContainerChange(wc, entry.getValue());
+ if (transition != null) transition.collect(wc);
+ effects |= containerEffect;
+
+ // Lifecycle changes will trigger ensureConfig for everything.
+ if ((effects & TRANSACT_EFFECTS_LIFECYCLE) == 0
+ && (containerEffect & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
+ haveConfigChanges.add(wc);
+ }
+ }
+ // Hierarchy changes
+ final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
+ for (int i = 0, n = hops.size(); i < n; ++i) {
+ final WindowContainerTransaction.HierarchyOp hop = hops.get(i);
+ final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
+ if (!wc.isAttached()) {
+ Slog.e(TAG, "Attempt to operate on detached container: " + wc);
+ continue;
+ }
+ if (syncId >= 0) {
+ addToSyncSet(syncId, wc);
}
- ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Apply window transaction, syncId=%d",
- syncId);
- mService.deferWindowLayout();
- try {
- ArraySet<WindowContainer> haveConfigChanges = new ArraySet<>();
- Iterator<Map.Entry<IBinder, WindowContainerTransaction.Change>> entries =
- t.getChanges().entrySet().iterator();
- while (entries.hasNext()) {
- final Map.Entry<IBinder, WindowContainerTransaction.Change> entry =
- entries.next();
- final WindowContainer wc = WindowContainer.fromBinder(entry.getKey());
- if (wc == null || !wc.isAttached()) {
- Slog.e(TAG, "Attempt to operate on detached container: " + wc);
- continue;
- }
- // Make sure we add to the syncSet before performing
- // operations so we don't end up splitting effects between the WM
- // pending transaction and the BLASTSync transaction.
- if (syncId >= 0) {
- addToSyncSet(syncId, wc);
- }
-
- int containerEffect = applyWindowContainerChange(wc, entry.getValue());
- if (transition != null) transition.collect(wc);
- effects |= containerEffect;
-
- // Lifecycle changes will trigger ensureConfig for everything.
- if ((effects & TRANSACT_EFFECTS_LIFECYCLE) == 0
- && (containerEffect & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
- haveConfigChanges.add(wc);
- }
- }
- // Hierarchy changes
- final List<WindowContainerTransaction.HierarchyOp> hops = t.getHierarchyOps();
- for (int i = 0, n = hops.size(); i < n; ++i) {
- final WindowContainerTransaction.HierarchyOp hop = hops.get(i);
- final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
- if (!wc.isAttached()) {
- Slog.e(TAG, "Attempt to operate on detached container: " + wc);
- continue;
- }
- if (syncId >= 0) {
- addToSyncSet(syncId, wc);
- }
effects |= sanitizeAndApplyHierarchyOp(wc, hop);
- if (transition != null) {
- transition.collect(wc);
- if (hop.isReparent() && hop.getNewParent() != null) {
- transition.collect(WindowContainer.fromBinder(hop.getNewParent()));
- }
- }
- }
- // Queue-up bounds-change transactions for tasks which are now organized. Do
- // this after hierarchy ops so we have the final organized state.
- entries = t.getChanges().entrySet().iterator();
- while (entries.hasNext()) {
- final Map.Entry<IBinder, WindowContainerTransaction.Change> entry =
- entries.next();
- final Task task = WindowContainer.fromBinder(entry.getKey()).asTask();
- final Rect surfaceBounds = entry.getValue().getBoundsChangeSurfaceBounds();
- if (task == null || !task.isAttached() || surfaceBounds == null) {
- continue;
- }
- if (!task.isOrganized()) {
- final Task parent =
- task.getParent() != null ? task.getParent().asTask() : null;
- // Also allow direct children of created-by-organizer tasks to be
- // controlled. In the future, these will become organized anyways.
- if (parent == null || !parent.mCreatedByOrganizer) {
- throw new IllegalArgumentException(
- "Can't manipulate non-organized task surface " + task);
- }
- }
- final SurfaceControl.Transaction sft = new SurfaceControl.Transaction();
- final SurfaceControl sc = task.getSurfaceControl();
- sft.setPosition(sc, surfaceBounds.left, surfaceBounds.top);
- if (surfaceBounds.isEmpty()) {
- sft.setWindowCrop(sc, null);
- } else {
- sft.setWindowCrop(sc, surfaceBounds.width(), surfaceBounds.height());
- }
- task.setMainWindowSizeChangeTransaction(sft);
+ if (transition != null) {
+ transition.collect(wc);
+ if (hop.isReparent() && hop.getNewParent() != null) {
+ transition.collect(WindowContainer.fromBinder(hop.getNewParent()));
}
- if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) {
- // Already calls ensureActivityConfig
- mService.mRootWindowContainer.ensureActivitiesVisible(
- null, 0, PRESERVE_WINDOWS);
- } else if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
- final PooledConsumer f = PooledLambda.obtainConsumer(
- ActivityRecord::ensureActivityConfiguration,
- PooledLambda.__(ActivityRecord.class), 0,
- true /* preserveWindow */);
- try {
- for (int i = haveConfigChanges.size() - 1; i >= 0; --i) {
- haveConfigChanges.valueAt(i).forAllActivities(f);
- }
- } finally {
- f.recycle();
- }
+ }
+ }
+ // Queue-up bounds-change transactions for tasks which are now organized. Do
+ // this after hierarchy ops so we have the final organized state.
+ entries = t.getChanges().entrySet().iterator();
+ while (entries.hasNext()) {
+ final Map.Entry<IBinder, WindowContainerTransaction.Change> entry = entries.next();
+ final Task task = WindowContainer.fromBinder(entry.getKey()).asTask();
+ final Rect surfaceBounds = entry.getValue().getBoundsChangeSurfaceBounds();
+ if (task == null || !task.isAttached() || surfaceBounds == null) {
+ continue;
+ }
+ if (!task.isOrganized()) {
+ final Task parent = task.getParent() != null ? task.getParent().asTask() : null;
+ // Also allow direct children of created-by-organizer tasks to be
+ // controlled. In the future, these will become organized anyways.
+ if (parent == null || !parent.mCreatedByOrganizer) {
+ throw new IllegalArgumentException(
+ "Can't manipulate non-organized task surface " + task);
}
-
- if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) == 0) {
- mService.addWindowLayoutReasons(LAYOUT_REASON_CONFIG_CHANGED);
+ }
+ final SurfaceControl.Transaction sft = new SurfaceControl.Transaction();
+ final SurfaceControl sc = task.getSurfaceControl();
+ sft.setPosition(sc, surfaceBounds.left, surfaceBounds.top);
+ if (surfaceBounds.isEmpty()) {
+ sft.setWindowCrop(sc, null);
+ } else {
+ sft.setWindowCrop(sc, surfaceBounds.width(), surfaceBounds.height());
+ }
+ task.setMainWindowSizeChangeTransaction(sft);
+ }
+ if ((effects & TRANSACT_EFFECTS_LIFECYCLE) != 0) {
+ // Already calls ensureActivityConfig
+ mService.mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
+ } else if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) != 0) {
+ final PooledConsumer f = PooledLambda.obtainConsumer(
+ ActivityRecord::ensureActivityConfiguration,
+ PooledLambda.__(ActivityRecord.class), 0,
+ true /* preserveWindow */);
+ try {
+ for (int i = haveConfigChanges.size() - 1; i >= 0; --i) {
+ haveConfigChanges.valueAt(i).forAllActivities(f);
}
} finally {
- mService.continueWindowLayout();
- if (syncId >= 0) {
- setSyncReady(syncId);
- }
+ f.recycle();
}
}
+
+ if ((effects & TRANSACT_EFFECTS_CLIENT_CONFIG) == 0) {
+ mService.addWindowLayoutReasons(LAYOUT_REASON_CONFIG_CHANGED);
+ }
} finally {
- Binder.restoreCallingIdentity(ident);
+ mService.continueWindowLayout();
}
- return syncId;
}
private int applyChanges(WindowContainer container, WindowContainerTransaction.Change change) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 2d69dcbcfbd0..2e7905c64049 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -505,33 +505,29 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
}
}
- boolean areBackgroundActivityStartsAllowed(boolean appSwitchAllowed) {
- // If app switching is not allowed, we ignore all the start activity grace period
- // exception so apps cannot start itself in onPause() after pressing home button.
- if (appSwitchAllowed) {
- // allow if any activity in the caller has either started or finished very recently, and
- // it must be started or finished after last stop app switches time.
- final long now = SystemClock.uptimeMillis();
- if (now - mLastActivityLaunchTime < ACTIVITY_BG_START_GRACE_PERIOD_MS
- || now - mLastActivityFinishTime < ACTIVITY_BG_START_GRACE_PERIOD_MS) {
- // if activity is started and finished before stop app switch time, we should not
- // let app to be able to start background activity even it's in grace period.
- if (mLastActivityLaunchTime > mAtm.getLastStopAppSwitchesTime()
- || mLastActivityFinishTime > mAtm.getLastStopAppSwitchesTime()) {
- if (DEBUG_ACTIVITY_STARTS) {
- Slog.d(TAG, "[WindowProcessController(" + mPid
- + ")] Activity start allowed: within "
- + ACTIVITY_BG_START_GRACE_PERIOD_MS + "ms grace period");
- }
- return true;
- }
+ boolean areBackgroundActivityStartsAllowed() {
+ // allow if any activity in the caller has either started or finished very recently, and
+ // it must be started or finished after last stop app switches time.
+ final long now = SystemClock.uptimeMillis();
+ if (now - mLastActivityLaunchTime < ACTIVITY_BG_START_GRACE_PERIOD_MS
+ || now - mLastActivityFinishTime < ACTIVITY_BG_START_GRACE_PERIOD_MS) {
+ // if activity is started and finished before stop app switch time, we should not
+ // let app to be able to start background activity even it's in grace period.
+ if (mLastActivityLaunchTime > mAtm.getLastStopAppSwitchesTime()
+ || mLastActivityFinishTime > mAtm.getLastStopAppSwitchesTime()) {
if (DEBUG_ACTIVITY_STARTS) {
- Slog.d(TAG, "[WindowProcessController(" + mPid + ")] Activity start within "
- + ACTIVITY_BG_START_GRACE_PERIOD_MS
- + "ms grace period but also within stop app switch window");
+ Slog.d(TAG, "[WindowProcessController(" + mPid
+ + ")] Activity start allowed: within "
+ + ACTIVITY_BG_START_GRACE_PERIOD_MS + "ms grace period");
}
-
+ return true;
+ }
+ if (DEBUG_ACTIVITY_STARTS) {
+ Slog.d(TAG, "[WindowProcessController(" + mPid + ")] Activity start within "
+ + ACTIVITY_BG_START_GRACE_PERIOD_MS
+ + "ms grace period but also within stop app switch window");
}
+
}
// allow if the proc is instrumenting with background activity starts privs
if (mInstrumentingWithBackgroundActivityStartPrivileges) {
@@ -543,7 +539,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
return true;
}
// allow if the caller has an activity in any foreground task
- if (appSwitchAllowed && hasActivityInVisibleTask()) {
+ if (hasActivityInVisibleTask()) {
if (DEBUG_ACTIVITY_STARTS) {
Slog.d(TAG, "[WindowProcessController(" + mPid
+ ")] Activity start allowed: process has activity in foreground task");
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 e116a353c723..03edc585b46a 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1131,6 +1131,7 @@ public final class SystemServer implements Dumpable {
IStorageManager storageManager = null;
NetworkManagementService networkManagement = null;
IpSecService ipSecService = null;
+ VcnManagementService vcnManagement = null;
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
IConnectivityManager connectivity = null;
@@ -1581,6 +1582,15 @@ public final class SystemServer implements Dumpable {
}
t.traceEnd();
+ t.traceBegin("StartVcnManagementService");
+ try {
+ vcnManagement = VcnManagementService.create(context);
+ ServiceManager.addService(Context.VCN_MANAGEMENT_SERVICE, vcnManagement);
+ } catch (Throwable e) {
+ reportWtf("starting VCN Management Service", e);
+ }
+ t.traceEnd();
+
t.traceBegin("StartTextServicesManager");
mSystemServiceManager.startService(TextServicesManagerService.Lifecycle.class);
t.traceEnd();
@@ -2371,6 +2381,7 @@ public final class SystemServer implements Dumpable {
final MediaRouterService mediaRouterF = mediaRouter;
final MmsServiceBroker mmsServiceF = mmsService;
final IpSecService ipSecServiceF = ipSecService;
+ final VcnManagementService vcnManagementF = vcnManagement;
final WindowManagerService windowManagerF = wm;
final ConnectivityManager connectivityF = (ConnectivityManager)
context.getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -2463,6 +2474,15 @@ public final class SystemServer implements Dumpable {
reportWtf("making IpSec Service ready", e);
}
t.traceEnd();
+ t.traceBegin("MakeVcnManagementServiceReady");
+ try {
+ if (vcnManagementF != null) {
+ vcnManagementF.systemReady();
+ }
+ } catch (Throwable e) {
+ reportWtf("making VcnManagementService ready", e);
+ }
+ t.traceEnd();
t.traceBegin("MakeNetworkStatsServiceReady");
try {
if (networkStatsF != null) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
index 3aedd3c7d753..d260e4dce79a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/LocationProviderManagerTest.java
@@ -22,6 +22,7 @@ import static android.app.AppOpsManager.OP_MONITOR_LOCATION;
import static android.location.Criteria.ACCURACY_COARSE;
import static android.location.Criteria.ACCURACY_FINE;
import static android.location.Criteria.POWER_HIGH;
+import static android.location.LocationRequest.PASSIVE_INTERVAL;
import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF;
import static androidx.test.ext.truth.location.LocationSubject.assertThat;
@@ -598,6 +599,38 @@ public class LocationProviderManagerTest {
}
@Test
+ public void testRegisterListener_Coarse() throws Exception {
+ ILocationListener listener = createMockLocationListener();
+ mManager.registerLocationRequest(
+ new LocationRequest.Builder(0).setWorkSource(WORK_SOURCE).build(),
+ IDENTITY,
+ PERMISSION_COARSE,
+ listener);
+
+ mProvider.setProviderLocation(createLocation(NAME, mRandom));
+ mProvider.setProviderLocation(createLocation(NAME, mRandom));
+ verify(listener, times(1))
+ .onLocationChanged(any(Location.class), nullable(IRemoteCallback.class));
+ }
+
+ @Test
+ public void testRegisterListener_Coarse_Passive() throws Exception {
+ ILocationListener listener = createMockLocationListener();
+ mManager.registerLocationRequest(
+ new LocationRequest.Builder(PASSIVE_INTERVAL)
+ .setMinUpdateIntervalMillis(0)
+ .setWorkSource(WORK_SOURCE).build(),
+ IDENTITY,
+ PERMISSION_COARSE,
+ listener);
+
+ mProvider.setProviderLocation(createLocation(NAME, mRandom));
+ mProvider.setProviderLocation(createLocation(NAME, mRandom));
+ verify(listener, times(1))
+ .onLocationChanged(any(Location.class), nullable(IRemoteCallback.class));
+ }
+
+ @Test
public void testGetCurrentLocation() throws Exception {
ArgumentCaptor<Location> locationCaptor = ArgumentCaptor.forClass(Location.class);
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/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/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 6255630712ae..95c881e1d927 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -63,7 +63,6 @@ import com.android.server.LocalServices;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.permission.LegacyPermissionDataProvider;
-import com.android.server.pm.permission.PermissionSettings;
import com.google.common.truth.Truth;
@@ -92,8 +91,6 @@ public class PackageManagerSettingsTests {
private static final int TEST_RESOURCE_ID = 2131231283;
@Mock
- PermissionSettings mPermissionSettings;
- @Mock
RuntimePermissionsPersistence mRuntimePermissionsPersistence;
@Mock
LegacyPermissionDataProvider mPermissionDataProvider;
@@ -117,7 +114,7 @@ public class PackageManagerSettingsTests {
writeOldFiles();
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- Settings settings = new Settings(context.getFilesDir(), mPermissionSettings,
+ Settings settings = new Settings(context.getFilesDir(),
mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
verifyKeySetMetaData(settings);
@@ -131,7 +128,7 @@ public class PackageManagerSettingsTests {
writeOldFiles();
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- Settings settings = new Settings(context.getFilesDir(), mPermissionSettings,
+ Settings settings = new Settings(context.getFilesDir(),
mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
@@ -147,7 +144,7 @@ public class PackageManagerSettingsTests {
writeOldFiles();
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- Settings settings = new Settings(context.getFilesDir(), mPermissionSettings,
+ Settings settings = new Settings(context.getFilesDir(),
mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
assertThat(settings.getPackageLPr(PACKAGE_NAME_3), is(notNullValue()));
@@ -169,13 +166,13 @@ public class PackageManagerSettingsTests {
writeOldFiles();
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- Settings settings = new Settings(context.getFilesDir(), mPermissionSettings,
+ Settings settings = new Settings(context.getFilesDir(),
mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
settings.writeLPr();
// Create Settings again to make it read from the new files
- settings = new Settings(context.getFilesDir(), mPermissionSettings,
+ settings = new Settings(context.getFilesDir(),
mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
@@ -199,7 +196,7 @@ public class PackageManagerSettingsTests {
writePackageRestrictions_noSuspendingPackageXml(0);
final Object lock = new Object();
final Context context = InstrumentationRegistry.getTargetContext();
- final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null, null,
+ final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null,
lock);
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, createPackageSetting(PACKAGE_NAME_2));
@@ -223,7 +220,7 @@ public class PackageManagerSettingsTests {
writePackageRestrictions_noSuspendParamsMapXml(0);
final Object lock = new Object();
final Context context = InstrumentationRegistry.getTargetContext();
- final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null, null,
+ final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null,
lock);
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
settingsUnderTest.readPackageRestrictionsLPr(0);
@@ -251,7 +248,7 @@ public class PackageManagerSettingsTests {
@Test
public void testReadWritePackageRestrictions_suspendInfo() {
final Context context = InstrumentationRegistry.getTargetContext();
- final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null, null,
+ final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null,
new Object());
final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
@@ -349,7 +346,7 @@ public class PackageManagerSettingsTests {
@Test
public void testReadWritePackageRestrictions_distractionFlags() {
final Context context = InstrumentationRegistry.getTargetContext();
- final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null, null,
+ final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null,
new Object());
final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
@@ -393,7 +390,7 @@ public class PackageManagerSettingsTests {
public void testWriteReadUsesStaticLibraries() {
final Context context = InstrumentationRegistry.getTargetContext();
final Object lock = new Object();
- final Settings settingsUnderTest = new Settings(context.getFilesDir(), mPermissionSettings,
+ final Settings settingsUnderTest = new Settings(context.getFilesDir(),
mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
ps1.appId = Process.FIRST_APPLICATION_UID;
@@ -469,7 +466,7 @@ public class PackageManagerSettingsTests {
writeOldFiles();
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- Settings settings = new Settings(context.getFilesDir(), mPermissionSettings,
+ Settings settings = new Settings(context.getFilesDir(),
mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
@@ -642,7 +639,7 @@ public class PackageManagerSettingsTests {
public void testUpdatePackageSetting03() {
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- final Settings testSettings01 = new Settings(context.getFilesDir(), mPermissionSettings,
+ final Settings testSettings01 = new Settings(context.getFilesDir(),
mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
final SharedUserSetting testUserSetting01 = createSharedUserSetting(
testSettings01, "TestUser", 10064, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/);
@@ -752,7 +749,7 @@ public class PackageManagerSettingsTests {
public void testCreateNewSetting03() {
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
- final Settings testSettings01 = new Settings(context.getFilesDir(), mPermissionSettings,
+ final Settings testSettings01 = new Settings(context.getFilesDir(),
mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
final SharedUserSetting testUserSetting01 = createSharedUserSetting(
testSettings01, "TestUser", 10064, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index e304083dfd27..c50792866582 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -126,6 +126,7 @@ public class ManagedServicesTest extends UiServiceTestCase {
users.add(mTen);
users.add(new UserInfo(11, "11", 0));
users.add(new UserInfo(12, "12", 0));
+ users.add(new UserInfo(13, "13", 0));
for (UserInfo user : users) {
when(mUm.getUserInfo(eq(user.id))).thenReturn(user);
}
@@ -135,6 +136,7 @@ public class ManagedServicesTest extends UiServiceTestCase {
profileIds.add(11);
profileIds.add(10);
profileIds.add(12);
+ profileIds.add(13);
when(mUserProfiles.getCurrentProfileIds()).thenReturn(profileIds);
mVersionString = "2";
@@ -145,11 +147,13 @@ public class ManagedServicesTest extends UiServiceTestCase {
mExpectedPrimaryPackages.put(10, "this.is.another.package");
mExpectedPrimaryPackages.put(11, "");
mExpectedPrimaryPackages.put(12, "bananas!");
+ mExpectedPrimaryPackages.put(13, "non.user.set.package");
mExpectedPrimaryComponentNames = new ArrayMap<>();
mExpectedPrimaryComponentNames.put(0, "this.is.a.package.name/Ba:another.package/B1");
mExpectedPrimaryComponentNames.put(10, "this.is.another.package/M1");
mExpectedPrimaryComponentNames.put(11, "");
mExpectedPrimaryComponentNames.put(12, "bananas!/Bananas!");
+ mExpectedPrimaryComponentNames.put(13, "non.user.set.package/M1");
mExpectedPrimary.put(APPROVAL_BY_PACKAGE, mExpectedPrimaryPackages);
mExpectedPrimary.put(APPROVAL_BY_COMPONENT, mExpectedPrimaryComponentNames);
@@ -341,6 +345,35 @@ public class ManagedServicesTest extends UiServiceTestCase {
}
}
+ /** Test that restore correctly parses the user_set attribute. */
+ @Test
+ public void testReadXml_restoresUserSet() throws Exception {
+ for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
+ ManagedServices service =
+ new TestManagedServices(
+ getContext(), mLock, mUserProfiles, mIpm, approvalLevel);
+ String testPackage = "user.test.package";
+ String testComponent = "user.test.component/C1";
+ String resolvedValue =
+ (approvalLevel == APPROVAL_BY_COMPONENT) ? testComponent : testPackage;
+ String xmlEntry = getXmlEntry(resolvedValue, 0, true, false);
+ XmlPullParser parser = getParserWithEntries(service, xmlEntry);
+
+ service.readXml(parser, null, true, 0);
+
+ assertFalse("Failed while parsing xml:\n" + xmlEntry,
+ service.isPackageOrComponentUserSet(resolvedValue, 0));
+
+ xmlEntry = getXmlEntry(resolvedValue, 0, true, true);
+ parser = getParserWithEntries(service, xmlEntry);
+
+ service.readXml(parser, null, true, 0);
+
+ assertTrue("Failed while parsing xml:\n" + xmlEntry,
+ service.isPackageOrComponentUserSet(resolvedValue, 0));
+ }
+ }
+
/** Test that restore ignores the user id attribute and applies the data to the target user. */
@Test
public void testWriteReadXml_writeReadDefaults() throws Exception {
@@ -374,7 +407,6 @@ public class ManagedServicesTest extends UiServiceTestCase {
assertEquals(1, defaults.size());
assertEquals(new ComponentName("package", "class"), defaults.valueAt(0));
-
}
@Test
@@ -628,6 +660,47 @@ public class ManagedServicesTest extends UiServiceTestCase {
}
@Test
+ public void testWriteXml_writesUserSet() throws Exception {
+ for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
+ ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
+ mIpm, approvalLevel);
+ loadXml(service);
+
+ XmlSerializer serializer = new FastXmlSerializer();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
+ serializer.startDocument(null, true);
+ service.writeXml(serializer, false, UserHandle.USER_ALL);
+ serializer.endDocument();
+ serializer.flush();
+
+ XmlPullParser parser = Xml.newPullParser();
+ byte[] rawOutput = baos.toByteArray();
+ parser.setInput(new BufferedInputStream(
+ new ByteArrayInputStream(rawOutput)), null);
+ parser.nextTag();
+ for (UserInfo userInfo : mUm.getUsers()) {
+ service.readXml(parser, null, true, userInfo.id);
+ }
+
+ String resolvedUserSetComponent = approvalLevel == APPROVAL_BY_PACKAGE
+ ? mExpectedPrimaryPackages.get(10)
+ : mExpectedPrimaryComponentNames.get(10);
+ String resolvedNonUserSetComponent = approvalLevel == APPROVAL_BY_PACKAGE
+ ? mExpectedPrimaryPackages.get(13)
+ : mExpectedPrimaryComponentNames.get(13);
+
+ try {
+ assertFalse(service.isPackageOrComponentUserSet(resolvedNonUserSetComponent, 13));
+ assertTrue(service.isPackageOrComponentUserSet(resolvedUserSetComponent, 10));
+ } catch (AssertionError e) {
+ throw new AssertionError(
+ "Assertion failed while parsing xml:\n" + new String(rawOutput), e);
+ }
+ }
+ }
+
+ @Test
public void rebindServices_onlyBindsExactMatchesIfComponent() throws Exception {
// If the primary and secondary lists contain component names, only those components within
// the package should be matched
@@ -965,6 +1038,7 @@ public class ManagedServicesTest extends UiServiceTestCase {
allowedPackages.add("package");
allowedPackages.add("component");
allowedPackages.add("bananas!");
+ allowedPackages.add("non.user.set.package");
Set<String> actual = service.getAllowedPackages();
assertEquals(allowedPackages.size(), actual.size());
@@ -1037,6 +1111,9 @@ public class ManagedServicesTest extends UiServiceTestCase {
expected12.add(ComponentName.unflattenFromString("bananas!/Bananas!"));
expected.put(12, expected12);
expected.put(11, new ArraySet<>());
+ ArraySet<ComponentName> expected13 = new ArraySet<>();
+ expected13.add(ComponentName.unflattenFromString("non.user.set.package/M1"));
+ expected.put(13, expected13);
SparseArray<ArraySet<ComponentName>> actual =
service.getAllowedComponents(mUserProfiles.getCurrentProfileIds());
@@ -1309,6 +1386,15 @@ public class ManagedServicesTest extends UiServiceTestCase {
}
private void loadXml(ManagedServices service) throws Exception {
+ String xmlString = createXml(service);
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new BufferedInputStream(
+ new ByteArrayInputStream(xmlString.getBytes())), null);
+ parser.nextTag();
+ service.readXml(parser, null, false, UserHandle.USER_ALL);
+ }
+
+ private String createXml(ManagedServices service) {
final StringBuffer xml = new StringBuffer();
String xmlTag = service.getConfig().xmlTag;
xml.append("<" + xmlTag
@@ -1316,8 +1402,9 @@ public class ManagedServicesTest extends UiServiceTestCase {
+ (mVersionString != null ? " version=\"" + mVersionString + "\" " : "")
+ ">\n");
for (int userId : mExpectedPrimary.get(service.mApprovalLevel).keySet()) {
+ String pkgOrCmp = mExpectedPrimary.get(service.mApprovalLevel).get(userId);
xml.append(getXmlEntry(
- mExpectedPrimary.get(service.mApprovalLevel).get(userId), userId, true));
+ pkgOrCmp, userId, true, !(pkgOrCmp.startsWith("non.user.set.package"))));
}
for (int userId : mExpectedSecondary.get(service.mApprovalLevel).keySet()) {
xml.append(getXmlEntry(
@@ -1333,11 +1420,7 @@ public class ManagedServicesTest extends UiServiceTestCase {
+ ManagedServices.ATT_APPROVED_LIST + "=\"98\" />\n");
xml.append("</" + xmlTag + ">");
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(new BufferedInputStream(
- new ByteArrayInputStream(xml.toString().getBytes())), null);
- parser.nextTag();
- service.readXml(parser, null, false, UserHandle.USER_ALL);
+ return xml.toString();
}
private XmlPullParser getParserWithEntries(ManagedServices service, String... xmlEntries)
@@ -1524,10 +1607,15 @@ public class ManagedServicesTest extends UiServiceTestCase {
}
private String getXmlEntry(String approved, int userId, boolean isPrimary) {
+ return getXmlEntry(approved, userId, isPrimary, true);
+ }
+
+ private String getXmlEntry(String approved, int userId, boolean isPrimary, boolean userSet) {
return "<" + ManagedServices.TAG_MANAGED_SERVICES + " "
+ ManagedServices.ATT_USER_ID + "=\"" + userId +"\" "
+ ManagedServices.ATT_IS_PRIMARY + "=\"" + isPrimary +"\" "
+ ManagedServices.ATT_APPROVED_LIST + "=\"" + approved +"\" "
+ + ManagedServices.ATT_USER_SET + "=\"" + (userSet ? approved : "") + "\" "
+ "/>\n";
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
index 5796e848ff6e..f649911b6bb9 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAssistantsTest.java
@@ -134,7 +134,7 @@ public class NotificationAssistantsTest extends UiServiceTestCase {
verify(mNm, never()).setDefaultAssistantForUser(anyInt());
verify(mAssistants, times(1)).addApprovedList(
- new ComponentName("b", "b").flattenToString(),10, true);
+ new ComponentName("b", "b").flattenToString(), 10, true, null);
}
@Test
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 740505e0d3d7..87aaba2b164a 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -111,9 +111,9 @@ import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentUris;
import android.content.Context;
+import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.IIntentSender;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
@@ -2880,16 +2880,17 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
public void testSetListenerAccessForUser() throws Exception {
UserHandle user = UserHandle.of(10);
ComponentName c = ComponentName.unflattenFromString("package/Component");
- mBinderService.setNotificationListenerAccessGrantedForUser(c, user.getIdentifier(), true);
+ mBinderService.setNotificationListenerAccessGrantedForUser(
+ c, user.getIdentifier(), true, true);
verify(mContext, times(1)).sendBroadcastAsUser(any(), eq(user), any());
verify(mListeners, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), user.getIdentifier(), true, true);
+ c.flattenToString(), user.getIdentifier(), true, true, true);
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), user.getIdentifier(), false, true);
+ c.flattenToString(), user.getIdentifier(), false, true, true);
verify(mAssistants, never()).setPackageOrComponentEnabled(
- any(), anyInt(), anyBoolean(), anyBoolean());
+ any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
}
@Test
@@ -2958,12 +2959,12 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testSetListenerAccess() throws Exception {
ComponentName c = ComponentName.unflattenFromString("package/Component");
- mBinderService.setNotificationListenerAccessGranted(c, true);
+ mBinderService.setNotificationListenerAccessGranted(c, true, true);
verify(mListeners, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, true, true);
+ c.flattenToString(), 0, true, true, true);
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, false, true);
+ c.flattenToString(), 0, false, true, true);
verify(mAssistants, never()).setPackageOrComponentEnabled(
any(), anyInt(), anyBoolean(), anyBoolean());
}
@@ -3112,12 +3113,12 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
public void testSetListenerAccess_onLowRam() throws Exception {
when(mActivityManager.isLowRamDevice()).thenReturn(true);
ComponentName c = ComponentName.unflattenFromString("package/Component");
- mBinderService.setNotificationListenerAccessGranted(c, true);
+ mBinderService.setNotificationListenerAccessGranted(c, true, true);
verify(mListeners).setPackageOrComponentEnabled(
- anyString(), anyInt(), anyBoolean(), anyBoolean());
+ anyString(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
verify(mConditionProviders).setPackageOrComponentEnabled(
- anyString(), anyInt(), anyBoolean(), anyBoolean());
+ anyString(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
verify(mAssistants).migrateToXml();
verify(mAssistants).resetDefaultAssistantsIfNecessary();
}
@@ -3160,14 +3161,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mActivityManager.isLowRamDevice()).thenReturn(true);
ComponentName c = ComponentName.unflattenFromString("package/Component");
- mBinderService.setNotificationListenerAccessGranted(c, true);
+ mBinderService.setNotificationListenerAccessGranted(c, true, true);
verify(mListeners, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, true, true);
+ c.flattenToString(), 0, true, true, true);
verify(mConditionProviders, times(1)).setPackageOrComponentEnabled(
- c.flattenToString(), 0, false, true);
+ c.flattenToString(), 0, false, true, true);
verify(mAssistants, never()).setPackageOrComponentEnabled(
- any(), anyInt(), anyBoolean(), anyBoolean());
+ any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
}
@Test
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 91e55ed7ab6a..b6b3d66d9c04 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -17,11 +17,15 @@
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -33,6 +37,8 @@ import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.clearInvocations;
+import android.app.WindowConfiguration;
+import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
@@ -220,4 +226,35 @@ public class TaskTests extends WindowTestsBase {
assertTrue(activity1.isVisible());
assertTrue(activity2.isVisible());
}
+
+ @Test
+ public void testResolveNonResizableTaskWindowingMode() {
+ final Task task = createTaskStackOnDisplay(mDisplayContent);
+ Configuration parentConfig = task.getParent().getConfiguration();
+ parentConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ doReturn(false).when(task).isResizeable();
+ WindowConfiguration requestedOverride =
+ task.getRequestedOverrideConfiguration().windowConfiguration;
+ WindowConfiguration resolvedOverride =
+ task.getResolvedOverrideConfiguration().windowConfiguration;
+
+ // The resolved override windowing mode of a non-resizeable task should be resolved as
+ // fullscreen even as a child of a freeform display.
+ requestedOverride.setWindowingMode(WINDOWING_MODE_UNDEFINED);
+ task.resolveOverrideConfiguration(parentConfig);
+ assertThat(resolvedOverride.getWindowingMode()).isEqualTo(WINDOWING_MODE_FULLSCREEN);
+
+ // The resolved override windowing mode of a non-resizeable task should be resolved as
+ // fullscreen, even when requested as freeform windowing mode
+ requestedOverride.setWindowingMode(WINDOWING_MODE_FREEFORM);
+ task.resolveOverrideConfiguration(parentConfig);
+ assertThat(resolvedOverride.getWindowingMode()).isEqualTo(WINDOWING_MODE_FULLSCREEN);
+
+ // The resolved override windowing mode of a non-resizeable task can be undefined as long
+ // as its parents is not in multi-window mode.
+ parentConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+ requestedOverride.setWindowingMode(WINDOWING_MODE_UNDEFINED);
+ task.resolveOverrideConfiguration(parentConfig);
+ assertThat(resolvedOverride.getWindowingMode()).isEqualTo(WINDOWING_MODE_UNDEFINED);
+ }
}
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..f1d49d5fc6c2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -976,6 +976,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/telephony/common/com/android/internal/telephony/CarrierAppUtils.java b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
index cfc7ac176f89..b92d410f3d6c 100644
--- a/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
+++ b/telephony/common/com/android/internal/telephony/CarrierAppUtils.java
@@ -125,11 +125,7 @@ public final class CarrierAppUtils {
}
private static boolean isUpdatedSystemApp(ApplicationInfo ai) {
- if ((ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
- return true;
- }
-
- return false;
+ return (ai.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
}
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 556e0b2b4096..c982f490e0fd 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5703,14 +5703,14 @@ public class TelephonyManager {
public static final int ERI_ICON_MODE_FLASH = 1;
/**
- * Returns the CDMA ERI icon index to display. The number is assigned by
- * 3GPP2 C.R1001-H v1.0 Table 8.1-1. Additionally carriers define their own ERI icon index.
+ * Returns the CDMA ERI icon display number. The number is assigned by
+ * 3GPP2 C.R1001-H v1.0 Table 8.1-1. Additionally carriers define their own ERI display numbers.
* Defined values are {@link #ERI_ON}, {@link #ERI_OFF}, and {@link #ERI_FLASH}.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public @EriIconIndex int getCdmaEnhancedRoamingIndicatorIconIndex() {
+ public @EriIconIndex int getCdmaEnhancedRoamingIndicatorDisplayNumber() {
return getCdmaEriIconIndex(getSubId());
}
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 953a2924dc44..b1700a10a288 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -496,6 +496,10 @@ public interface RILConstants {
int RIL_REQUEST_ENTER_SIM_DEPERSONALIZATION = 212;
int RIL_REQUEST_ENABLE_NR_DUAL_CONNECTIVITY = 213;
int RIL_REQUEST_IS_NR_DUAL_CONNECTIVITY_ENABLED = 214;
+ int RIL_REQUEST_ALLOCATE_PDU_SESSION_ID = 215;
+ int RIL_REQUEST_RELEASE_PDU_SESSION_ID = 216;
+ int RIL_REQUEST_BEGIN_HANDOVER = 217;
+ int RIL_REQUEST_CANCEL_HANDOVER = 218;
/* Responses begin */
int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 2a0c99c3bc52..7470cd898396 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -251,6 +251,7 @@ import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.AdditionalAnswers;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
@@ -452,6 +453,13 @@ public class ConnectivityServiceTest {
}
@Override
+ public Context createContextAsUser(UserHandle user, int flags) {
+ final Context asUser = mock(Context.class, AdditionalAnswers.delegatesTo(this));
+ doReturn(user).when(asUser).getUser();
+ return asUser;
+ }
+
+ @Override
public ContentResolver getContentResolver() {
return mContentResolver;
}
@@ -4992,22 +5000,22 @@ public class ConnectivityServiceTest {
// simulate that situation and check if ConnectivityService could filter that case.
mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
waitForIdle();
- verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notifyAsUser(anyString(),
- eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
+ verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).notify(anyString(),
+ eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
// If private DNS resolution successful, the PRIVATE_DNS_BROKEN notification shouldn't be
// shown.
mWiFiNetworkAgent.setNetworkValid(true /* isStrictMode */);
mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
waitForIdle();
- verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancelAsUser(anyString(),
- eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), eq(UserHandle.ALL));
+ verify(mNotificationManager, timeout(TIMEOUT_MS).times(1)).cancel(anyString(),
+ eq(NotificationType.PRIVATE_DNS_BROKEN.eventId));
// If private DNS resolution failed again, the PRIVATE_DNS_BROKEN notification should be
// shown again.
mWiFiNetworkAgent.setNetworkInvalid(true /* isStrictMode */);
mWiFiNetworkAgent.mNetworkMonitor.forceReevaluation(Process.myUid());
waitForIdle();
- verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notifyAsUser(anyString(),
- eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any(), eq(UserHandle.ALL));
+ verify(mNotificationManager, timeout(TIMEOUT_MS).times(2)).notify(anyString(),
+ eq(NotificationType.PRIVATE_DNS_BROKEN.eventId), any());
}
@Test
diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
index 47db5d431671..b47be97ed002 100644
--- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -22,6 +22,7 @@ import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
@@ -36,6 +37,7 @@ import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
+import android.os.UserHandle;
import android.telephony.TelephonyManager;
import androidx.test.filters.SmallTest;
@@ -47,6 +49,7 @@ import com.android.server.connectivity.NetworkNotificationManager.NotificationTy
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.AdditionalAnswers;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -104,17 +107,22 @@ public class NetworkNotificationManagerTest {
when(mCtx.getResources()).thenReturn(mResources);
when(mCtx.getPackageManager()).thenReturn(mPm);
when(mCtx.getApplicationInfo()).thenReturn(new ApplicationInfo());
+ final Context asUserCtx = mock(Context.class, AdditionalAnswers.delegatesTo(mCtx));
+ doReturn(UserHandle.ALL).when(asUserCtx).getUser();
+ when(mCtx.createContextAsUser(eq(UserHandle.ALL), anyInt())).thenReturn(asUserCtx);
+ when(mCtx.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
+ .thenReturn(mNotificationManager);
when(mNetworkInfo.getExtraInfo()).thenReturn("extra");
when(mResources.getColor(anyInt(), any())).thenReturn(0xFF607D8B);
- mManager = new NetworkNotificationManager(mCtx, mTelephonyManager, mNotificationManager);
+ mManager = new NetworkNotificationManager(mCtx, mTelephonyManager);
}
private void verifyTitleByNetwork(final int id, final NetworkAgentInfo nai, final int title) {
final String tag = NetworkNotificationManager.tagFor(id);
mManager.showNotification(id, PRIVATE_DNS_BROKEN, nai, null, null, true);
verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(PRIVATE_DNS_BROKEN.eventId), any(), any());
+ .notify(eq(tag), eq(PRIVATE_DNS_BROKEN.eventId), any());
final int transportType = NetworkNotificationManager.approximateTransportType(nai);
if (transportType == NetworkCapabilities.TRANSPORT_WIFI) {
verify(mResources, times(1)).getString(title, eq(any()));
@@ -164,8 +172,8 @@ public class NetworkNotificationManagerTest {
final int id = ids.get(i);
final int eventId = types.get(i).eventId;
final String tag = NetworkNotificationManager.tagFor(id);
- verify(mNotificationManager, times(1)).notifyAsUser(eq(tag), eq(eventId), any(), any());
- verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(eventId), any());
+ verify(mNotificationManager, times(1)).notify(eq(tag), eq(eventId), any());
+ verify(mNotificationManager, times(1)).cancel(eq(tag), eq(eventId));
}
}
@@ -174,13 +182,13 @@ public class NetworkNotificationManagerTest {
mManager.showNotification(100, NO_INTERNET, mCellNai, mWifiNai, null, false);
mManager.showNotification(101, LOST_INTERNET, mCellNai, mWifiNai, null, false);
- verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false);
final int eventId = NO_INTERNET.eventId;
final String tag = NetworkNotificationManager.tagFor(102);
- verify(mNotificationManager, times(1)).notifyAsUser(eq(tag), eq(eventId), any(), any());
+ verify(mNotificationManager, times(1)).notify(eq(tag), eq(eventId), any());
}
@Test
@@ -191,7 +199,7 @@ public class NetworkNotificationManagerTest {
mManager.showNotification(103, LOST_INTERNET, mWifiNai, mCellNai, null, false);
mManager.showNotification(104, NETWORK_SWITCH, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
}
@Test
@@ -201,19 +209,16 @@ public class NetworkNotificationManagerTest {
// Show first NO_INTERNET
mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(NO_INTERNET.eventId), any(), any());
+ verify(mNotificationManager, times(1)).notify(eq(tag), eq(NO_INTERNET.eventId), any());
// Captive portal detection triggers SIGN_IN a bit later, clearing the previous NO_INTERNET
mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(1))
- .cancelAsUser(eq(tag), eq(NO_INTERNET.eventId), any());
- verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any());
+ verify(mNotificationManager, times(1)).cancel(eq(tag), eq(NO_INTERNET.eventId));
+ verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any());
// Network disconnects
mManager.clearNotification(id);
- verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(SIGN_IN.eventId), any());
+ verify(mNotificationManager, times(1)).cancel(eq(tag), eq(SIGN_IN.eventId));
}
@Test
@@ -223,18 +228,17 @@ public class NetworkNotificationManagerTest {
// Show first SIGN_IN
mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any());
+ verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any());
reset(mNotificationManager);
// NO_INTERNET arrives after, but is ignored.
mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, never()).cancelAsUser(any(), anyInt(), any());
- verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
+ verify(mNotificationManager, never()).cancel(any(), anyInt());
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
// Network disconnects
mManager.clearNotification(id);
- verify(mNotificationManager, times(1)).cancelAsUser(eq(tag), eq(SIGN_IN.eventId), any());
+ verify(mNotificationManager, times(1)).cancel(eq(tag), eq(SIGN_IN.eventId));
}
@Test
@@ -246,24 +250,20 @@ public class NetworkNotificationManagerTest {
// to previous type or not. If they are equal then clear the notification; if they are not
// equal then return.
mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(NO_INTERNET.eventId), any(), any());
+ verify(mNotificationManager, times(1)).notify(eq(tag), eq(NO_INTERNET.eventId), any());
// Previous notification is NO_INTERNET and given type is NO_INTERNET too. The notification
// should be cleared.
mManager.clearNotification(id, NO_INTERNET);
- verify(mNotificationManager, times(1))
- .cancelAsUser(eq(tag), eq(NO_INTERNET.eventId), any());
+ verify(mNotificationManager, times(1)).cancel(eq(tag), eq(NO_INTERNET.eventId));
// SIGN_IN is popped-up.
mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(1))
- .notifyAsUser(eq(tag), eq(SIGN_IN.eventId), any(), any());
+ verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any());
// The notification type is not matching previous one, PARTIAL_CONNECTIVITY won't be
// cleared.
mManager.clearNotification(id, PARTIAL_CONNECTIVITY);
- verify(mNotificationManager, never())
- .cancelAsUser(eq(tag), eq(PARTIAL_CONNECTIVITY.eventId), any());
+ verify(mNotificationManager, never()).cancel(eq(tag), eq(PARTIAL_CONNECTIVITY.eventId));
}
}
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index bc3db11ccd3c..e3ba3e106e14 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -45,6 +45,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
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;
@@ -106,6 +107,7 @@ import com.android.server.IpSecService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.AdditionalAnswers;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
@@ -215,6 +217,8 @@ public class VpnTest {
when(mContext.getOpPackageName()).thenReturn(TEST_VPN_PKG);
when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps);
+ when(mContext.getSystemServiceName(NotificationManager.class))
+ .thenReturn(Context.NOTIFICATION_SERVICE);
when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
.thenReturn(mNotificationManager);
when(mContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE)))
@@ -594,26 +598,23 @@ public class VpnTest {
// Don't show a notification for regular disconnected states.
vpn.updateState(DetailedState.DISCONNECTED, TAG);
- order.verify(mNotificationManager, atLeastOnce())
- .cancelAsUser(anyString(), anyInt(), eq(userHandle));
+ order.verify(mNotificationManager, atLeastOnce()).cancel(anyString(), anyInt());
// Start showing a notification for disconnected once always-on.
vpn.setAlwaysOnPackage(PKGS[0], false, null, mKeyStore);
- order.verify(mNotificationManager)
- .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
+ order.verify(mNotificationManager).notify(anyString(), anyInt(), any());
// Stop showing the notification once connected.
vpn.updateState(DetailedState.CONNECTED, TAG);
- order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle));
+ order.verify(mNotificationManager).cancel(anyString(), anyInt());
// Show the notification if we disconnect again.
vpn.updateState(DetailedState.DISCONNECTED, TAG);
- order.verify(mNotificationManager)
- .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
+ order.verify(mNotificationManager).notify(anyString(), anyInt(), any());
// Notification should be cleared after unsetting always-on package.
vpn.setAlwaysOnPackage(null, false, null, mKeyStore);
- order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle));
+ order.verify(mNotificationManager).cancel(anyString(), anyInt());
}
@Test
@@ -1272,6 +1273,10 @@ public class VpnTest {
* Mock some methods of vpn object.
*/
private Vpn createVpn(@UserIdInt int userId) {
+ final Context asUserContext = mock(Context.class, AdditionalAnswers.delegatesTo(mContext));
+ doReturn(UserHandle.of(userId)).when(asUserContext).getUser();
+ when(mContext.createContextAsUser(eq(UserHandle.of(userId)), anyInt()))
+ .thenReturn(asUserContext);
return new Vpn(Looper.myLooper(), mContext, new TestDeps(), mNetService,
userId, mKeyStore, mSystemServices, mIkev2SessionCreator);
}
diff --git a/wifi/api/system-current.txt b/wifi/api/system-current.txt
index 5dc5dfc02bce..edbd46300191 100644
--- a/wifi/api/system-current.txt
+++ b/wifi/api/system-current.txt
@@ -246,6 +246,7 @@ package android.net.wifi {
field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.SoftApCapability> CREATOR;
field public static final long SOFTAP_FEATURE_ACS_OFFLOAD = 1L; // 0x1L
field public static final long SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT = 2L; // 0x2L
+ field public static final long SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION = 8L; // 0x8L
field public static final long SOFTAP_FEATURE_WPA3_SAE = 4L; // 0x4L
}
@@ -336,8 +337,11 @@ package android.net.wifi {
field @Deprecated public static final int RANDOMIZATION_NONE = 0; // 0x0
field @Deprecated public static final int RANDOMIZATION_PERSISTENT = 1; // 0x1
field @Deprecated public static final int RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA = 17; // 0x11
+ field @Deprecated public static final int RECENT_FAILURE_DISCONNECTION_AP_BUSY = 1004; // 0x3ec
field @Deprecated public static final int RECENT_FAILURE_MBO_OCE_DISCONNECT = 1001; // 0x3e9
field @Deprecated public static final int RECENT_FAILURE_NONE = 0; // 0x0
+ field @Deprecated public static final int RECENT_FAILURE_POOR_CHANNEL_CONDITIONS = 1003; // 0x3eb
+ field @Deprecated public static final int RECENT_FAILURE_REFUSED_TEMPORARILY = 1002; // 0x3ea
field @Deprecated public boolean allowAutojoin;
field @Deprecated public int carrierId;
field @Deprecated public String creatorName;
@@ -424,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
@@ -614,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/jarjar-rules.txt b/wifi/jarjar-rules.txt
index b0ff4bb27e70..ff06a180b8c1 100644
--- a/wifi/jarjar-rules.txt
+++ b/wifi/jarjar-rules.txt
@@ -36,7 +36,7 @@ rule android.net.ipmemorystore.IOnStatusListener* com.android.wifi.x.@0
rule android.net.ipmemorystore.NetworkAttributesParcelable* com.android.wifi.x.@0
rule android.net.ipmemorystore.SameL3NetworkResponseParcelable* com.android.wifi.x.@0
rule android.net.ipmemorystore.StatusParcelable* com.android.wifi.x.@0
-rule android.net.networkstack.aidl.quirks.IPv6ProvisioningLossQuirk* com.android.wifi.x.@0
+rule android.net.networkstack.aidl.** com.android.wifi.x.@0
# Net utils (includes Network Stack helper classes).
rule android.net.DhcpResults* com.android.wifi.x.@0
diff --git a/wifi/java/android/net/wifi/SoftApCapability.java b/wifi/java/android/net/wifi/SoftApCapability.java
index 6bd4211d8214..d570b7e8afa9 100644
--- a/wifi/java/android/net/wifi/SoftApCapability.java
+++ b/wifi/java/android/net/wifi/SoftApCapability.java
@@ -46,7 +46,7 @@ public final class SoftApCapability implements Parcelable {
* Support for automatic channel selection in driver (ACS).
* Driver will auto select best channel based on interference to optimize performance.
*
- * flag when {@link R.bool.config_wifi_softap_acs_supported)} is true.
+ * flag when {@link R.bool.config_wifi_softap_acs_supported} is true.
*
* <p>
* Use {@link WifiManager.SoftApCallback#onInfoChanged(SoftApInfo)} and
@@ -57,7 +57,7 @@ public final class SoftApCapability implements Parcelable {
/**
* Support for client force disconnect.
- * flag when {@link R.bool.config_wifi_sofap_client_force_disconnect_supported)} is true
+ * flag when {@link R.bool.config_wifiSofapClientForceDisconnectSupported} is true
*
* <p>
* Several Soft AP client control features, e.g. specifying the maximum number of
@@ -67,20 +67,32 @@ public final class SoftApCapability implements Parcelable {
*/
public static final long SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT = 1 << 1;
-
/**
* Support for WPA3 Simultaneous Authentication of Equals (WPA3-SAE).
*
- * flag when {@link config_wifi_softap_sae_supported)} is true.
+ * flag when {@link config_wifi_softap_sae_supported} is true.
*/
public static final long SOFTAP_FEATURE_WPA3_SAE = 1 << 2;
+ /**
+ * Support for MAC address customization.
+ * flag when {@link R.bool.config_wifiSoftapMacAddressCustomizationSupported} is true
+ *
+ * <p>
+ * Check feature support before invoking
+ * {@link SoftApConfiguration.Builder#setBssid(MadAddress)} or
+ * {@link SoftApConfiguration.Builder#setMacRandomizationSetting(int)} with
+ * {@link SoftApConfiguration.RANDOMIZATION_PERSISTENT}
+ */
+ public static final long SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION = 1 << 3;
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@LongDef(flag = true, prefix = { "SOFTAP_FEATURE_" }, value = {
SOFTAP_FEATURE_ACS_OFFLOAD,
SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT,
SOFTAP_FEATURE_WPA3_SAE,
+ SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION,
})
public @interface HotspotFeatures {}
diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java
index 2c53daaf55a7..c0f6e7a20f95 100644
--- a/wifi/java/android/net/wifi/SoftApConfiguration.java
+++ b/wifi/java/android/net/wifi/SoftApConfiguration.java
@@ -819,6 +819,11 @@ public final class SoftApConfiguration implements Parcelable {
* Derived MAC address 1: e2:c7:60:c4:0e:b7
* Derived MAC address 2: e2:38:9f:c4:0e:b7
*
+ * <p>
+ * Use {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and
+ * {@link SoftApCapability#areFeaturesSupported(long)}
+ * with {@link SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION} to determine
+ * whether or not this feature is supported.
*
* @param bssid BSSID, or null to have the BSSID chosen by the framework. The caller is
* responsible for avoiding collisions.
@@ -957,9 +962,9 @@ public final class SoftApConfiguration implements Parcelable {
* {@link #setBand(int)}.
*
* The channel auto selection will be offloaded to driver when
- * {@link SoftApCapability#areFeaturesSupported(
- * SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD)}
- * returns true. The driver will auto select the best channel (e.g. best performance)
+ * {@link SoftApCapability#areFeaturesSupported(long)}
+ * with {@link SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD}
+ * return true. The driver will auto select the best channel (e.g. best performance)
* based on environment interference. Check {@link SoftApCapability} for more detail.
*
* The API contains (band, channel) input since the 6GHz band uses the same channel
@@ -998,8 +1003,8 @@ public final class SoftApConfiguration implements Parcelable {
* auto-select a valid channel from the band configured with {@link #setBands(int[])}.
*
* The channel auto selection will be offloaded to driver when
- * {@link SoftApCapability#areFeaturesSupported(
- * SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD)}
+ * {@link SoftApCapability#areFeaturesSupported(long)}
+ * with {@link SoftApCapability.SOFTAP_FEATURE_ACS_OFFLOAD}
* returns true. The driver will auto select the best channel (e.g. best performance)
* based on environment interference. Check {@link SoftApCapability} for more detail.
*
@@ -1046,14 +1051,14 @@ public final class SoftApConfiguration implements Parcelable {
* <p>
* <li>If not set, defaults to 0.</li>
*
- * This method requires hardware support. If the method is used to set a
+ * This method requires HAL support. If the method is used to set a
* non-zero {@code maxNumberOfClients} value then
* {@link WifiManager#startTetheredHotspot} will report error code
* {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}.
*
* <p>
* Use {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and
- * {@link SoftApCapability#areFeaturesSupported(int)}
+ * {@link SoftApCapability#areFeaturesSupported(long)}
* with {@link SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT} to determine whether
* or not this feature is supported.
*
@@ -1127,13 +1132,13 @@ public final class SoftApConfiguration implements Parcelable {
* {@link #setBlockedClientList(List)} and {@link #setAllowedClientList(List)}.
*
* <p>
- * This method requires hardware support. Hardware support can be determined using
+ * This method requires HAL support. HAL support can be determined using
* {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and
- * {@link SoftApCapability#areFeaturesSupported(int)}
+ * {@link SoftApCapability#areFeaturesSupported(long)}
* with {@link SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT}
*
* <p>
- * If the method is called on a device without hardware support then starting the soft AP
+ * If the method is called on a device without HAL support then starting the soft AP
* using {@link WifiManager#startTetheredHotspot(SoftApConfiguration)} will fail with
* {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}.
*
@@ -1182,13 +1187,13 @@ public final class SoftApConfiguration implements Parcelable {
* to the Soft AP.
*
* <p>
- * This method requires hardware support. Hardware support can be determined using
+ * This method requires HAL support. HAL support can be determined using
* {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and
- * {@link SoftApCapability#areFeaturesSupported(int)}
+ * {@link SoftApCapability#areFeaturesSupported(long)}
* with {@link SoftApCapability.SOFTAP_FEATURE_CLIENT_FORCE_DISCONNECT}
*
* <p>
- * If the method is called on a device without hardware support then starting the soft AP
+ * If the method is called on a device without HAL support then starting the soft AP
* using {@link WifiManager#startTetheredHotspot(SoftApConfiguration)} will fail with
* {@link WifiManager#SAP_START_FAILURE_UNSUPPORTED_CONFIGURATION}.
*
@@ -1210,7 +1215,14 @@ public final class SoftApConfiguration implements Parcelable {
* <p>
* <li>If not set, defaults to {@link #RANDOMIZATION_PERSISTENT}</li>
*
- * @param macRandomizationSetting One of the following setting:.
+ * <p>
+ * Requires HAL support when set to {@link #RANDOMIZATION_PERSISTENT}.
+ * Use {@link WifiManager.SoftApCallback#onCapabilityChanged(SoftApCapability)} and
+ * {@link SoftApCapability#areFeaturesSupported(long)}
+ * with {@link SoftApCapability.SOFTAP_FEATURE_MAC_ADDRESS_CUSTOMIZATION} to determine
+ * whether or not this feature is supported.
+ *
+ * @param macRandomizationSetting One of the following setting:
* {@link #RANDOMIZATION_NONE} or {@link #RANDOMIZATION_PERSISTENT}.
* @return Builder for chaining.
*
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 9a8a5ad4b41f..8103ff717ef3 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.
@@ -2074,27 +2085,42 @@ public class WifiConfiguration implements Parcelable {
*/
@RecentFailureReason
private int mAssociationStatus = RECENT_FAILURE_NONE;
+ private long mLastUpdateTimeSinceBootMillis;
/**
* @param status the association status code for the recent failure
*/
- public void setAssociationStatus(@RecentFailureReason int status) {
+ public void setAssociationStatus(@RecentFailureReason int status,
+ long updateTimeSinceBootMs) {
mAssociationStatus = status;
+ mLastUpdateTimeSinceBootMillis = updateTimeSinceBootMs;
}
/**
* Sets the RecentFailure to NONE
*/
public void clear() {
mAssociationStatus = RECENT_FAILURE_NONE;
+ mLastUpdateTimeSinceBootMillis = 0;
}
/**
- * Get the recent failure code. One of {@link #RECENT_FAILURE_NONE} or
- * {@link #RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA}.
+ * Get the recent failure code. One of {@link #RECENT_FAILURE_NONE},
+ * {@link #RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA},
+ * {@link #RECENT_FAILURE_MBO_OCE_DISCONNECT},
+ * {@link #RECENT_FAILURE_REFUSED_TEMPORARILY},
+ * {@link #RECENT_FAILURE_POOR_CHANNEL_CONDITIONS}.
+ * {@link #RECENT_FAILURE_DISCONNECTION_AP_BUSY}
*/
@RecentFailureReason
public int getAssociationStatus() {
return mAssociationStatus;
}
+
+ /**
+ * Get the timestamp the failure status is last updated, in milliseconds since boot.
+ */
+ public long getLastUpdateTimeSinceBootMillis() {
+ return mLastUpdateTimeSinceBootMillis;
+ }
}
/**
@@ -2111,7 +2137,11 @@ public class WifiConfiguration implements Parcelable {
@IntDef(prefix = "RECENT_FAILURE_", value = {
RECENT_FAILURE_NONE,
RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA,
- RECENT_FAILURE_MBO_OCE_DISCONNECT})
+ RECENT_FAILURE_MBO_OCE_DISCONNECT,
+ RECENT_FAILURE_REFUSED_TEMPORARILY,
+ RECENT_FAILURE_POOR_CHANNEL_CONDITIONS,
+ RECENT_FAILURE_DISCONNECTION_AP_BUSY
+ })
public @interface RecentFailureReason {}
/**
@@ -2136,12 +2166,39 @@ public class WifiConfiguration implements Parcelable {
public static final int RECENT_FAILURE_MBO_OCE_DISCONNECT = 1001;
/**
+ * Failed to connect because the association is rejected by the AP.
+ * IEEE 802.11 association status code 30.
+ * @hide
+ */
+ @SystemApi
+ public static final int RECENT_FAILURE_REFUSED_TEMPORARILY = 1002;
+
+ /**
+ * Failed to connect because of excess frame loss and/or poor channel conditions.
+ * IEEE 802.11 association status code 34.
+ * @hide
+ */
+ @SystemApi
+ public static final int RECENT_FAILURE_POOR_CHANNEL_CONDITIONS = 1003;
+
+ /**
+ * Disconnected by the AP because the AP can't handle all the associated stations.
+ * IEEE 802.11 disconnection reason code 5.
+ * @hide
+ */
+ @SystemApi
+ public static final int RECENT_FAILURE_DISCONNECTION_AP_BUSY = 1004;
+
+ /**
* Get the failure reason for the most recent connection attempt, or
* {@link #RECENT_FAILURE_NONE} if there was no failure.
*
* Failure reasons include:
* {@link #RECENT_FAILURE_AP_UNABLE_TO_HANDLE_NEW_STA}
- *
+ * {@link #RECENT_FAILURE_MBO_OCE_DISCONNECT}
+ * {@link #RECENT_FAILURE_REFUSED_TEMPORARILY}
+ * {@link #RECENT_FAILURE_POOR_CHANNEL_CONDITIONS}
+ * {@link #RECENT_FAILURE_DISCONNECTION_AP_BUSY}
* @hide
*/
@RecentFailureReason
@@ -2203,6 +2260,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;
@@ -2326,13 +2384,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) {
@@ -2479,7 +2538,8 @@ public class WifiConfiguration implements Parcelable {
}
}
sbuf.append("recentFailure: ").append("Association Rejection code: ")
- .append(recentFailure.getAssociationStatus()).append("\n");
+ .append(recentFailure.getAssociationStatus()).append(", last update time: ")
+ .append(recentFailure.getLastUpdateTimeSinceBootMillis()).append("\n");
return sbuf.toString();
}
@@ -2896,6 +2956,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;
@@ -2918,7 +2979,8 @@ public class WifiConfiguration implements Parcelable {
numNoInternetAccessReports = source.numNoInternetAccessReports;
noInternetAccessExpected = source.noInternetAccessExpected;
shared = source.shared;
- recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus());
+ recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus(),
+ source.recentFailure.getLastUpdateTimeSinceBootMillis());
mRandomizedMacAddress = source.mRandomizedMacAddress;
macRandomizationSetting = source.macRandomizationSetting;
randomizedMacExpirationTimeMs = source.randomizedMacExpirationTimeMs;
@@ -2976,6 +3038,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);
@@ -2995,6 +3058,7 @@ public class WifiConfiguration implements Parcelable {
dest.writeInt(shared ? 1 : 0);
dest.writeString(mPasspointManagementObjectTree);
dest.writeInt(recentFailure.getAssociationStatus());
+ dest.writeLong(recentFailure.getLastUpdateTimeSinceBootMillis());
dest.writeParcelable(mRandomizedMacAddress, flags);
dest.writeInt(macRandomizationSetting);
dest.writeInt(osu ? 1 : 0);
@@ -3053,6 +3117,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;
@@ -3071,7 +3136,7 @@ public class WifiConfiguration implements Parcelable {
config.noInternetAccessExpected = in.readInt() != 0;
config.shared = in.readInt() != 0;
config.mPasspointManagementObjectTree = in.readString();
- config.recentFailure.setAssociationStatus(in.readInt());
+ config.recentFailure.setAssociationStatus(in.readInt(), in.readLong());
config.mRandomizedMacAddress = in.readParcelable(null);
config.macRandomizationSetting = in.readInt();
config.osu = 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/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.