summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp665
-rw-r--r--ApiDocs.bp436
-rw-r--r--StubLibraries.bp340
-rw-r--r--apex/sdkext/derive_sdk/derive_sdk.cpp2
-rw-r--r--apex/statsd/aidl/android/os/IPullAtomCallback.aidl2
-rw-r--r--apex/statsd/aidl/android/os/IStatsCompanionService.aidl3
-rw-r--r--apex/statsd/aidl/android/os/IStatsd.aidl5
-rw-r--r--apex/statsd/framework/Android.bp2
-rw-r--r--apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java24
-rw-r--r--api/current.txt16
-rw-r--r--api/removed.txt9
-rwxr-xr-xapi/system-current.txt59
-rw-r--r--api/test-current.txt1
-rw-r--r--cmds/statsd/Android.bp2
-rw-r--r--cmds/statsd/src/StatsService.cpp7
-rw-r--r--cmds/statsd/src/StatsService.h5
-rw-r--r--cmds/statsd/src/external/StatsPuller.cpp1
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.cpp13
-rw-r--r--cmds/statsd/src/external/StatsPullerManager.h4
-rw-r--r--cmds/svc/src/com/android/commands/svc/DataCommand.java68
-rw-r--r--cmds/svc/src/com/android/commands/svc/Svc.java1
-rwxr-xr-xcmds/svc/svc14
-rw-r--r--core/java/android/annotation/CallbackExecutor.java10
-rw-r--r--core/java/android/annotation/RequiresPermission.java11
-rw-r--r--core/java/android/app/Activity.java15
-rw-r--r--core/java/android/app/ActivityManager.java13
-rw-r--r--core/java/android/app/IActivityManager.aidl5
-rw-r--r--core/java/android/app/IActivityTaskManager.aidl5
-rw-r--r--core/java/android/app/StatsManager.java56
-rw-r--r--core/java/android/app/SystemServiceRegistry.java24
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java17
-rw-r--r--core/java/android/companion/Association.aidl (renamed from packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgHandler.java)16
-rw-r--r--core/java/android/companion/Association.java179
-rw-r--r--core/java/android/companion/ICompanionDeviceDiscoveryService.aidl5
-rw-r--r--core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl25
-rw-r--r--core/java/android/content/Context.java8
-rw-r--r--core/java/android/content/Intent.java1
-rw-r--r--core/java/android/content/integrity/AppInstallMetadata.java13
-rw-r--r--core/java/android/content/pm/DataLoaderParams.java72
-rw-r--r--core/java/android/content/pm/DataLoaderParamsParcel.aidl5
-rw-r--r--core/java/android/content/pm/DataLoaderType.aidl37
-rw-r--r--core/java/android/content/pm/IDataLoader.aidl4
-rw-r--r--core/java/android/content/pm/IDataLoaderStatusListener.aidl17
-rw-r--r--core/java/android/content/pm/PackageInstaller.java42
-rw-r--r--core/java/android/os/incremental/IncrementalFileStorages.java4
-rw-r--r--core/java/android/security/FileIntegrityManager.java77
-rw-r--r--core/java/android/security/IFileIntegrityService.aidl (renamed from packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainLooper.java)22
-rw-r--r--core/java/android/service/dataloader/DataLoaderService.java229
-rw-r--r--core/java/android/telephony/PhoneStateListener.java19
-rw-r--r--core/java/android/telephony/TelephonyRegistryManager.java9
-rw-r--r--core/java/android/view/RemoteAnimationDefinition.java17
-rw-r--r--core/java/android/view/SurfaceControl.java95
-rw-r--r--core/java/android/view/View.java25
-rw-r--r--core/java/android/view/ViewGroup.java4
-rw-r--r--core/java/android/view/textclassifier/TextLinks.java36
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java31
-rw-r--r--core/java/com/android/internal/app/ChooserStackedAppDialogFragment.java20
-rw-r--r--core/java/com/android/internal/app/SuspendedAppActivity.java11
-rw-r--r--core/java/com/android/internal/app/chooser/MultiDisplayResolveInfo.java34
-rw-r--r--core/java/com/android/internal/content/FileSystemProvider.java19
-rw-r--r--core/java/com/android/internal/infra/AndroidFuture.aidl2
-rw-r--r--core/java/com/android/internal/infra/PerUser.java59
-rw-r--r--core/java/com/android/internal/os/Zygote.java4
-rw-r--r--core/java/com/android/internal/telephony/IPhoneStateListener.aidl7
-rw-r--r--core/java/com/android/internal/telephony/ITelephonyRegistry.aidl8
-rw-r--r--core/java/com/android/internal/util/FunctionalUtils.java33
-rw-r--r--core/jni/android_media_AudioFormat.h5
-rw-r--r--core/jni/android_os_Debug.cpp2
-rw-r--r--core/jni/android_service_DataLoaderService.cpp23
-rw-r--r--core/jni/android_view_SurfaceControl.cpp82
-rw-r--r--core/res/AndroidManifest.xml10
-rw-r--r--core/res/res/values/config.xml11
-rw-r--r--core/res/res/values/dimens.xml1
-rw-r--r--core/res/res/values/public.xml8
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java8
-rw-r--r--core/tests/overlaytests/device/res/layout/layout.xml39
-rw-r--r--core/tests/overlaytests/device/res/values/config.xml12
-rw-r--r--core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java54
-rw-r--r--core/tests/overlaytests/device/src/com/android/overlaytest/view/TestTextView.java48
-rw-r--r--core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml3
-rw-r--r--core/tests/overlaytests/device/test-apps/AppOverlayOne/res/layout/layout.xml39
-rw-r--r--core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml5
-rw-r--r--core/tests/overlaytests/device/test-apps/AppOverlayOne/res/xml/overlays.xml61
-rw-r--r--libs/androidfw/Idmap.cpp8
-rw-r--r--libs/androidfw/include/androidfw/Idmap.h9
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h2
-rw-r--r--media/Android.bp4
-rw-r--r--media/java/android/media/AudioFormat.java12
-rw-r--r--media/java/android/media/AudioPlaybackConfiguration.java23
-rw-r--r--media/java/android/media/MediaRoute2ProviderInfo.java5
-rw-r--r--media/java/android/media/MediaRoute2ProviderService.java188
-rw-r--r--media/java/android/media/RouteSessionInfo.java87
-rw-r--r--media/java/android/media/tv/tuner/FilterSettings.java92
-rw-r--r--media/java/android/media/tv/tuner/ScanMessage.java131
-rw-r--r--media/java/android/media/tv/tuner/Tuner.java81
-rw-r--r--media/java/android/media/tv/tuner/TunerConstants.java70
-rw-r--r--media/java/android/media/tv/tuner/TunerUtils.java135
-rw-r--r--media/jni/android_media_MediaMetricsJNI.cpp21
-rw-r--r--media/jni/android_media_MediaMuxer.cpp33
-rw-r--r--media/jni/android_media_tv_Tuner.cpp33
-rw-r--r--media/jni/android_media_tv_Tuner.h2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraErrorCollector.java4
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/InMatcher.java2
-rw-r--r--media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java48
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java4
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java4
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java7
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java7
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java4
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java4
-rw-r--r--packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java22
-rw-r--r--packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp12
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java2
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java4
-rw-r--r--packages/SettingsProvider/res/values/blocked_settings.xml24
-rw-r--r--packages/SettingsProvider/res/values/overlayable.xml25
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java143
-rw-r--r--packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java54
-rw-r--r--packages/SystemUI/Android.bp1
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/CarrierTextController.java4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/ScreenDecorations.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIService.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/UiOffloadThread.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainResources.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/qualifiers/UiBackground.java (renamed from packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainHandler.java)6
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroupController.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java70
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/time/SystemClock.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/time/SystemClockImpl.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java36
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java32
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java119
-rw-r--r--packages/WindowManager/OWNERS3
-rw-r--r--packages/WindowManager/Shell/Android.bp29
-rw-r--r--packages/WindowManager/Shell/AndroidManifest.xml20
-rw-r--r--packages/WindowManager/Shell/OWNERS4
-rw-r--r--packages/WindowManager/Shell/res/values/config.xml21
-rw-r--r--packages/WindowManager/Shell/src/com/android/wm/shell/WindowManagerShell.java (renamed from packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgLooper.java)17
-rw-r--r--packages/WindowManager/Shell/tests/Android.bp45
-rw-r--r--packages/WindowManager/Shell/tests/AndroidManifest.xml32
-rw-r--r--packages/WindowManager/Shell/tests/AndroidTest.xml31
-rw-r--r--packages/WindowManager/Shell/tests/res/values/config.xml21
-rw-r--r--packages/WindowManager/Shell/tests/src/com/android/wm/shell/tests/WindowManagerShellTest.java40
-rw-r--r--packages/overlays/Android.mk2
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java2
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/SecondFingerMultiTap.java167
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java26
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java2
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java189
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java31
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java77
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java20
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java2
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java42
-rw-r--r--services/core/java/com/android/server/display/DisplayDevice.java13
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java29
-rw-r--r--services/core/java/com/android/server/display/DisplayModeDirector.java136
-rw-r--r--services/core/java/com/android/server/display/LocalDisplayAdapter.java214
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplay.java25
-rw-r--r--services/core/java/com/android/server/display/OverlayDisplayAdapter.java6
-rw-r--r--services/core/java/com/android/server/incremental/IncrementalManagerService.java7
-rw-r--r--services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java10
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java2
-rw-r--r--services/core/java/com/android/server/integrity/AppIntegrityManagerService.java4
-rw-r--r--services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java504
-rw-r--r--services/core/java/com/android/server/integrity/IntegrityFileManager.java169
-rw-r--r--services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java24
-rw-r--r--services/core/java/com/android/server/integrity/model/RuleMetadata.java41
-rw-r--r--services/core/java/com/android/server/integrity/parser/RuleMetadataParser.java67
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleMetadataSerializer.java52
-rw-r--r--services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java32
-rw-r--r--services/core/java/com/android/server/media/AudioPlayerStateMonitor.java3
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java2
-rw-r--r--services/core/java/com/android/server/pm/DataLoaderManagerService.java30
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java209
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java519
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java13
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java92
-rw-r--r--services/core/java/com/android/server/pm/PackageVerificationState.java58
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java36
-rw-r--r--services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java12
-rw-r--r--services/core/java/com/android/server/security/FileIntegrityService.java170
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java12
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartInterceptor.java3
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java18
-rw-r--r--services/core/java/com/android/server/wm/RootActivityContainer.java178
-rw-r--r--services/core/java/com/android/server/wm/Task.java5
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java84
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java15
-rw-r--r--services/incremental/IncrementalService.cpp27
-rw-r--r--services/incremental/Metadata.proto2
-rw-r--r--services/incremental/test/IncrementalServiceTest.cpp6
-rw-r--r--services/java/com/android/server/SystemServer.java8
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java5
-rw-r--r--services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/test.apkbin0 -> 1357952 bytes
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java21
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java349
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java190
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java75
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java61
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java55
-rw-r--r--telephony/java/android/telephony/Annotation.java80
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java23
-rw-r--r--telephony/java/android/telephony/CellIdentity.java4
-rw-r--r--telephony/java/android/telephony/CellIdentityCdma.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityGsm.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityLte.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityNr.java2
-rw-r--r--telephony/java/android/telephony/CellIdentityTdscdma.java1
-rw-r--r--telephony/java/android/telephony/CellIdentityWcdma.java2
-rw-r--r--telephony/java/android/telephony/PreciseCallState.java24
-rw-r--r--telephony/java/android/telephony/SmsMessage.java16
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java25
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl6
-rw-r--r--tests/ApkVerityTest/AndroidTest.xml2
-rw-r--r--wifi/java/android/net/wifi/EasyConnectStatusCallback.java102
-rw-r--r--wifi/java/android/net/wifi/IDppCallback.aidl2
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java86
-rw-r--r--wifi/java/android/net/wifi/WifiScanner.java27
-rw-r--r--wifi/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java84
-rw-r--r--wifi/tests/src/android/net/wifi/WifiManagerTest.java60
-rw-r--r--wifi/tests/src/android/net/wifi/WifiScannerTest.java20
291 files changed, 7663 insertions, 2969 deletions
diff --git a/Android.bp b/Android.bp
index 536f6885bd13..08b5b4aeed21 100644
--- a/Android.bp
+++ b/Android.bp
@@ -353,9 +353,6 @@ java_library {
"com.android.sysprop.apex",
"PlatformProperties",
],
- aidl: {
- include_dirs: ["system/connectivity/wificond/aidl"],
- },
sdk_version: "core_platform",
installable: false,
}
@@ -605,7 +602,7 @@ filegroup {
java_library {
name: "framework-annotations-lib",
srcs: [ ":framework-annotations" ],
- sdk_version: "current",
+ sdk_version: "core_current",
}
filegroup {
@@ -699,7 +696,7 @@ java_library {
"core/proto/android/privacy.proto",
"core/proto/android/section.proto",
],
- sdk_version: "current",
+ sdk_version: "9",
srcs: [
"core/proto/**/*.proto",
"libs/incident/proto/android/os/**/*.proto",
@@ -722,6 +719,7 @@ java_library {
"core/proto/android/privacy.proto",
"core/proto/android/section.proto",
],
+ sdk_version: "core_current",
// Protos have lots of MissingOverride and similar.
errorprone: {
javacflags: ["-XepDisableAllChecks"],
@@ -833,6 +831,7 @@ filegroup {
name: "dataloader_aidl",
srcs: [
"core/java/android/content/pm/DataLoaderParamsParcel.aidl",
+ "core/java/android/content/pm/DataLoaderType.aidl",
"core/java/android/content/pm/FileSystemControlParcel.aidl",
"core/java/android/content/pm/IDataLoaderStatusListener.aidl",
"core/java/android/content/pm/IPackageInstallerSessionFileSystemConnector.aidl",
@@ -1023,645 +1022,6 @@ python_binary_host {
],
}
-// Make the api/current.txt file available for use by modules in other
-// directories.
-filegroup {
- name: "frameworks-base-api-current.txt",
- srcs: [
- "api/current.txt",
- ],
-}
-
-// Make the api/system-current.txt file available for use by modules in other
-// directories.
-filegroup {
- name: "frameworks-base-api-system-current.txt",
- srcs: [
- "api/system-current.txt",
- ],
-}
-
-// Make the api/system-removed.txt file available for use by modules in other
-// directories.
-filegroup {
- name: "frameworks-base-api-system-removed.txt",
- srcs: [
- "api/system-removed.txt",
- ],
-}
-
-framework_docs_only_args = " -android -manifest $(location core/res/AndroidManifest.xml) " +
- "-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
- "-overview $(location core/java/overview.html) " +
- // Federate Support Library references against local API file.
- "-federate SupportLib https://developer.android.com " +
- "-federationapi SupportLib $(location :current-support-api) " +
- // Federate Support Library references against local API file.
- "-federate AndroidX https://developer.android.com " +
- "-federationapi AndroidX $(location :current-androidx-api) "
-
-framework_docs_only_libs = [
- "voip-common",
- "android.test.mock",
- "android-support-annotations",
- "android-support-compat",
- "android-support-core-ui",
- "android-support-core-utils",
- "android-support-design",
- "android-support-dynamic-animation",
- "android-support-exifinterface",
- "android-support-fragment",
- "android-support-media-compat",
- "android-support-percent",
- "android-support-transition",
- "android-support-v7-cardview",
- "android-support-v7-gridlayout",
- "android-support-v7-mediarouter",
- "android-support-v7-palette",
- "android-support-v7-preference",
- "android-support-v13",
- "android-support-v14-preference",
- "android-support-v17-leanback",
- "android-support-vectordrawable",
- "android-support-animatedvectordrawable",
- "android-support-v7-appcompat",
- "android-support-v7-recyclerview",
- "android-support-v8-renderscript",
- "android-support-multidex",
- "android-support-multidex-instrumentation",
-]
-
-metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
- "--ignore-classes-on-classpath " +
- "--hide-package com.android.server " +
- "--error UnhiddenSystemApi " +
- "--hide RequiresPermission " +
- "--hide CallbackInterface " +
- "--hide MissingPermission --hide BroadcastBehavior " +
- "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
- "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
- "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.*"
-
-packages_to_document = [
- "android",
- "dalvik",
- "java",
- "javax",
- "junit",
- "org.apache.http",
- "org.json",
- "org.w3c.dom",
- "org.xml.sax",
- "org.xmlpull",
-]
-
-stubs_defaults {
- name: "framework-doc-stubs-default",
- srcs: [
- ":framework-mime-sources",
- ":framework-non-updatable-sources",
- ":framework-updatable-sources",
- "core/java/**/*.logtags",
- "test-base/src/**/*.java",
- ":opt-telephony-srcs",
- ":opt-net-voip-srcs",
- ":core-current-stubs-source",
- ":core_public_api_files",
- "test-mock/src/**/*.java",
- "test-runner/src/**/*.java",
- ],
- libs: framework_docs_only_libs,
- create_doc_stubs: true,
- annotations_enabled: true,
- api_levels_annotations_enabled: true,
- api_levels_annotations_dirs: [
- "sdk-dir",
- "api-versions-jars-dir",
- ],
- previous_api: ":last-released-public-api",
- merge_annotations_dirs: [
- "metalava-manual",
- ],
-}
-
-doc_defaults {
- name: "framework-docs-default",
- libs: framework_docs_only_libs +
- ["stub-annotations"],
- html_dirs: [
- "docs/html",
- ],
- knowntags: [
- "docs/knowntags.txt",
- ":known-oj-tags",
- ],
- custom_template: "droiddoc-templates-sdk",
- resourcesdir: "docs/html/reference/images/",
- resourcesoutdir: "reference/android/images/",
- hdf: [
- "dac true",
- "sdk.codename O",
- "sdk.preview.version 1",
- "sdk.version 7.0",
- "sdk.rel.id 1",
- "sdk.preview 0",
- ],
- arg_files: [
- "core/res/AndroidManifest.xml",
- "core/java/overview.html",
- ":current-support-api",
- ":current-androidx-api",
- ],
- create_stubs: false,
-}
-
-doc_defaults {
- name: "framework-dokka-docs-default",
- create_stubs: false,
-}
-
-stubs_defaults {
- name: "metalava-api-stubs-default",
- srcs: [
- ":framework-non-updatable-sources",
- ":framework-updatable-sources",
- "core/java/**/*.logtags",
- ":opt-telephony-srcs",
- ":opt-net-voip-srcs",
- ":core-current-stubs-source",
- ":core_public_api_files",
- ":ike-api-srcs",
- ],
- libs: ["framework-internal-utils"],
- installable: false,
- annotations_enabled: true,
- previous_api: ":last-released-public-api",
- merge_annotations_dirs: [
- "metalava-manual",
- ],
- api_levels_annotations_enabled: true,
- api_levels_annotations_dirs: [
- "sdk-dir",
- "api-versions-jars-dir",
- ],
- sdk_version: "core_platform",
- filter_packages: packages_to_document,
-}
-
-droidstubs {
- name: "framework-doc-stubs",
- defaults: ["framework-doc-stubs-default"],
- arg_files: [
- "core/res/AndroidManifest.xml",
- ],
- args: metalava_framework_docs_args,
- write_sdk_values: true,
-}
-
-droidstubs {
- name: "framework-doc-system-stubs",
- defaults: ["framework-doc-stubs-default"],
- arg_files: [
- "core/res/AndroidManifest.xml",
- ],
- args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) ",
- write_sdk_values: true,
-}
-
-droiddoc {
- name: "doc-comment-check-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- args: framework_docs_only_args + " -referenceonly -parsecomments",
- installable: false,
-}
-
-droiddoc {
- name: "offline-sdk-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc offline",
- ],
- proofread_file: "offline-sdk-docs-proofrerad.txt",
- args: framework_docs_only_args + " -offlinemode -title \"Android SDK\"",
- static_doc_index_redirect: "docs/docs-preview-index.html",
-}
-
-droiddoc {
- // Please sync with android-api-council@ before making any changes for the name property below.
- // Since there's cron jobs that fetch offline-sdk-referenceonly-docs-docs.zip periodically.
- // See b/116221385 for reference.
- name: "offline-sdk-referenceonly-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc offline",
- ],
- proofread_file: "offline-sdk-referenceonly-docs-proofrerad.txt",
- args: framework_docs_only_args + " -offlinemode -title \"Android SDK\" -referenceonly",
- static_doc_index_redirect: "docs/docs-documentation-redirect.html",
- static_doc_properties: "docs/source.properties",
-}
-
-droiddoc {
- // Please sync with android-api-council@ before making any changes for the name property below.
- // Since there's cron jobs that fetch offline-system-sdk-referenceonly-docs-docs.zip periodically.
- // See b/116221385 for reference.
- name: "offline-system-sdk-referenceonly-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-system-stubs",
- ],
- hdf: [
- "android.whichdoc offline",
- ],
- proofread_file: "offline-system-sdk-referenceonly-docs-proofrerad.txt",
- args: framework_docs_only_args + " -hide 101 -hide 104 -hide 108" +
- " -offlinemode -title \"Android System SDK\" -referenceonly",
- static_doc_index_redirect: "docs/docs-documentation-redirect.html",
- static_doc_properties: "docs/source.properties",
-}
-
-droiddoc {
- name: "online-sdk-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc online",
- "android.hasSamples true",
- ],
- proofread_file: "online-sdk-docs-proofrerad.txt",
- args: framework_docs_only_args +
- " -toroot / -samplegroup Admin " +
- " -samplegroup Background " +
- " -samplegroup Connectivity " +
- " -samplegroup Content " +
- " -samplegroup Input " +
- " -samplegroup Media " +
- " -samplegroup Notification " +
- " -samplegroup RenderScript " +
- " -samplegroup Security " +
- " -samplegroup Sensors " +
- " -samplegroup System " +
- " -samplegroup Testing " +
- " -samplegroup UI " +
- " -samplegroup Views " +
- " -samplegroup Wearable -samplesdir development/samples/browseable ",
-}
-
-droiddoc {
- name: "online-system-api-sdk-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-system-stubs",
- ],
- hdf: [
- "android.whichdoc online",
- "android.hasSamples true",
- ],
- proofread_file: "online-system-api-sdk-docs-proofrerad.txt",
- args: framework_docs_only_args +
- " -referenceonly " +
- " -title \"Android SDK - Including system APIs.\" " +
- " -hide 101 " +
- " -hide 104 " +
- " -hide 108 " +
- " -toroot / -samplegroup Admin " +
- " -samplegroup Background " +
- " -samplegroup Connectivity " +
- " -samplegroup Content " +
- " -samplegroup Input " +
- " -samplegroup Media " +
- " -samplegroup Notification " +
- " -samplegroup RenderScript " +
- " -samplegroup Security " +
- " -samplegroup Sensors " +
- " -samplegroup System " +
- " -samplegroup Testing " +
- " -samplegroup UI " +
- " -samplegroup Views " +
- " -samplegroup Wearable -samplesdir development/samples/browseable ",
- installable: false,
-}
-
-droiddoc {
- name: "ds-docs-java",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc online",
- "android.hasSamples true",
- ],
- proofread_file: "ds-docs-proofrerad.txt",
- args: framework_docs_only_args +
- " -toroot / -yamlV2 -metalavaApiSince -samplegroup Admin " +
- " -samplegroup Background " +
- " -samplegroup Connectivity " +
- " -samplegroup Content " +
- " -samplegroup Input " +
- " -samplegroup Media " +
- " -samplegroup Notification " +
- " -samplegroup RenderScript " +
- " -samplegroup Security " +
- " -samplegroup Sensors " +
- " -samplegroup System " +
- " -samplegroup Testing " +
- " -samplegroup UI " +
- " -samplegroup Views " +
- " -samplegroup Wearable -devsite -samplesdir development/samples/browseable ",
-}
-
-droiddoc {
- name: "ds-docs-kt",
- defaults: ["framework-dokka-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- args: "-noJdkLink -links https://kotlinlang.org/api/latest/jvm/stdlib/^external/dokka/package-list " +
- "-noStdlibLink",
- proofread_file: "ds-dokka-proofread.txt",
- dokka_enabled: true,
-}
-
-java_genrule {
- name: "ds-docs",
- tools: [
- "zip2zip",
- "merge_zips",
- ],
- srcs: [
- ":ds-docs-java{.docs.zip}",
- ":ds-docs-kt{.docs.zip}",
- ],
- out: ["ds-docs.zip"],
- dist: {
- targets: ["docs"],
- },
- cmd: "$(location zip2zip) -i $(location :ds-docs-kt{.docs.zip}) -o $(genDir)/ds-docs-kt-moved.zip **/*:en/reference/kotlin && " +
- "$(location merge_zips) $(out) $(location :ds-docs-java{.docs.zip}) $(genDir)/ds-docs-kt-moved.zip",
-}
-
-java_genrule {
- name: "ds-docs-switched",
- tools: [
- "switcher4",
- "soong_zip",
- ],
- srcs: [
- ":ds-docs-java{.docs.zip}",
- ":ds-docs-kt{.docs.zip}",
- ],
- out: ["ds-docs-switched.zip"],
- dist: {
- targets: ["docs"],
- },
- cmd: "unzip $(location :ds-docs-java{.docs.zip}) -d $(genDir) && " +
- "unzip $(location :ds-docs-kt{.docs.zip}) -d $(genDir)/en/reference/kotlin && " +
- "SWITCHER=$$(cd $$(dirname $(location switcher4)) && pwd)/$$(basename $(location switcher4)) && " +
- "(cd $(genDir)/en/reference && $$SWITCHER --work platform) && " +
- "$(location soong_zip) -o $(out) -C $(genDir) -D $(genDir)",
-}
-
-
-droiddoc {
- name: "ds-static-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc online",
- ],
- proofread_file: "ds-static-docs-proofrerad.txt",
- args: framework_docs_only_args +
- " -staticonly " +
- " -toroot / " +
- " -devsite " +
- " -ignoreJdLinks ",
-}
-
-droiddoc {
- name: "ds-ref-navtree-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc online",
- ],
- proofread_file: "ds-ref-navtree-docs-proofrerad.txt",
- args: framework_docs_only_args +
- " -toroot / " +
- " -atLinksNavtree " +
- " -navtreeonly ",
-}
-
-droiddoc {
- name: "online-sdk-dev-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- hdf: [
- "android.whichdoc online",
- "android.hasSamples true",
- ],
- proofread_file: "online-sdk-dev-docs-proofrerad.txt",
- args: framework_docs_only_args +
- " -toroot / -samplegroup Admin " +
- " -samplegroup Background " +
- " -samplegroup Connectivity " +
- " -samplegroup Content " +
- " -samplegroup Input " +
- " -samplegroup Media " +
- " -samplegroup Notification " +
- " -samplegroup RenderScript " +
- " -samplegroup Security " +
- " -samplegroup Sensors " +
- " -samplegroup System " +
- " -samplegroup Testing " +
- " -samplegroup UI " +
- " -samplegroup Views " +
- " -samplegroup Wearable -samplesdir development/samples/browseable ",
-}
-
-droiddoc {
- name: "hidden-docs",
- defaults: ["framework-docs-default"],
- srcs: [
- ":framework-doc-stubs",
- ],
- proofread_file: "hidden-docs-proofrerad.txt",
- args: framework_docs_only_args +
- " -referenceonly " +
- " -title \"Android SDK - Including hidden APIs.\"",
-}
-
-droidstubs {
- name: "hwbinder-stubs-docs",
- srcs: [
- "core/java/android/os/HidlSupport.java",
- "core/java/android/annotation/IntDef.java",
- "core/java/android/annotation/IntRange.java",
- "core/java/android/annotation/NonNull.java",
- "core/java/android/annotation/SystemApi.java",
- "core/java/android/os/HidlMemory.java",
- "core/java/android/os/HwBinder.java",
- "core/java/android/os/HwBlob.java",
- "core/java/android/os/HwParcel.java",
- "core/java/android/os/IHwBinder.java",
- "core/java/android/os/IHwInterface.java",
- "core/java/android/os/DeadObjectException.java",
- "core/java/android/os/DeadSystemException.java",
- "core/java/android/os/NativeHandle.java",
- "core/java/android/os/RemoteException.java",
- "core/java/android/util/AndroidException.java",
- ],
- installable: false,
- sdk_version: "core_platform",
- annotations_enabled: true,
- previous_api: ":last-released-public-api",
- merge_annotations_dirs: [
- "metalava-manual",
- ],
- args: " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\)",
-}
-
-java_library_static {
- name: "hwbinder.stubs",
- sdk_version: "core_current",
- srcs: [
- ":hwbinder-stubs-docs",
- ],
-}
-
-droidstubs {
- name: "hiddenapi-lists-docs",
- defaults: ["metalava-api-stubs-default"],
- arg_files: [
- "core/res/AndroidManifest.xml",
- ],
- dex_api_filename: "public-dex.txt",
- private_dex_api_filename: "private-dex.txt",
- removed_dex_api_filename: "removed-dex.txt",
- args: metalava_framework_docs_args +
- " --show-unannotated " +
- " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) " +
- " --show-annotation android.annotation.TestApi ",
-}
-
-droidstubs {
- name: "hiddenapi-mappings",
- defaults: ["metalava-api-stubs-default"],
- srcs: [
- ":opt-telephony-common-srcs",
- ],
-
- arg_files: [
- "core/res/AndroidManifest.xml",
- ],
- dex_mapping_filename: "dex-mapping.txt",
- args: metalava_framework_docs_args +
- " --hide ReferencesHidden " +
- " --hide UnhiddenSystemApi " +
- " --show-unannotated " +
- " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) " +
- " --show-annotation android.annotation.TestApi ",
-}
-
-droidstubs {
- name: "api-stubs-docs",
- defaults: ["metalava-api-stubs-default"],
- api_filename: "public_api.txt",
- private_api_filename: "private.txt",
- removed_api_filename: "removed.txt",
- arg_files: [
- "core/res/AndroidManifest.xml",
- ],
- args: metalava_framework_docs_args,
- check_api: {
- current: {
- api_file: "api/current.txt",
- removed_api_file: "api/removed.txt",
- },
- last_released: {
- api_file: ":last-released-public-api",
- removed_api_file: "api/removed.txt",
- baseline_file: ":public-api-incompatibilities-with-last-released",
- },
- api_lint: {
- enabled: true,
- new_since: ":last-released-public-api",
- baseline_file: "api/lint-baseline.txt",
- },
- },
- jdiff_enabled: true,
-}
-
-droidstubs {
- name: "system-api-stubs-docs",
- defaults: ["metalava-api-stubs-default"],
- api_tag_name: "SYSTEM",
- api_filename: "system-api.txt",
- private_api_filename: "system-private.txt",
- private_dex_api_filename: "system-private-dex.txt",
- removed_api_filename: "system-removed.txt",
- arg_files: [
- "core/res/AndroidManifest.xml",
- ],
- args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\)",
- check_api: {
- current: {
- api_file: "api/system-current.txt",
- removed_api_file: "api/system-removed.txt",
- },
- last_released: {
- api_file: ":last-released-system-api",
- removed_api_file: "api/system-removed.txt",
- baseline_file: ":system-api-incompatibilities-with-last-released"
- },
- api_lint: {
- enabled: true,
- new_since: ":last-released-system-api",
- baseline_file: "api/system-lint-baseline.txt",
- },
- },
- jdiff_enabled: true,
-}
-
-droidstubs {
- name: "test-api-stubs-docs",
- defaults: ["metalava-api-stubs-default"],
- api_tag_name: "TEST",
- api_filename: "test-api.txt",
- removed_api_filename: "test-removed.txt",
- arg_files: [
- "core/res/AndroidManifest.xml",
- ],
- args: metalava_framework_docs_args + " --show-annotation android.annotation.TestApi",
- check_api: {
- current: {
- api_file: "api/test-current.txt",
- removed_api_file: "api/test-removed.txt",
- },
- api_lint: {
- enabled: true,
- baseline_file: "api/test-lint-baseline.txt",
- },
- },
-}
-
filegroup {
name: "framework-annotation-nonnull-srcs",
srcs: [
@@ -1777,3 +1137,20 @@ filegroup {
"core/java/com/android/internal/util/XmlUtils.java",
],
}
+
+// TODO(b/145644363): move this to under StubLibraries.bp or ApiDocs.bp
+metalava_framework_docs_args = "--manifest $(location core/res/AndroidManifest.xml) " +
+ "--ignore-classes-on-classpath " +
+ "--hide-package com.android.server " +
+ "--error UnhiddenSystemApi " +
+ "--hide RequiresPermission " +
+ "--hide CallbackInterface " +
+ "--hide MissingPermission --hide BroadcastBehavior " +
+ "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
+ "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
+ "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.*"
+
+build = [
+ "StubLibraries.bp",
+ "ApiDocs.bp",
+]
diff --git a/ApiDocs.bp b/ApiDocs.bp
new file mode 100644
index 000000000000..e373db66925f
--- /dev/null
+++ b/ApiDocs.bp
@@ -0,0 +1,436 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// How API docs are generated:
+//
+// raw source files --(metalava)--> stub source files --(doclava)--> API doc
+//
+// The metalava conversion is done by droidstub modules framework-doc-*-stubs.
+// The API doc generation is done by the various droiddoc modules each of which
+// is for different format.
+
+/////////////////////////////////////////////////////////////////////
+// stub source files are generated using metalava
+/////////////////////////////////////////////////////////////////////
+
+framework_docs_only_libs = [
+ "voip-common",
+ "android.test.mock",
+ "android-support-annotations",
+ "android-support-compat",
+ "android-support-core-ui",
+ "android-support-core-utils",
+ "android-support-design",
+ "android-support-dynamic-animation",
+ "android-support-exifinterface",
+ "android-support-fragment",
+ "android-support-media-compat",
+ "android-support-percent",
+ "android-support-transition",
+ "android-support-v7-cardview",
+ "android-support-v7-gridlayout",
+ "android-support-v7-mediarouter",
+ "android-support-v7-palette",
+ "android-support-v7-preference",
+ "android-support-v13",
+ "android-support-v14-preference",
+ "android-support-v17-leanback",
+ "android-support-vectordrawable",
+ "android-support-animatedvectordrawable",
+ "android-support-v7-appcompat",
+ "android-support-v7-recyclerview",
+ "android-support-v8-renderscript",
+ "android-support-multidex",
+ "android-support-multidex-instrumentation",
+]
+
+stubs_defaults {
+ name: "framework-doc-stubs-default",
+ srcs: [
+ ":framework-mime-sources",
+ ":framework-non-updatable-sources",
+ ":framework-updatable-sources",
+ "core/java/**/*.logtags",
+ "test-base/src/**/*.java",
+ ":opt-telephony-srcs",
+ ":opt-net-voip-srcs",
+ ":core-current-stubs-source",
+ ":core_public_api_files",
+ "test-mock/src/**/*.java",
+ "test-runner/src/**/*.java",
+ ],
+ libs: framework_docs_only_libs,
+ create_doc_stubs: true,
+ annotations_enabled: true,
+ api_levels_annotations_enabled: true,
+ api_levels_annotations_dirs: [
+ "sdk-dir",
+ "api-versions-jars-dir",
+ ],
+ previous_api: ":last-released-public-api",
+ merge_annotations_dirs: [
+ "metalava-manual",
+ ],
+}
+
+droidstubs {
+ name: "framework-doc-stubs",
+ defaults: ["framework-doc-stubs-default"],
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ ],
+ args: metalava_framework_docs_args,
+ write_sdk_values: true,
+}
+
+droidstubs {
+ name: "framework-doc-system-stubs",
+ defaults: ["framework-doc-stubs-default"],
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ ],
+ args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) ",
+ write_sdk_values: true,
+}
+
+/////////////////////////////////////////////////////////////////////
+// API docs are created from the generated stub source files
+// using droiddoc
+/////////////////////////////////////////////////////////////////////
+
+framework_docs_only_args = " -android -manifest $(location core/res/AndroidManifest.xml) " +
+ "-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
+ "-overview $(location core/java/overview.html) " +
+ // Federate Support Library references against local API file.
+ "-federate SupportLib https://developer.android.com " +
+ "-federationapi SupportLib $(location :current-support-api) " +
+ // Federate Support Library references against local API file.
+ "-federate AndroidX https://developer.android.com " +
+ "-federationapi AndroidX $(location :current-androidx-api) "
+
+doc_defaults {
+ name: "framework-docs-default",
+ libs: framework_docs_only_libs +
+ ["stub-annotations"],
+ html_dirs: [
+ "docs/html",
+ ],
+ knowntags: [
+ "docs/knowntags.txt",
+ ":known-oj-tags",
+ ],
+ custom_template: "droiddoc-templates-sdk",
+ resourcesdir: "docs/html/reference/images/",
+ resourcesoutdir: "reference/android/images/",
+ hdf: [
+ "dac true",
+ "sdk.codename O",
+ "sdk.preview.version 1",
+ "sdk.version 7.0",
+ "sdk.rel.id 1",
+ "sdk.preview 0",
+ ],
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ "core/java/overview.html",
+ ":current-support-api",
+ ":current-androidx-api",
+ ],
+ create_stubs: false,
+}
+
+doc_defaults {
+ name: "framework-dokka-docs-default",
+ create_stubs: false,
+}
+
+droiddoc {
+ name: "doc-comment-check-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ args: framework_docs_only_args + " -referenceonly -parsecomments",
+ installable: false,
+}
+
+droiddoc {
+ name: "offline-sdk-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ hdf: [
+ "android.whichdoc offline",
+ ],
+ proofread_file: "offline-sdk-docs-proofrerad.txt",
+ args: framework_docs_only_args + " -offlinemode -title \"Android SDK\"",
+ static_doc_index_redirect: "docs/docs-preview-index.html",
+}
+
+droiddoc {
+ // Please sync with android-api-council@ before making any changes for the name property below.
+ // Since there's cron jobs that fetch offline-sdk-referenceonly-docs-docs.zip periodically.
+ // See b/116221385 for reference.
+ name: "offline-sdk-referenceonly-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ hdf: [
+ "android.whichdoc offline",
+ ],
+ proofread_file: "offline-sdk-referenceonly-docs-proofrerad.txt",
+ args: framework_docs_only_args + " -offlinemode -title \"Android SDK\" -referenceonly",
+ static_doc_index_redirect: "docs/docs-documentation-redirect.html",
+ static_doc_properties: "docs/source.properties",
+}
+
+droiddoc {
+ // Please sync with android-api-council@ before making any changes for the name property below.
+ // Since there's cron jobs that fetch offline-system-sdk-referenceonly-docs-docs.zip periodically.
+ // See b/116221385 for reference.
+ name: "offline-system-sdk-referenceonly-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-system-stubs",
+ ],
+ hdf: [
+ "android.whichdoc offline",
+ ],
+ proofread_file: "offline-system-sdk-referenceonly-docs-proofrerad.txt",
+ args: framework_docs_only_args + " -hide 101 -hide 104 -hide 108" +
+ " -offlinemode -title \"Android System SDK\" -referenceonly",
+ static_doc_index_redirect: "docs/docs-documentation-redirect.html",
+ static_doc_properties: "docs/source.properties",
+}
+
+droiddoc {
+ name: "online-sdk-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ hdf: [
+ "android.whichdoc online",
+ "android.hasSamples true",
+ ],
+ proofread_file: "online-sdk-docs-proofrerad.txt",
+ args: framework_docs_only_args +
+ " -toroot / -samplegroup Admin " +
+ " -samplegroup Background " +
+ " -samplegroup Connectivity " +
+ " -samplegroup Content " +
+ " -samplegroup Input " +
+ " -samplegroup Media " +
+ " -samplegroup Notification " +
+ " -samplegroup RenderScript " +
+ " -samplegroup Security " +
+ " -samplegroup Sensors " +
+ " -samplegroup System " +
+ " -samplegroup Testing " +
+ " -samplegroup UI " +
+ " -samplegroup Views " +
+ " -samplegroup Wearable -samplesdir development/samples/browseable ",
+}
+
+droiddoc {
+ name: "online-system-api-sdk-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-system-stubs",
+ ],
+ hdf: [
+ "android.whichdoc online",
+ "android.hasSamples true",
+ ],
+ proofread_file: "online-system-api-sdk-docs-proofrerad.txt",
+ args: framework_docs_only_args +
+ " -referenceonly " +
+ " -title \"Android SDK - Including system APIs.\" " +
+ " -hide 101 " +
+ " -hide 104 " +
+ " -hide 108 " +
+ " -toroot / -samplegroup Admin " +
+ " -samplegroup Background " +
+ " -samplegroup Connectivity " +
+ " -samplegroup Content " +
+ " -samplegroup Input " +
+ " -samplegroup Media " +
+ " -samplegroup Notification " +
+ " -samplegroup RenderScript " +
+ " -samplegroup Security " +
+ " -samplegroup Sensors " +
+ " -samplegroup System " +
+ " -samplegroup Testing " +
+ " -samplegroup UI " +
+ " -samplegroup Views " +
+ " -samplegroup Wearable -samplesdir development/samples/browseable ",
+ installable: false,
+}
+
+droiddoc {
+ name: "ds-docs-java",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ hdf: [
+ "android.whichdoc online",
+ "android.hasSamples true",
+ ],
+ proofread_file: "ds-docs-proofrerad.txt",
+ args: framework_docs_only_args +
+ " -toroot / -yamlV2 -metalavaApiSince -samplegroup Admin " +
+ " -samplegroup Background " +
+ " -samplegroup Connectivity " +
+ " -samplegroup Content " +
+ " -samplegroup Input " +
+ " -samplegroup Media " +
+ " -samplegroup Notification " +
+ " -samplegroup RenderScript " +
+ " -samplegroup Security " +
+ " -samplegroup Sensors " +
+ " -samplegroup System " +
+ " -samplegroup Testing " +
+ " -samplegroup UI " +
+ " -samplegroup Views " +
+ " -samplegroup Wearable -devsite -samplesdir development/samples/browseable ",
+}
+
+droiddoc {
+ name: "ds-docs-kt",
+ defaults: ["framework-dokka-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ args: "-noJdkLink -links https://kotlinlang.org/api/latest/jvm/stdlib/^external/dokka/package-list " +
+ "-noStdlibLink",
+ proofread_file: "ds-dokka-proofread.txt",
+ dokka_enabled: true,
+}
+
+java_genrule {
+ name: "ds-docs",
+ tools: [
+ "zip2zip",
+ "merge_zips",
+ ],
+ srcs: [
+ ":ds-docs-java{.docs.zip}",
+ ":ds-docs-kt{.docs.zip}",
+ ],
+ out: ["ds-docs.zip"],
+ dist: {
+ targets: ["docs"],
+ },
+ cmd: "$(location zip2zip) -i $(location :ds-docs-kt{.docs.zip}) -o $(genDir)/ds-docs-kt-moved.zip **/*:en/reference/kotlin && " +
+ "$(location merge_zips) $(out) $(location :ds-docs-java{.docs.zip}) $(genDir)/ds-docs-kt-moved.zip",
+}
+
+java_genrule {
+ name: "ds-docs-switched",
+ tools: [
+ "switcher4",
+ "soong_zip",
+ ],
+ srcs: [
+ ":ds-docs-java{.docs.zip}",
+ ":ds-docs-kt{.docs.zip}",
+ ],
+ out: ["ds-docs-switched.zip"],
+ dist: {
+ targets: ["docs"],
+ },
+ cmd: "unzip $(location :ds-docs-java{.docs.zip}) -d $(genDir) && " +
+ "unzip $(location :ds-docs-kt{.docs.zip}) -d $(genDir)/en/reference/kotlin && " +
+ "SWITCHER=$$(cd $$(dirname $(location switcher4)) && pwd)/$$(basename $(location switcher4)) && " +
+ "(cd $(genDir)/en/reference && $$SWITCHER --work platform) && " +
+ "$(location soong_zip) -o $(out) -C $(genDir) -D $(genDir)",
+}
+
+droiddoc {
+ name: "ds-static-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ hdf: [
+ "android.whichdoc online",
+ ],
+ proofread_file: "ds-static-docs-proofrerad.txt",
+ args: framework_docs_only_args +
+ " -staticonly " +
+ " -toroot / " +
+ " -devsite " +
+ " -ignoreJdLinks ",
+}
+
+droiddoc {
+ name: "ds-ref-navtree-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ hdf: [
+ "android.whichdoc online",
+ ],
+ proofread_file: "ds-ref-navtree-docs-proofrerad.txt",
+ args: framework_docs_only_args +
+ " -toroot / " +
+ " -atLinksNavtree " +
+ " -navtreeonly ",
+}
+
+droiddoc {
+ name: "online-sdk-dev-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ hdf: [
+ "android.whichdoc online",
+ "android.hasSamples true",
+ ],
+ proofread_file: "online-sdk-dev-docs-proofrerad.txt",
+ args: framework_docs_only_args +
+ " -toroot / -samplegroup Admin " +
+ " -samplegroup Background " +
+ " -samplegroup Connectivity " +
+ " -samplegroup Content " +
+ " -samplegroup Input " +
+ " -samplegroup Media " +
+ " -samplegroup Notification " +
+ " -samplegroup RenderScript " +
+ " -samplegroup Security " +
+ " -samplegroup Sensors " +
+ " -samplegroup System " +
+ " -samplegroup Testing " +
+ " -samplegroup UI " +
+ " -samplegroup Views " +
+ " -samplegroup Wearable -samplesdir development/samples/browseable ",
+}
+
+droiddoc {
+ name: "hidden-docs",
+ defaults: ["framework-docs-default"],
+ srcs: [
+ ":framework-doc-stubs",
+ ],
+ proofread_file: "hidden-docs-proofrerad.txt",
+ args: framework_docs_only_args +
+ " -referenceonly " +
+ " -title \"Android SDK - Including hidden APIs.\"",
+}
+
diff --git a/StubLibraries.bp b/StubLibraries.bp
new file mode 100644
index 000000000000..78f1b9ca26e5
--- /dev/null
+++ b/StubLibraries.bp
@@ -0,0 +1,340 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// How stubs are generated:
+//
+// raw source files --(metalava)--> stub source files --(javac)--> stub jar files
+//
+// The metalava conversion is done by droidstub modules *-api-stubs-docs.
+// The javac compilation is done by java_library modules android_*_stubs_current.
+// The metalava conversion is also responsible for creating API signature files
+// and comparing them against the last API signature in api/*-current.txt files
+// and also against the latest frozen API signature in prebuilts/sdk/*/*/api/android.txt
+// files.
+
+/////////////////////////////////////////////////////////////////////
+// Common metalava configs
+/////////////////////////////////////////////////////////////////////
+
+packages_to_document = [
+ "android",
+ "dalvik",
+ "java",
+ "javax",
+ "junit",
+ "org.apache.http",
+ "org.json",
+ "org.w3c.dom",
+ "org.xml.sax",
+ "org.xmlpull",
+]
+
+stubs_defaults {
+ name: "metalava-api-stubs-default",
+ srcs: [
+ ":framework-non-updatable-sources",
+ ":framework-updatable-sources",
+ "core/java/**/*.logtags",
+ ":opt-telephony-srcs",
+ ":opt-net-voip-srcs",
+ ":core-current-stubs-source",
+ ":core_public_api_files",
+ ":ike-api-srcs",
+ ],
+ libs: ["framework-internal-utils"],
+ installable: false,
+ annotations_enabled: true,
+ previous_api: ":last-released-public-api",
+ merge_annotations_dirs: [
+ "metalava-manual",
+ ],
+ api_levels_annotations_enabled: true,
+ api_levels_annotations_dirs: [
+ "sdk-dir",
+ "api-versions-jars-dir",
+ ],
+ sdk_version: "core_platform",
+ filter_packages: packages_to_document,
+}
+
+/////////////////////////////////////////////////////////////////////
+// *-api-stubs-docs modules providing source files for the stub libraries
+/////////////////////////////////////////////////////////////////////
+
+droidstubs {
+ name: "api-stubs-docs",
+ defaults: ["metalava-api-stubs-default"],
+ api_filename: "public_api.txt",
+ private_api_filename: "private.txt",
+ removed_api_filename: "removed.txt",
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ ],
+ args: metalava_framework_docs_args,
+ check_api: {
+ current: {
+ api_file: "api/current.txt",
+ removed_api_file: "api/removed.txt",
+ },
+ last_released: {
+ api_file: ":last-released-public-api",
+ removed_api_file: "api/removed.txt",
+ baseline_file: ":public-api-incompatibilities-with-last-released",
+ },
+ api_lint: {
+ enabled: true,
+ new_since: ":last-released-public-api",
+ baseline_file: "api/lint-baseline.txt",
+ },
+ },
+ jdiff_enabled: true,
+}
+
+droidstubs {
+ name: "system-api-stubs-docs",
+ defaults: ["metalava-api-stubs-default"],
+ api_tag_name: "SYSTEM",
+ api_filename: "system-api.txt",
+ private_api_filename: "system-private.txt",
+ private_dex_api_filename: "system-private-dex.txt",
+ removed_api_filename: "system-removed.txt",
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ ],
+ args: metalava_framework_docs_args + " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\)",
+ check_api: {
+ current: {
+ api_file: "api/system-current.txt",
+ removed_api_file: "api/system-removed.txt",
+ },
+ last_released: {
+ api_file: ":last-released-system-api",
+ removed_api_file: "api/system-removed.txt",
+ baseline_file: ":system-api-incompatibilities-with-last-released"
+ },
+ api_lint: {
+ enabled: true,
+ new_since: ":last-released-system-api",
+ baseline_file: "api/system-lint-baseline.txt",
+ },
+ },
+ jdiff_enabled: true,
+}
+
+droidstubs {
+ name: "test-api-stubs-docs",
+ defaults: ["metalava-api-stubs-default"],
+ api_tag_name: "TEST",
+ api_filename: "test-api.txt",
+ removed_api_filename: "test-removed.txt",
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ ],
+ args: metalava_framework_docs_args + " --show-annotation android.annotation.TestApi",
+ check_api: {
+ current: {
+ api_file: "api/test-current.txt",
+ removed_api_file: "api/test-removed.txt",
+ },
+ api_lint: {
+ enabled: true,
+ baseline_file: "api/test-lint-baseline.txt",
+ },
+ },
+}
+
+/////////////////////////////////////////////////////////////////////
+// android_*_stubs_current modules are the stubs libraries compiled
+// from *-api-stubs-docs
+/////////////////////////////////////////////////////////////////////
+
+java_defaults {
+ name: "framework-stubs-default",
+ errorprone: {
+ javacflags: [
+ "-XepDisableAllChecks",
+ ],
+ },
+ java_resources: [
+ ":notices-for-framework-stubs",
+ ],
+ sdk_version: "core_current",
+ system_modules: "none",
+ java_version: "1.8",
+ compile_dex: true,
+}
+
+java_library_static {
+ name: "android_stubs_current",
+ srcs: [
+ ":api-stubs-docs",
+ ],
+ libs: [
+ "stub-annotations",
+ ],
+ static_libs: [
+ "private-stub-annotations-jar",
+ ],
+ defaults: ["framework-stubs-default"],
+}
+
+java_library_static {
+ name: "android_system_stubs_current",
+ srcs: [
+ ":system-api-stubs-docs",
+ ],
+ libs: [
+ "stub-annotations",
+ ],
+ static_libs: [
+ "private-stub-annotations-jar",
+ ],
+ defaults: ["framework-stubs-default"],
+}
+
+java_library_static {
+ name: "android_test_stubs_current",
+ srcs: [
+ ":test-api-stubs-docs",
+ ],
+ libs: [
+ "stub-annotations",
+ ],
+ static_libs: [
+ "private-stub-annotations-jar",
+ ],
+ defaults: ["framework-stubs-default"],
+}
+
+java_system_modules {
+ name: "android_stubs_current_system_modules",
+ libs: ["android_stubs_current"],
+}
+
+java_system_modules {
+ name: "android_system_stubs_current_system_modules",
+ libs: ["android_system_stubs_current"],
+}
+
+java_system_modules {
+ name: "android_test_stubs_current_system_modules",
+ libs: ["android_test_stubs_current"],
+}
+
+/////////////////////////////////////////////////////////////////////
+// hwbinder.stubs provides APIs required for building HIDL Java
+// libraries.
+/////////////////////////////////////////////////////////////////////
+
+droidstubs {
+ name: "hwbinder-stubs-docs",
+ srcs: [
+ "core/java/android/os/HidlSupport.java",
+ "core/java/android/annotation/IntDef.java",
+ "core/java/android/annotation/IntRange.java",
+ "core/java/android/annotation/NonNull.java",
+ "core/java/android/annotation/SystemApi.java",
+ "core/java/android/os/HidlMemory.java",
+ "core/java/android/os/HwBinder.java",
+ "core/java/android/os/HwBlob.java",
+ "core/java/android/os/HwParcel.java",
+ "core/java/android/os/IHwBinder.java",
+ "core/java/android/os/IHwInterface.java",
+ "core/java/android/os/DeadObjectException.java",
+ "core/java/android/os/DeadSystemException.java",
+ "core/java/android/os/NativeHandle.java",
+ "core/java/android/os/RemoteException.java",
+ "core/java/android/util/AndroidException.java",
+ ],
+ installable: false,
+ sdk_version: "core_platform",
+ annotations_enabled: true,
+ previous_api: ":last-released-public-api",
+ merge_annotations_dirs: [
+ "metalava-manual",
+ ],
+ args: " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\)",
+}
+
+java_library_static {
+ name: "hwbinder.stubs",
+ sdk_version: "core_current",
+ srcs: [
+ ":hwbinder-stubs-docs",
+ ],
+}
+
+/////////////////////////////////////////////////////////////////////
+// Stubs for hiddenapi processing.
+/////////////////////////////////////////////////////////////////////
+
+droidstubs {
+ name: "hiddenapi-lists-docs",
+ defaults: ["metalava-api-stubs-default"],
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ ],
+ dex_api_filename: "public-dex.txt",
+ private_dex_api_filename: "private-dex.txt",
+ removed_dex_api_filename: "removed-dex.txt",
+ args: metalava_framework_docs_args +
+ " --show-unannotated " +
+ " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) " +
+ " --show-annotation android.annotation.TestApi ",
+}
+
+droidstubs {
+ name: "hiddenapi-mappings",
+ defaults: ["metalava-api-stubs-default"],
+ srcs: [
+ ":opt-telephony-common-srcs",
+ ],
+
+ arg_files: [
+ "core/res/AndroidManifest.xml",
+ ],
+ dex_mapping_filename: "dex-mapping.txt",
+ args: metalava_framework_docs_args +
+ " --hide ReferencesHidden " +
+ " --hide UnhiddenSystemApi " +
+ " --show-unannotated " +
+ " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.PRIVILEGED_APPS,process=android.annotation.SystemApi.Process.ALL\\) " +
+ " --show-annotation android.annotation.TestApi ",
+}
+
+/////////////////////////////////////////////////////////////////////
+// api/*-current.txt files for use by modules in other directories
+// like the CTS test
+/////////////////////////////////////////////////////////////////////
+
+filegroup {
+ name: "frameworks-base-api-current.txt",
+ srcs: [
+ "api/current.txt",
+ ],
+}
+
+filegroup {
+ name: "frameworks-base-api-system-current.txt",
+ srcs: [
+ "api/system-current.txt",
+ ],
+}
+
+filegroup {
+ name: "frameworks-base-api-system-removed.txt",
+ srcs: [
+ "api/system-removed.txt",
+ ],
+}
diff --git a/apex/sdkext/derive_sdk/derive_sdk.cpp b/apex/sdkext/derive_sdk/derive_sdk.cpp
index 7536def60767..0a9711677015 100644
--- a/apex/sdkext/derive_sdk/derive_sdk.cpp
+++ b/apex/sdkext/derive_sdk/derive_sdk.cpp
@@ -63,6 +63,7 @@ int main(int, char**) {
LOG(ERROR) << "failed to parse " << path;
continue;
}
+ LOG(INFO) << "Read version " << sdk_version.version() << " from " << path;
versions.push_back(sdk_version.version());
}
auto itr = std::min_element(versions.begin(), versions.end());
@@ -73,5 +74,6 @@ int main(int, char**) {
return EXIT_FAILURE;
}
+ LOG(INFO) << "R extension version is " << prop_value;
return EXIT_SUCCESS;
}
diff --git a/apex/statsd/aidl/android/os/IPullAtomCallback.aidl b/apex/statsd/aidl/android/os/IPullAtomCallback.aidl
index 88d3c3e46ff5..ff0b97bb5b84 100644
--- a/apex/statsd/aidl/android/os/IPullAtomCallback.aidl
+++ b/apex/statsd/aidl/android/os/IPullAtomCallback.aidl
@@ -26,6 +26,6 @@ interface IPullAtomCallback {
/**
* Initiate a request for a pull for an atom.
*/
- void onPullAtom(int atomTag, IPullAtomResultReceiver resultReceiver);
+ oneway void onPullAtom(int atomTag, IPullAtomResultReceiver resultReceiver);
}
diff --git a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
index 22a25374e064..5a6118ef81ca 100644
--- a/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
+++ b/apex/statsd/aidl/android/os/IStatsCompanionService.aidl
@@ -90,4 +90,7 @@ interface IStatsCompanionService {
/** Tells StatsCompanionService to tell statsd to register a puller for the given atom id */
oneway void registerPullAtomCallback(int atomTag, long coolDownNs, long timeoutNs,
in int[] additiveFields, IPullAtomCallback pullerCallback);
+
+ /** Tells StatsCompanionService to tell statsd to unregister a puller for the given atom id */
+ oneway void unregisterPullAtomCallback(int atomTag);
}
diff --git a/apex/statsd/aidl/android/os/IStatsd.aidl b/apex/statsd/aidl/android/os/IStatsd.aidl
index cffc6ce6e4df..cce79fae7587 100644
--- a/apex/statsd/aidl/android/os/IStatsd.aidl
+++ b/apex/statsd/aidl/android/os/IStatsd.aidl
@@ -215,6 +215,11 @@ interface IStatsd {
*/
oneway void unregisterPullerCallback(int atomTag, String packageName);
+ /**
+ * Unregisters any pullAtomCallback for the given uid/atom.
+ */
+ oneway void unregisterPullAtomCallback(int uid, int atomTag);
+
/**
* The install requires staging.
*/
diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp
index 37b07a6380aa..a2b0577fe001 100644
--- a/apex/statsd/framework/Android.bp
+++ b/apex/statsd/framework/Android.bp
@@ -24,7 +24,7 @@ java_library {
name: "framework-statsd",
installable: true,
// TODO(b/146209659): Use system_current instead.
- sdk_version: "core_platform",
+ sdk_version: "core_current",
srcs: [
":framework-statsd-sources",
],
diff --git a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
index c5fd3f2025e7..7ed51caf23dd 100644
--- a/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
+++ b/apex/statsd/service/java/com/android/server/stats/StatsCompanionService.java
@@ -2752,6 +2752,30 @@ public class StatsCompanionService extends IStatsCompanionService.Stub {
}
}
+ @Override
+ public void unregisterPullAtomCallback(int atomTag) {
+ synchronized (sStatsdLock) {
+ // Always remove the puller in SCS.
+ // If statsd is down, we will not register it when it comes back up.
+ int callingUid = Binder.getCallingUid();
+ final long token = Binder.clearCallingIdentity();
+ PullerKey key = new PullerKey(callingUid, atomTag);
+ mPullers.remove(key);
+
+ if (sStatsd == null) {
+ Slog.w(TAG, "Could not access statsd for registering puller for atom " + atomTag);
+ return;
+ }
+ try {
+ sStatsd.unregisterPullAtomCallback(callingUid, atomTag);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to access statsd to register puller for atom " + atomTag);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ }
+
// Statsd related code
/**
diff --git a/api/current.txt b/api/current.txt
index 86aa80b159bd..4d5d1a1c02d3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3955,6 +3955,7 @@ package android.app {
public class ActivityManager {
method public int addAppTask(@NonNull android.app.Activity, @NonNull android.content.Intent, @Nullable android.app.ActivityManager.TaskDescription, @NonNull android.graphics.Bitmap);
+ method public void appNotResponding(@NonNull String);
method public boolean clearApplicationUserData();
method public void clearWatchHeapLimit();
method @RequiresPermission(android.Manifest.permission.DUMP) public void dumpPackageState(java.io.FileDescriptor, String);
@@ -9972,6 +9973,7 @@ package android.content {
field public static final String DOWNLOAD_SERVICE = "download";
field public static final String DROPBOX_SERVICE = "dropbox";
field public static final String EUICC_SERVICE = "euicc";
+ field public static final String FILE_INTEGRITY_SERVICE = "file_integrity";
field public static final String FINGERPRINT_SERVICE = "fingerprint";
field public static final String HARDWARE_PROPERTIES_SERVICE = "hardware_properties";
field public static final String INPUT_METHOD_SERVICE = "input_method";
@@ -23742,6 +23744,7 @@ package android.media {
field public static final int ENCODING_IEC61937 = 13; // 0xd
field public static final int ENCODING_INVALID = 0; // 0x0
field public static final int ENCODING_MP3 = 9; // 0x9
+ field public static final int ENCODING_OPUS = 20; // 0x14
field public static final int ENCODING_PCM_16BIT = 2; // 0x2
field public static final int ENCODING_PCM_8BIT = 3; // 0x3
field public static final int ENCODING_PCM_FLOAT = 4; // 0x4
@@ -41387,6 +41390,11 @@ package android.security {
method public android.security.ConfirmationPrompt.Builder setPromptText(CharSequence);
}
+ public final class FileIntegrityManager {
+ method public boolean isApkVeritySupported();
+ method @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public boolean isAppSourceCertificateTrusted(@NonNull java.security.cert.X509Certificate) throws java.security.cert.CertificateEncodingException;
+ }
+
public final class KeyChain {
ctor public KeyChain();
method public static void choosePrivateKeyAlias(@NonNull android.app.Activity, @NonNull android.security.KeyChainAliasCallback, @Nullable String[], @Nullable java.security.Principal[], @Nullable String, int, @Nullable String);
@@ -45487,6 +45495,7 @@ package android.telephony {
ctor public PhoneStateListener();
ctor public PhoneStateListener(@NonNull java.util.concurrent.Executor);
method public void onActiveDataSubscriptionIdChanged(int);
+ method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onCallDisconnectCauseChanged(int, int);
method public void onCallForwardingIndicatorChanged(boolean);
method public void onCallStateChanged(int, String);
method public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
@@ -45494,6 +45503,7 @@ package android.telephony {
method public void onDataActivity(int);
method public void onDataConnectionStateChanged(int);
method public void onDataConnectionStateChanged(int, int);
+ method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
method public void onMessageWaitingIndicatorChanged(boolean);
method @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState);
method public void onServiceStateChanged(android.telephony.ServiceState);
@@ -45501,6 +45511,7 @@ package android.telephony {
method public void onSignalStrengthsChanged(android.telephony.SignalStrength);
method public void onUserMobileDataStateChanged(boolean);
field public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 4194304; // 0x400000
+ field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
field public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8
field public static final int LISTEN_CALL_STATE = 32; // 0x20
field public static final int LISTEN_CELL_INFO = 1024; // 0x400
@@ -45508,6 +45519,7 @@ package android.telephony {
field public static final int LISTEN_DATA_ACTIVITY = 128; // 0x80
field public static final int LISTEN_DATA_CONNECTION_STATE = 64; // 0x40
field public static final int LISTEN_EMERGENCY_NUMBER_LIST = 16777216; // 0x1000000
+ field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
field public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 4; // 0x4
field public static final int LISTEN_NONE = 0; // 0x0
field @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
@@ -51681,6 +51693,7 @@ package android.view {
method public boolean isScrollContainer();
method public boolean isScrollbarFadingEnabled();
method @android.view.ViewDebug.ExportedProperty public boolean isSelected();
+ method public final boolean isShowingLayoutBounds();
method public boolean isShown();
method @android.view.ViewDebug.ExportedProperty public boolean isSoundEffectsEnabled();
method public final boolean isTemporarilyDetached();
@@ -55256,6 +55269,7 @@ package android.view.textclassifier {
method public int describeContents();
method @NonNull public android.os.Bundle getExtras();
method @NonNull public java.util.Collection<android.view.textclassifier.TextLinks.TextLink> getLinks();
+ method @NonNull public String getText();
method public void writeToParcel(android.os.Parcel, int);
field public static final int APPLY_STRATEGY_IGNORE = 0; // 0x0
field public static final int APPLY_STRATEGY_REPLACE = 1; // 0x1
@@ -55282,6 +55296,7 @@ package android.view.textclassifier {
method @Nullable public android.os.LocaleList getDefaultLocales();
method @Nullable public android.view.textclassifier.TextClassifier.EntityConfig getEntityConfig();
method @NonNull public android.os.Bundle getExtras();
+ method @Nullable public java.time.ZonedDateTime getReferenceTime();
method @NonNull public CharSequence getText();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.view.textclassifier.TextLinks.Request> CREATOR;
@@ -55293,6 +55308,7 @@ package android.view.textclassifier {
method @NonNull public android.view.textclassifier.TextLinks.Request.Builder setDefaultLocales(@Nullable android.os.LocaleList);
method @NonNull public android.view.textclassifier.TextLinks.Request.Builder setEntityConfig(@Nullable android.view.textclassifier.TextClassifier.EntityConfig);
method public android.view.textclassifier.TextLinks.Request.Builder setExtras(@Nullable android.os.Bundle);
+ method @NonNull public android.view.textclassifier.TextLinks.Request.Builder setReferenceTime(@Nullable java.time.ZonedDateTime);
}
public static final class TextLinks.TextLink implements android.os.Parcelable {
diff --git a/api/removed.txt b/api/removed.txt
index 8b30d0a5cf39..fb6d57694c78 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -435,15 +435,6 @@ package android.provider {
field @Deprecated public static final String TIMESTAMP = "timestamp";
}
- public final class MediaStore {
- method @Deprecated @NonNull public static java.util.Set<java.lang.String> getAllVolumeNames(@NonNull android.content.Context);
- method @Deprecated public static boolean getIncludePending(@NonNull android.net.Uri);
- method @Deprecated @NonNull public static android.net.Uri setIncludeTrashed(@NonNull android.net.Uri);
- method @Deprecated public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri);
- method @Deprecated public static void trash(@NonNull android.content.Context, @NonNull android.net.Uri, long);
- method @Deprecated public static void untrash(@NonNull android.content.Context, @NonNull android.net.Uri);
- }
-
public static interface MediaStore.Audio.AudioColumns extends android.provider.MediaStore.MediaColumns {
field public static final String ALBUM = "album";
field public static final String ARTIST = "artist";
diff --git a/api/system-current.txt b/api/system-current.txt
index 2d0213fa3c0f..f2433dec4ef9 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -260,7 +260,6 @@ package android {
public static final class R.drawable {
field public static final int ic_info = 17301684; // 0x10800b4
- field public static final int stat_notify_wifi_in_range = 17301685; // 0x10800b5
}
public static final class R.raw {
@@ -281,9 +280,6 @@ package android {
field public static final int config_helpIntentNameKey = 17039390; // 0x104001e
field public static final int config_helpPackageNameKey = 17039387; // 0x104001b
field public static final int config_helpPackageNameValue = 17039388; // 0x104001c
- field public static final int notification_channel_network_alerts = 17039398; // 0x1040026
- field public static final int notification_channel_network_available = 17039399; // 0x1040027
- field public static final int notification_channel_network_status = 17039397; // 0x1040025
}
public static final class R.style {
@@ -1934,10 +1930,12 @@ package android.content.pm {
}
public class DataLoaderParams {
- ctor public DataLoaderParams(@NonNull String, @NonNull String, @Nullable java.util.Map<java.lang.String,android.os.ParcelFileDescriptor>);
+ method @NonNull public static final android.content.pm.DataLoaderParams forIncremental(@NonNull android.content.ComponentName, @NonNull String, @Nullable java.util.Map<java.lang.String,android.os.ParcelFileDescriptor>);
+ method @NonNull public static final android.content.pm.DataLoaderParams forStreaming(@NonNull android.content.ComponentName, @NonNull String);
+ method @NonNull public final String getArguments();
+ method @NonNull public final android.content.ComponentName getComponentName();
method @NonNull public final java.util.Map<java.lang.String,android.os.ParcelFileDescriptor> getDynamicArgs();
- method @NonNull public final String getPackageName();
- method @NonNull public final String getStaticArgs();
+ method @NonNull public final int getType();
}
public final class InstantAppInfo implements android.os.Parcelable {
@@ -2050,11 +2048,11 @@ package android.content.pm {
public static class PackageInstaller.SessionParams implements android.os.Parcelable {
method @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE) public void setAllocateAggressive(boolean);
method @Deprecated public void setAllowDowngrade(boolean);
+ method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setDataLoaderParams(@NonNull android.content.pm.DataLoaderParams);
method public void setDontKillApp(boolean);
method public void setEnableRollback(boolean);
method public void setEnableRollback(boolean, int);
method @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) public void setGrantedRuntimePermissions(String[]);
- method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setIncrementalParams(@NonNull android.content.pm.DataLoaderParams);
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setInstallAsApex();
method public void setInstallAsInstantApp(boolean);
method public void setInstallAsVirtualPreload();
@@ -4068,6 +4066,7 @@ package android.media {
method public android.media.PlayerProxy getPlayerProxy();
method public int getPlayerState();
method public int getPlayerType();
+ method public boolean isActive();
field public static final int PLAYER_STATE_IDLE = 1; // 0x1
field public static final int PLAYER_STATE_PAUSED = 3; // 0x3
field public static final int PLAYER_STATE_RELEASED = 0; // 0x0
@@ -5392,11 +5391,15 @@ package android.net.wifi {
ctor public EasyConnectStatusCallback();
method public abstract void onConfiguratorSuccess(int);
method public abstract void onEnrolleeSuccess(int);
- method public abstract void onFailure(int);
+ method public void onFailure(int);
+ method public void onFailure(int, @Nullable String, @NonNull android.util.SparseArray<int[]>, @NonNull int[]);
method public abstract void onProgress(int);
field public static final int EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION = -2; // 0xfffffffe
field public static final int EASY_CONNECT_EVENT_FAILURE_BUSY = -5; // 0xfffffffb
+ field public static final int EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK = -10; // 0xfffffff6
field public static final int EASY_CONNECT_EVENT_FAILURE_CONFIGURATION = -4; // 0xfffffffc
+ field public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION = -11; // 0xfffffff5
+ field public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION = -12; // 0xfffffff4
field public static final int EASY_CONNECT_EVENT_FAILURE_GENERIC = -7; // 0xfffffff9
field public static final int EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK = -9; // 0xfffffff7
field public static final int EASY_CONNECT_EVENT_FAILURE_INVALID_URI = -1; // 0xffffffff
@@ -5404,7 +5407,10 @@ package android.net.wifi {
field public static final int EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED = -8; // 0xfffffff8
field public static final int EASY_CONNECT_EVENT_FAILURE_TIMEOUT = -6; // 0xfffffffa
field public static final int EASY_CONNECT_EVENT_PROGRESS_AUTHENTICATION_SUCCESS = 0; // 0x0
+ field public static final int EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_ACCEPTED = 3; // 0x3
+ field public static final int EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_SENT_WAITING_RESPONSE = 2; // 0x2
field public static final int EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING = 1; // 0x1
+ field public static final int EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED = 1; // 0x1
field public static final int EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT = 0; // 0x0
}
@@ -8897,6 +8903,7 @@ package android.telephony {
}
public class CarrierConfigManager {
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultCarrierServicePackageName();
method @NonNull public static android.os.PersistableBundle getDefaultConfig();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void overrideConfig(int, @Nullable android.os.PersistableBundle);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void updateConfigForPhoneId(int, String);
@@ -8971,6 +8978,34 @@ package android.telephony {
field public static final String CELL_BROADCAST_SERVICE_INTERFACE = "android.telephony.CellBroadcastService";
}
+ public abstract class CellIdentity implements android.os.Parcelable {
+ method @NonNull public abstract android.telephony.CellLocation asCellLocation();
+ }
+
+ public final class CellIdentityCdma extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.cdma.CdmaCellLocation asCellLocation();
+ }
+
+ public final class CellIdentityGsm extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ }
+
+ public final class CellIdentityLte extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ }
+
+ public final class CellIdentityNr extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.CellLocation asCellLocation();
+ }
+
+ public final class CellIdentityTdscdma extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ }
+
+ public final class CellIdentityWcdma extends android.telephony.CellIdentity {
+ method @NonNull public android.telephony.gsm.GsmCellLocation asCellLocation();
+ }
+
public final class DataFailCause {
field public static final int ACCESS_ATTEMPT_ALREADY_IN_PROGRESS = 2219; // 0x8ab
field public static final int ACCESS_BLOCK = 2087; // 0x827
@@ -9550,8 +9585,6 @@ package android.telephony {
public class PhoneStateListener {
method public void onCallAttributesChanged(@NonNull android.telephony.CallAttributes);
- method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onCallDisconnectCauseChanged(int, int);
- method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber);
method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber);
method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState);
@@ -9559,8 +9592,6 @@ package android.telephony {
method public void onSrvccStateChanged(int);
method public void onVoiceActivationStateChanged(int);
field public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
- field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
- field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
@@ -9570,6 +9601,7 @@ package android.telephony {
}
public final class PreciseCallState implements android.os.Parcelable {
+ ctor public PreciseCallState(int, int, int, int, int);
method public int describeContents();
method public int getBackgroundCallState();
method public int getForegroundCallState();
@@ -9941,6 +9973,7 @@ package android.telephony {
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
method public int getMaxNumberOfSimultaneouslyActiveSims();
method public static long getMaxNumberVerificationTimeoutMillis();
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String[] getMergedImsisFromGroup();
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getNetworkCountryIso(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask();
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
diff --git a/api/test-current.txt b/api/test-current.txt
index 503941c86939..08a21609d476 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -4359,6 +4359,7 @@ package android.view {
method public void setAutofilled(boolean);
method public final void setFocusedInCluster();
method public void setIsRootNamespace(boolean);
+ method public final void setShowingLayoutBounds(boolean);
}
public class ViewConfiguration {
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index afff61497157..887d17cb7e4b 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -409,7 +409,7 @@ cc_benchmark {
// ==== java proto device library (for test only) ==============================
java_library {
name: "statsdprotolite",
- sdk_version: "core_platform",
+ sdk_version: "core_current",
proto: {
type: "lite",
include_dirs: ["external/protobuf/src"],
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 4d38ba03b1df..bb3a094af34a 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1320,6 +1320,13 @@ Status StatsService::unregisterPullerCallback(int32_t atomTag, const String16& p
return Status::ok();
}
+Status StatsService::unregisterPullAtomCallback(int32_t uid, int32_t atomTag) {
+ ENFORCE_UID(AID_SYSTEM);
+ VLOG("StatsService::unregisterPullAtomCallback called.");
+ mPullerManager->UnregisterPullAtomCallback(uid, atomTag);
+ return Status::ok();
+}
+
Status StatsService::sendBinaryPushStateChangedAtom(const android::String16& trainNameIn,
const int64_t trainVersionCodeIn,
const int options,
diff --git a/cmds/statsd/src/StatsService.h b/cmds/statsd/src/StatsService.h
index 9abf415ad91f..de55ca9c38cd 100644
--- a/cmds/statsd/src/StatsService.h
+++ b/cmds/statsd/src/StatsService.h
@@ -199,6 +199,11 @@ public:
virtual Status unregisterPullerCallback(int32_t atomTag, const String16& packageName) override;
/**
+ * Binder call to unregister any existing callback for the given uid and atom.
+ */
+ virtual Status unregisterPullAtomCallback(int32_t uid, int32_t atomTag) override;
+
+ /**
* Binder call to log BinaryPushStateChanged atom.
*/
virtual Status sendBinaryPushStateChangedAtom(
diff --git a/cmds/statsd/src/external/StatsPuller.cpp b/cmds/statsd/src/external/StatsPuller.cpp
index 3c6bc2db1d62..883bd28a4d13 100644
--- a/cmds/statsd/src/external/StatsPuller.cpp
+++ b/cmds/statsd/src/external/StatsPuller.cpp
@@ -47,6 +47,7 @@ bool StatsPuller::Pull(std::vector<std::shared_ptr<LogEvent>>* data) {
if (mHasGoodData) {
(*data) = mCachedData;
StatsdStats::getInstance().notePullFromCache(mTagId);
+
}
return mHasGoodData;
}
diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp
index f913118385a3..50896f84da43 100644
--- a/cmds/statsd/src/external/StatsPullerManager.cpp
+++ b/cmds/statsd/src/external/StatsPullerManager.cpp
@@ -294,6 +294,11 @@ StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) {
}
bool StatsPullerManager::Pull(int tagId, vector<shared_ptr<LogEvent>>* data) {
+ AutoMutex _l(mLock);
+ return PullLocked(tagId, data);
+}
+
+bool StatsPullerManager::PullLocked(int tagId, vector<shared_ptr<LogEvent>>* data) {
VLOG("Initiating pulling %d", tagId);
if (kAllPullAtomInfo.find({.atomTag = tagId}) != kAllPullAtomInfo.end()) {
@@ -422,7 +427,7 @@ void StatsPullerManager::OnAlarmFired(int64_t elapsedTimeNs) {
for (const auto& pullInfo : needToPull) {
vector<shared_ptr<LogEvent>> data;
- bool pullSuccess = Pull(pullInfo.first, &data);
+ bool pullSuccess = PullLocked(pullInfo.first, &data);
if (pullSuccess) {
StatsdStats::getInstance().notePullDelay(
pullInfo.first, getElapsedRealtimeNs() - elapsedTimeNs);
@@ -522,6 +527,12 @@ void StatsPullerManager::UnregisterPullerCallback(int32_t atomTag) {
kAllPullAtomInfo.erase({.atomTag = atomTag});
}
+void StatsPullerManager::UnregisterPullAtomCallback(const int uid, const int32_t atomTag) {
+ AutoMutex _l(mLock);
+ StatsdStats::getInstance().notePullerCallbackRegistrationChanged(atomTag, /*registered=*/false);
+ kAllPullAtomInfo.erase({.atomTag = atomTag});
+}
+
} // namespace statsd
} // namespace os
} // namespace android
diff --git a/cmds/statsd/src/external/StatsPullerManager.h b/cmds/statsd/src/external/StatsPullerManager.h
index 1bd9f92e4448..349fd47b6c9d 100644
--- a/cmds/statsd/src/external/StatsPullerManager.h
+++ b/cmds/statsd/src/external/StatsPullerManager.h
@@ -125,6 +125,8 @@ public:
void UnregisterPullerCallback(int32_t atomTag);
+ void UnregisterPullAtomCallback(const int uid, const int32_t atomTag);
+
static std::map<PullerKey, PullAtomInfo> kAllPullAtomInfo;
private:
@@ -139,6 +141,8 @@ private:
// mapping from simple matcher tagId to receivers
std::map<int, std::list<ReceiverInfo>> mReceivers;
+ bool PullLocked(int tagId, vector<std::shared_ptr<LogEvent>>* data);
+
// locks for data receiver and StatsCompanionService changes
Mutex mLock;
diff --git a/cmds/svc/src/com/android/commands/svc/DataCommand.java b/cmds/svc/src/com/android/commands/svc/DataCommand.java
deleted file mode 100644
index 35510cfd38b1..000000000000
--- a/cmds/svc/src/com/android/commands/svc/DataCommand.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.commands.svc;
-
-import android.os.ServiceManager;
-import android.os.RemoteException;
-import android.content.Context;
-import com.android.internal.telephony.ITelephony;
-
-public class DataCommand extends Svc.Command {
- public DataCommand() {
- super("data");
- }
-
- public String shortHelp() {
- return "Control mobile data connectivity";
- }
-
- public String longHelp() {
- return shortHelp() + "\n"
- + "\n"
- + "usage: svc data [enable|disable]\n"
- + " Turn mobile data on or off.\n\n";
- }
-
- public void run(String[] args) {
- boolean validCommand = false;
- if (args.length >= 2) {
- boolean flag = false;
- if ("enable".equals(args[1])) {
- flag = true;
- validCommand = true;
- } else if ("disable".equals(args[1])) {
- flag = false;
- validCommand = true;
- }
- if (validCommand) {
- ITelephony phoneMgr
- = ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
- try {
- if (flag) {
- phoneMgr.enableDataConnectivity();
- } else
- phoneMgr.disableDataConnectivity();
- }
- catch (RemoteException e) {
- System.err.println("Mobile data operation failed: " + e);
- }
- return;
- }
- }
- System.err.println(longHelp());
- }
-}
diff --git a/cmds/svc/src/com/android/commands/svc/Svc.java b/cmds/svc/src/com/android/commands/svc/Svc.java
index e602e2abbe03..2ed2678bc877 100644
--- a/cmds/svc/src/com/android/commands/svc/Svc.java
+++ b/cmds/svc/src/com/android/commands/svc/Svc.java
@@ -93,7 +93,6 @@ public class Svc {
public static final Command[] COMMANDS = new Command[] {
COMMAND_HELP,
new PowerCommand(),
- new DataCommand(),
// `svc wifi` has been migrated to WifiShellCommand
new UsbCommand(),
new NfcCommand(),
diff --git a/cmds/svc/svc b/cmds/svc/svc
index 60c95c7ec855..95265e817c1b 100755
--- a/cmds/svc/svc
+++ b/cmds/svc/svc
@@ -19,6 +19,20 @@ if [ "x$1" == "xwifi" ]; then
exit 1
fi
+if [ "x$1" == "xdata" ]; then
+ if [ "x$2" == "xenable" ]; then
+ exec cmd phone data enable
+ elif [ "x$2" == "xdisable" ]; then
+ exec cmd phone data disable
+ else
+ echo "Enable/Disable Mobile Data Connectivity"
+ echo ""
+ echo "usage: svc data [enable|disable]"
+ echo ""
+ fi
+ exit 1
+fi
+
export CLASSPATH=/system/framework/svc.jar
exec app_process /system/bin com.android.commands.svc.Svc "$@"
diff --git a/core/java/android/annotation/CallbackExecutor.java b/core/java/android/annotation/CallbackExecutor.java
index 5671a3d2b6d6..4258f730eb16 100644
--- a/core/java/android/annotation/CallbackExecutor.java
+++ b/core/java/android/annotation/CallbackExecutor.java
@@ -19,9 +19,6 @@ package android.annotation;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.SOURCE;
-import android.content.Context;
-import android.os.AsyncTask;
-
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.concurrent.Executor;
@@ -30,9 +27,10 @@ import java.util.concurrent.Executor;
* @paramDoc Callback and listener events are dispatched through this
* {@link Executor}, providing an easy way to control which thread is
* used. To dispatch events through the main thread of your
- * application, you can use {@link Context#getMainExecutor()}. To
- * dispatch events through a shared thread pool, you can use
- * {@link AsyncTask#THREAD_POOL_EXECUTOR}.
+ * application, you can use
+ * {@link android.content.Context#getMainExecutor() Context.getMainExecutor()}.
+ * To dispatch events through a shared thread pool, you can use
+ * {@link android.os.AsyncTask#THREAD_POOL_EXECUTOR AsyncTask#THREAD_POOL_EXECUTOR}.
* @hide
*/
@Retention(SOURCE)
diff --git a/core/java/android/annotation/RequiresPermission.java b/core/java/android/annotation/RequiresPermission.java
index 59d419f78ee0..1d89e31b2b99 100644
--- a/core/java/android/annotation/RequiresPermission.java
+++ b/core/java/android/annotation/RequiresPermission.java
@@ -15,11 +15,6 @@
*/
package android.annotation;
-import android.content.Intent;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.CONSTRUCTOR;
import static java.lang.annotation.ElementType.FIELD;
@@ -27,6 +22,9 @@ import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.SOURCE;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
/**
* Denotes that the annotated element requires (or may require) one or more permissions.
* <p/>
@@ -57,7 +55,8 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
* <p>
* When specified on a parameter, the annotation indicates that the method requires
* a permission which depends on the value of the parameter. For example, consider
- * {@link android.app.Activity#startActivity(Intent)}:
+ * {@link android.app.Activity#startActivity(android.content.Intent)
+ * Activity#startActivity(Intent)}:
* <pre>{@code
* public void startActivity(@RequiresPermission Intent intent) { ... }
* }</pre>
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index ff581c059935..9e0c2fc18fd9 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -8674,7 +8674,6 @@ public class Activity extends ContextThemeWrapper
* @hide
*/
@RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS)
- @UnsupportedAppUsage
public void registerRemoteAnimations(RemoteAnimationDefinition definition) {
try {
ActivityTaskManager.getService().registerRemoteAnimations(mToken, definition);
@@ -8683,6 +8682,20 @@ public class Activity extends ContextThemeWrapper
}
}
+ /**
+ * Unregisters all remote animations for this activity.
+ *
+ * @hide
+ */
+ @RequiresPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS)
+ public void unregisterRemoteAnimations() {
+ try {
+ ActivityTaskManager.getService().unregisterRemoteAnimations(mToken);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
class HostCallbacks extends FragmentHostCallback<Activity> {
public HostCallbacks() {
super(Activity.this /*activity*/);
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 68bdfae218ae..3f9f7fbbe477 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -4547,4 +4547,17 @@ public class ActivityManager {
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Method for the app to tell system that it's wedged and would like to trigger an ANR.
+ *
+ * @param reason The description of that what happened
+ */
+ public void appNotResponding(@NonNull final String reason) {
+ try {
+ getService().appNotResponding(reason);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 112bd303a8b3..e8494c4c5893 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -583,4 +583,9 @@ interface IActivityManager {
* unlockProgressListener can be null if monitoring progress is not necessary.
*/
boolean startUserInForegroundWithListener(int userid, IProgressListener unlockProgressListener);
+
+ /**
+ * Method for the app to tell system that it's wedged and would like to trigger an ANR.
+ */
+ void appNotResponding(String reason);
}
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index e2b1b8664d75..df5d6c71756d 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -437,6 +437,11 @@ interface IActivityTaskManager {
void registerRemoteAnimations(in IBinder token, in RemoteAnimationDefinition definition);
/**
+ * Unregisters all remote animations for a specific activity.
+ */
+ void unregisterRemoteAnimations(in IBinder token);
+
+ /**
* Registers a remote animation to be run for all activity starts from a certain package during
* a short predefined amount of time.
*/
diff --git a/core/java/android/app/StatsManager.java b/core/java/android/app/StatsManager.java
index cd855cf134d9..2d851e0abe6d 100644
--- a/core/java/android/app/StatsManager.java
+++ b/core/java/android/app/StatsManager.java
@@ -107,6 +107,20 @@ public final class StatsManager {
*/
public static final String ACTION_STATSD_STARTED = "android.app.action.STATSD_STARTED";
+ // Pull atom callback return codes.
+ /**
+ * Value indicating that this pull was successful and that the result should be used.
+ *
+ * @hide
+ **/
+ public static final int PULL_SUCCESS = 0;
+
+ /**
+ * Value indicating that this pull was unsuccessful and that the result should not be used.
+ * @hide
+ **/
+ public static final int PULL_SKIP = 1;
+
private static final long DEFAULT_COOL_DOWN_NS = 1_000_000_000L; // 1 second.
private static final long DEFAULT_TIMEOUT_NS = 10_000_000_000L; // 10 seconds.
@@ -508,13 +522,11 @@ public final class StatsManager {
* additive fields for mapping isolated to host uids.
* @param callback The callback to be invoked when the stats service pulls the atom.
* @param executor The executor in which to run the callback
- * @throws RemoteException if unsuccessful due to failing to connect to system server.
*
* @hide
*/
public void registerPullAtomCallback(int atomTag, @Nullable PullAtomMetadata metadata,
- @NonNull StatsPullAtomCallback callback, @NonNull Executor executor)
- throws RemoteException, SecurityException {
+ @NonNull StatsPullAtomCallback callback, @NonNull Executor executor) {
long coolDownNs = metadata == null ? DEFAULT_COOL_DOWN_NS : metadata.mCoolDownNs;
long timeoutNs = metadata == null ? DEFAULT_TIMEOUT_NS : metadata.mTimeoutNs;
int[] additiveFields = metadata == null ? new int[0] : metadata.mAdditiveFields;
@@ -522,10 +534,34 @@ public final class StatsManager {
additiveFields = new int[0];
}
synchronized (sLock) {
- IStatsCompanionService service = getIStatsCompanionServiceLocked();
- PullAtomCallbackInternal rec =
+ try {
+ IStatsCompanionService service = getIStatsCompanionServiceLocked();
+ PullAtomCallbackInternal rec =
new PullAtomCallbackInternal(atomTag, callback, executor);
- service.registerPullAtomCallback(atomTag, coolDownNs, timeoutNs, additiveFields, rec);
+ service.registerPullAtomCallback(atomTag, coolDownNs, timeoutNs, additiveFields,
+ rec);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Unable to register pull callback", e);
+ }
+ }
+ }
+
+ /**
+ * Unregisters a callback for an atom when that atom is to be pulled. Note that any ongoing
+ * pulls will still occur.
+ *
+ * @param atomTag The tag of the atom of which to unregister
+ *
+ * @hide
+ */
+ public void unregisterPullAtomCallback(int atomTag) {
+ synchronized (sLock) {
+ try {
+ IStatsCompanionService service = getIStatsCompanionServiceLocked();
+ service.unregisterPullAtomCallback(atomTag);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Unable to unregister pull atom callback");
+ }
}
}
@@ -544,9 +580,11 @@ public final class StatsManager {
public void onPullAtom(int atomTag, IPullAtomResultReceiver resultReceiver) {
mExecutor.execute(() -> {
List<StatsEvent> data = new ArrayList<>();
- boolean success = mCallback.onPullAtom(atomTag, data);
+ int successInt = mCallback.onPullAtom(atomTag, data);
+ boolean success = successInt == PULL_SUCCESS;
StatsEventParcel[] parcels = new StatsEventParcel[data.size()];
for (int i = 0; i < data.size(); i++) {
+ parcels[i] = new StatsEventParcel();
parcels[i].buffer = data.get(i).getBytes();
}
try {
@@ -649,9 +687,9 @@ public final class StatsManager {
public interface StatsPullAtomCallback {
/**
* Pull data for the specified atom tag, filling in the provided list of StatsEvent data.
- * @return if the pull was successful
+ * @return {@link #PULL_SUCCESS} if the pull was successful, or {@link #PULL_SKIP} if not.
*/
- boolean onPullAtom(int atomTag, List<StatsEvent> data);
+ int onPullAtom(int atomTag, List<StatsEvent> data);
}
private class StatsdDeathRecipient implements IBinder.DeathRecipient {
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 69c37ec42bd0..31c73b90aace 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -50,6 +50,8 @@ import android.content.ContentCaptureOptions;
import android.content.Context;
import android.content.IRestrictionsManager;
import android.content.RestrictionsManager;
+import android.content.integrity.AppIntegrityManager;
+import android.content.integrity.IAppIntegrityManager;
import android.content.om.IOverlayManager;
import android.content.om.OverlayManager;
import android.content.pm.CrossProfileApps;
@@ -160,6 +162,8 @@ import android.permission.PermissionControllerManager;
import android.permission.PermissionManager;
import android.print.IPrintManager;
import android.print.PrintManager;
+import android.security.FileIntegrityManager;
+import android.security.IFileIntegrityService;
import android.service.oemlock.IOemLockService;
import android.service.oemlock.OemLockManager;
import android.service.persistentdata.IPersistentDataBlockService;
@@ -1212,6 +1216,7 @@ public final class SystemServiceRegistry {
return new DynamicSystemManager(
IDynamicSystemService.Stub.asInterface(b));
}});
+
registerService(Context.BATTERY_STATS_SERVICE, BatteryStatsManager.class,
new CachedServiceFetcher<BatteryStatsManager>() {
@Override
@@ -1245,7 +1250,26 @@ public final class SystemServiceRegistry {
return new IncrementalManager(
IIncrementalManagerNative.Stub.asInterface(b));
}});
+
+ registerService(Context.FILE_INTEGRITY_SERVICE, FileIntegrityManager.class,
+ new CachedServiceFetcher<FileIntegrityManager>() {
+ @Override
+ public FileIntegrityManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(
+ Context.FILE_INTEGRITY_SERVICE);
+ return new FileIntegrityManager(
+ IFileIntegrityService.Stub.asInterface(b));
+ }});
//CHECKSTYLE:ON IndentationCheck
+ registerService(Context.APP_INTEGRITY_SERVICE, AppIntegrityManager.class,
+ new CachedServiceFetcher<AppIntegrityManager>() {
+ @Override
+ public AppIntegrityManager createService(ContextImpl ctx)
+ throws ServiceNotFoundException {
+ IBinder b = ServiceManager.getServiceOrThrow(Context.APP_INTEGRITY_SERVICE);
+ return new AppIntegrityManager(IAppIntegrityManager.Stub.asInterface(b));
+ }});
sInitializing = true;
try {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3ca8f49e4d54..11feccada492 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -5061,12 +5061,17 @@ public class DevicePolicyManager {
* owner. If Device ID attestation is requested (using {@link #ID_TYPE_SERIAL},
* {@link #ID_TYPE_IMEI} or {@link #ID_TYPE_MEID}), the caller must be the Device Owner
* or the Certificate Installer delegate.
- * @throws IllegalArgumentException if the alias in {@code keySpec} is empty, if the
- * algorithm specification in {@code keySpec} is not {@code RSAKeyGenParameterSpec}
- * or {@code ECGenParameterSpec}, or if Device ID attestation was requested but the
- * {@code keySpec} does not contain an attestation challenge.
- * @throws UnsupportedOperationException if Device ID attestation was requested but the
- * underlying hardware does not support it.
+ * @throws IllegalArgumentException in the following cases:
+ * <p>
+ * <ul>
+ * <li>The alias in {@code keySpec} is empty.</li>
+ * <li>The algorithm specification in {@code keySpec} is not
+ * {@code RSAKeyGenParameterSpec} or {@code ECGenParameterSpec}.</li>
+ * <li>Device ID attestation was requested but the {@code keySpec} does not contain an
+ * attestation challenge.</li>
+ * </ul>
+ * @throws UnsupportedOperationException if Device ID attestation or individual attestation
+ * was requested but the underlying hardware does not support it.
* @throws StrongBoxUnavailableException if the use of StrongBox for key generation was
* specified in {@code keySpec} but the device does not have one.
* @see KeyGenParameterSpec.Builder#setAttestationChallenge(byte[])
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgHandler.java b/core/java/android/companion/Association.aidl
index bc6b83ba1def..2a28f1f094ad 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgHandler.java
+++ b/core/java/android/companion/Association.aidl
@@ -13,18 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package android.companion;
-package com.android.systemui.dagger.qualifiers;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface BgHandler {
-}
+parcelable Association;
diff --git a/core/java/android/companion/Association.java b/core/java/android/companion/Association.java
new file mode 100644
index 000000000000..3fa6a3e76634
--- /dev/null
+++ b/core/java/android/companion/Association.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.companion;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+import java.util.Objects;
+
+/**
+ * A record indicating that a device with a given address was confirmed by the user to be
+ * associated to a given companion app
+ *
+ * @hide
+ */
+@DataClass(genEqualsHashCode = true, genToString = true)
+public class Association implements Parcelable {
+
+ public final int userId;
+ public final @NonNull String deviceAddress;
+ public final @NonNull String companionAppPackage;
+
+
+
+
+ // Code below generated by codegen v1.0.13.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/companion/Association.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ public Association(
+ int userId,
+ @NonNull String deviceAddress,
+ @NonNull String companionAppPackage) {
+ this.userId = userId;
+ this.deviceAddress = deviceAddress;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, deviceAddress);
+ this.companionAppPackage = companionAppPackage;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, companionAppPackage);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "Association { " +
+ "userId = " + userId + ", " +
+ "deviceAddress = " + deviceAddress + ", " +
+ "companionAppPackage = " + companionAppPackage +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(Association other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ Association that = (Association) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && userId == that.userId
+ && Objects.equals(deviceAddress, that.deviceAddress)
+ && Objects.equals(companionAppPackage, that.companionAppPackage);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + userId;
+ _hash = 31 * _hash + Objects.hashCode(deviceAddress);
+ _hash = 31 * _hash + Objects.hashCode(companionAppPackage);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ dest.writeInt(userId);
+ dest.writeString(deviceAddress);
+ dest.writeString(companionAppPackage);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ protected Association(@NonNull Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ int _userId = in.readInt();
+ String _deviceAddress = in.readString();
+ String _companionAppPackage = in.readString();
+
+ this.userId = _userId;
+ this.deviceAddress = _deviceAddress;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, deviceAddress);
+ this.companionAppPackage = _companionAppPackage;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, companionAppPackage);
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<Association> CREATOR
+ = new Parcelable.Creator<Association>() {
+ @Override
+ public Association[] newArray(int size) {
+ return new Association[size];
+ }
+
+ @Override
+ public Association createFromParcel(@NonNull Parcel in) {
+ return new Association(in);
+ }
+ };
+
+ @DataClass.Generated(
+ time = 1573767103332L,
+ codegenVersion = "1.0.13",
+ sourceFile = "frameworks/base/core/java/android/companion/Association.java",
+ inputSignatures = "public final int userId\npublic final @android.annotation.NonNull java.lang.String deviceAddress\npublic final @android.annotation.NonNull java.lang.String companionAppPackage\nclass Association extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
index 5398c3cea68d..5e3d46caae91 100644
--- a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
+++ b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
@@ -16,9 +16,10 @@
package android.companion;
+import android.companion.Association;
import android.companion.AssociationRequest;
-import android.companion.ICompanionDeviceDiscoveryServiceCallback;
import android.companion.IFindDeviceCallback;
+import com.android.internal.infra.AndroidFuture;
/** @hide */
@@ -27,5 +28,5 @@ interface ICompanionDeviceDiscoveryService {
in AssociationRequest request,
in String callingPackage,
in IFindDeviceCallback findCallback,
- in ICompanionDeviceDiscoveryServiceCallback serviceCallback);
+ in AndroidFuture<Association> serviceCallback);
}
diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
deleted file mode 100644
index c9dc019bd2f2..000000000000
--- a/core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing per missions and
- * limitations under the License.
- */
-
-package android.companion;
-
-/** @hide */
-interface ICompanionDeviceDiscoveryServiceCallback {
- @UnsupportedAppUsage
- oneway void onDeviceSelected(String packageName, int userId, String deviceAddress);
- @UnsupportedAppUsage
- oneway void onDeviceSelectionCancel();
-}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 483bf3f1ec87..4815d7847115 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -5045,6 +5045,14 @@ public abstract class Context {
public static final String INCREMENTAL_SERVICE = "incremental_service";
/**
+ * Use with {@link #getSystemService(String)} to retrieve an
+ * {@link android.security.FileIntegrityManager}.
+ * @see #getSystemService(String)
+ * @see android.security.FileIntegrityManager
+ */
+ public static final String FILE_INTEGRITY_SERVICE = "file_integrity";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c5a147af3137..7967708ce19a 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -11050,6 +11050,7 @@ public class Intent implements Parcelable, Cloneable {
case ACTION_MEDIA_SCANNER_FINISHED:
case ACTION_MEDIA_SCANNER_SCAN_FILE:
case ACTION_PACKAGE_NEEDS_VERIFICATION:
+ case ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION:
case ACTION_PACKAGE_VERIFIED:
case ACTION_PACKAGE_ENABLE_ROLLBACK:
// Ignore legacy actions
diff --git a/core/java/android/content/integrity/AppInstallMetadata.java b/core/java/android/content/integrity/AppInstallMetadata.java
index c9634758f63f..70776c76531b 100644
--- a/core/java/android/content/integrity/AppInstallMetadata.java
+++ b/core/java/android/content/integrity/AppInstallMetadata.java
@@ -86,6 +86,19 @@ public final class AppInstallMetadata {
return mIsPreInstalled;
}
+ @Override
+ public String toString() {
+ return String.format(
+ "AppInstallMetadata { PackageName = %s, AppCert = %s, InstallerName = %s,"
+ + " InstallerCert = %s, VersionCode = %d, PreInstalled = %b }",
+ mPackageName,
+ mAppCertificate,
+ mInstallerName == null ? "null" : mInstallerName,
+ mInstallerCertificate == null ? "null" : mInstallerCertificate,
+ mVersionCode,
+ mIsPreInstalled);
+ }
+
/** Builder class for constructing {@link AppInstallMetadata} objects. */
public static final class Builder {
private String mPackageName;
diff --git a/core/java/android/content/pm/DataLoaderParams.java b/core/java/android/content/pm/DataLoaderParams.java
index af4b99a5f815..60d7bb3c5918 100644
--- a/core/java/android/content/pm/DataLoaderParams.java
+++ b/core/java/android/content/pm/DataLoaderParams.java
@@ -19,6 +19,7 @@ package android.content.pm;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.content.ComponentName;
import android.os.ParcelFileDescriptor;
import java.util.Arrays;
@@ -26,7 +27,7 @@ import java.util.Map;
import java.util.stream.Collectors;
/**
- * This class represents the parameters used to configure an Incremental Data Loader.
+ * This class represents the parameters used to configure a Data Loader.
*
* WARNING: This is a system API to aid internal development.
* Use at your own risk. It will change or be removed without warning.
@@ -34,13 +35,41 @@ import java.util.stream.Collectors;
*/
@SystemApi
public class DataLoaderParams {
- @NonNull private final DataLoaderParamsParcel mData;
+ @NonNull
+ private final DataLoaderParamsParcel mData;
- public DataLoaderParams(@NonNull String url, @NonNull String packageName,
+ /**
+ * Creates and populates set of Data Loader parameters for Streaming installation.
+ *
+ * @param componentName Data Loader component supporting Streaming installation.
+ * @param arguments free form installation arguments
+ */
+ public static final @NonNull DataLoaderParams forStreaming(@NonNull ComponentName componentName,
+ @NonNull String arguments) {
+ return new DataLoaderParams(DataLoaderType.STREAMING, componentName, arguments, null);
+ }
+
+ /**
+ * Creates and populates set of Data Loader parameters for Incremental installation.
+ *
+ * @param componentName Data Loader component supporting Incremental installation.
+ * @param arguments free form installation arguments
+ * @param namedFds TODO(b/146080380) remove
+ */
+ public static final @NonNull DataLoaderParams forIncremental(
+ @NonNull ComponentName componentName, @NonNull String arguments,
@Nullable Map<String, ParcelFileDescriptor> namedFds) {
+ return new DataLoaderParams(DataLoaderType.INCREMENTAL, componentName, arguments, namedFds);
+ }
+
+ /** @hide */
+ public DataLoaderParams(@NonNull @DataLoaderType int type, @NonNull ComponentName componentName,
+ @NonNull String arguments, @Nullable Map<String, ParcelFileDescriptor> namedFds) {
DataLoaderParamsParcel data = new DataLoaderParamsParcel();
- data.staticArgs = url;
- data.packageName = packageName;
+ data.type = type;
+ data.packageName = componentName.getPackageName();
+ data.className = componentName.getClassName();
+ data.arguments = arguments;
if (namedFds == null || namedFds.isEmpty()) {
data.dynamicArgs = new NamedParcelFileDescriptor[0];
} else {
@@ -56,39 +85,42 @@ public class DataLoaderParams {
mData = data;
}
- /**
- * @hide
- */
- public DataLoaderParams(@NonNull DataLoaderParamsParcel data) {
+ /** @hide */
+ DataLoaderParams(@NonNull DataLoaderParamsParcel data) {
mData = data;
}
+ /** @hide */
+ public final @NonNull DataLoaderParamsParcel getData() {
+ return mData;
+ }
+
/**
- * @return static server's URL
+ * @return data loader type
*/
- public final @NonNull String getStaticArgs() {
- return mData.staticArgs;
+ public final @NonNull @DataLoaderType int getType() {
+ return mData.type;
}
/**
- * @return data loader's package name
+ * @return data loader's component name
*/
- public final @NonNull String getPackageName() {
- return mData.packageName;
+ public final @NonNull ComponentName getComponentName() {
+ return new ComponentName(mData.packageName, mData.className);
}
/**
- * @hide
+ * @return data loader's arguments
*/
- public final @NonNull DataLoaderParamsParcel getData() {
- return mData;
+ public final @NonNull String getArguments() {
+ return mData.arguments;
}
/**
- * @return data loader's dynamic arguments such as file descriptors
+ * @return data loader's dynamic arguments such as file descriptors TODO: remove
*/
public final @NonNull Map<String, ParcelFileDescriptor> getDynamicArgs() {
return Arrays.stream(mData.dynamicArgs).collect(
- Collectors.toMap(p->p.name, p->p.fd));
+ Collectors.toMap(p -> p.name, p -> p.fd));
}
}
diff --git a/core/java/android/content/pm/DataLoaderParamsParcel.aidl b/core/java/android/content/pm/DataLoaderParamsParcel.aidl
index 33163980b915..e05843b4d4e9 100644
--- a/core/java/android/content/pm/DataLoaderParamsParcel.aidl
+++ b/core/java/android/content/pm/DataLoaderParamsParcel.aidl
@@ -16,6 +16,7 @@
package android.content.pm;
+import android.content.pm.DataLoaderType;
import android.content.pm.NamedParcelFileDescriptor;
/**
@@ -23,7 +24,9 @@ import android.content.pm.NamedParcelFileDescriptor;
* @hide
*/
parcelable DataLoaderParamsParcel {
+ DataLoaderType type;
@utf8InCpp String packageName;
- @utf8InCpp String staticArgs;
+ @utf8InCpp String className;
+ @utf8InCpp String arguments;
NamedParcelFileDescriptor[] dynamicArgs;
}
diff --git a/core/java/android/content/pm/DataLoaderType.aidl b/core/java/android/content/pm/DataLoaderType.aidl
new file mode 100644
index 000000000000..7d726f5ddd6f
--- /dev/null
+++ b/core/java/android/content/pm/DataLoaderType.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+/**
+ * Types of Data Loader for an installation session.
+ * @hide
+ */
+@Backing(type="int")
+enum DataLoaderType {
+ /**
+ * Default value, legacy installation.
+ */
+ NONE = 0,
+ /**
+ * Streaming installation using data loader.
+ */
+ STREAMING = 1,
+ /**
+ * Streaming installation using Incremental FileSystem.
+ */
+ INCREMENTAL = 2,
+}
diff --git a/core/java/android/content/pm/IDataLoader.aidl b/core/java/android/content/pm/IDataLoader.aidl
index c65bd6acbaf8..b5baa9379d16 100644
--- a/core/java/android/content/pm/IDataLoader.aidl
+++ b/core/java/android/content/pm/IDataLoader.aidl
@@ -27,7 +27,9 @@ import java.util.List;
*/
oneway interface IDataLoader {
void create(int id, in Bundle params, IDataLoaderStatusListener listener);
- void start(in List<InstallationFile> fileInfos);
+ void start();
void stop();
void destroy();
+
+ void prepareImage(in List<InstallationFile> addedFiles, in List<String> removedFiles);
}
diff --git a/core/java/android/content/pm/IDataLoaderStatusListener.aidl b/core/java/android/content/pm/IDataLoaderStatusListener.aidl
index a60d6ee2d28a..5011faafa2f7 100644
--- a/core/java/android/content/pm/IDataLoaderStatusListener.aidl
+++ b/core/java/android/content/pm/IDataLoaderStatusListener.aidl
@@ -22,13 +22,18 @@ package android.content.pm;
*/
oneway interface IDataLoaderStatusListener {
/** Data loader status */
- const int DATA_LOADER_READY = 0;
- const int DATA_LOADER_NOT_READY = 1;
- const int DATA_LOADER_RUNNING = 2;
+ const int DATA_LOADER_CREATED = 0;
+ const int DATA_LOADER_DESTROYED = 1;
+
+ const int DATA_LOADER_STARTED = 2;
const int DATA_LOADER_STOPPED = 3;
- const int DATA_LOADER_SLOW_CONNECTION = 4;
- const int DATA_LOADER_NO_CONNECTION = 5;
- const int DATA_LOADER_CONNECTION_OK = 6;
+
+ const int DATA_LOADER_IMAGE_READY = 4;
+ const int DATA_LOADER_IMAGE_NOT_READY = 5;
+
+ const int DATA_LOADER_SLOW_CONNECTION = 6;
+ const int DATA_LOADER_NO_CONNECTION = 7;
+ const int DATA_LOADER_CONNECTION_OK = 8;
/** Data loader status callback */
void onStatusChanged(in int dataLoaderId, in int status);
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 3d6d849bf03d..e4a0bc0197a1 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1461,10 +1461,7 @@ public class PackageInstaller {
/** {@hide} */
public long requiredInstalledVersionCode = PackageManager.VERSION_CODE_HIGHEST;
/** {@hide} */
- public DataLoaderParams incrementalParams;
- /** TODO(b/146080380): add a class name to make it fully compatible with ComponentName.
- * {@hide} */
- public String dataLoaderPackageName;
+ public DataLoaderParams dataLoaderParams;
/** {@hide} */
public int rollbackDataPolicy = PackageManager.RollbackDataPolicy.RESTORE;
@@ -1503,10 +1500,8 @@ public class PackageInstaller {
DataLoaderParamsParcel dataLoaderParamsParcel = source.readParcelable(
DataLoaderParamsParcel.class.getClassLoader());
if (dataLoaderParamsParcel != null) {
- incrementalParams = new DataLoaderParams(
- dataLoaderParamsParcel);
+ dataLoaderParams = new DataLoaderParams(dataLoaderParamsParcel);
}
- dataLoaderPackageName = source.readString();
rollbackDataPolicy = source.readInt();
}
@@ -1531,8 +1526,7 @@ public class PackageInstaller {
ret.isMultiPackage = isMultiPackage;
ret.isStaged = isStaged;
ret.requiredInstalledVersionCode = requiredInstalledVersionCode;
- ret.incrementalParams = incrementalParams;
- ret.dataLoaderPackageName = dataLoaderPackageName;
+ ret.dataLoaderParams = dataLoaderParams;
ret.rollbackDataPolicy = rollbackDataPolicy;
return ret;
}
@@ -1893,29 +1887,18 @@ public class PackageInstaller {
}
/**
- * Set Incremental data loader params.
+ * Set the data loader params for the session.
+ * This also switches installation into data provider mode and disallow direct writes into
+ * staging folder.
+ *
* WARNING: This is a system API to aid internal development.
* Use at your own risk. It will change or be removed without warning.
* {@hide}
*/
@SystemApi
@RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
- public void setIncrementalParams(@NonNull DataLoaderParams incrementalParams) {
- this.incrementalParams = incrementalParams;
- }
-
- /**
- * Set the data provider params for the session.
- * This also switches installation into callback mode and disallow direct writes into
- * staging folder.
- * TODO(b/146080380): unify dataprovider params with Incremental.
- *
- * @param dataLoaderPackageName name of the dataLoader package
- * {@hide}
- */
- @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
- public void setDataLoaderPackageName(String dataLoaderPackageName) {
- this.dataLoaderPackageName = dataLoaderPackageName;
+ public void setDataLoaderParams(@NonNull DataLoaderParams dataLoaderParams) {
+ this.dataLoaderParams = dataLoaderParams;
}
/** {@hide} */
@@ -1938,7 +1921,7 @@ public class PackageInstaller {
pw.printPair("isMultiPackage", isMultiPackage);
pw.printPair("isStaged", isStaged);
pw.printPair("requiredInstalledVersionCode", requiredInstalledVersionCode);
- pw.printPair("dataLoaderPackageName", dataLoaderPackageName);
+ pw.printPair("dataLoaderParams", dataLoaderParams);
pw.printPair("rollbackDataPolicy", rollbackDataPolicy);
pw.println();
}
@@ -1969,12 +1952,11 @@ public class PackageInstaller {
dest.writeBoolean(isMultiPackage);
dest.writeBoolean(isStaged);
dest.writeLong(requiredInstalledVersionCode);
- if (incrementalParams != null) {
- dest.writeParcelable(incrementalParams.getData(), flags);
+ if (dataLoaderParams != null) {
+ dest.writeParcelable(dataLoaderParams.getData(), flags);
} else {
dest.writeParcelable(null, flags);
}
- dest.writeString(dataLoaderPackageName);
dest.writeInt(rollbackDataPolicy);
}
diff --git a/core/java/android/os/incremental/IncrementalFileStorages.java b/core/java/android/os/incremental/IncrementalFileStorages.java
index fb94fc9bd719..2138d553102e 100644
--- a/core/java/android/os/incremental/IncrementalFileStorages.java
+++ b/core/java/android/os/incremental/IncrementalFileStorages.java
@@ -87,8 +87,8 @@ public final class IncrementalFileStorages {
mPackageName = packageName;
mStageDir = stageDir;
mIncrementalManager = incrementalManager;
- if (dataLoaderParams.getPackageName().equals("local")) {
- final String incrementalPath = dataLoaderParams.getStaticArgs();
+ if (dataLoaderParams.getComponentName().getPackageName().equals("local")) {
+ final String incrementalPath = dataLoaderParams.getArguments();
mDefaultStorage = mIncrementalManager.openStorage(incrementalPath);
mDefaultDir = incrementalPath;
return;
diff --git a/core/java/android/security/FileIntegrityManager.java b/core/java/android/security/FileIntegrityManager.java
new file mode 100644
index 000000000000..cdd6584e9b35
--- /dev/null
+++ b/core/java/android/security/FileIntegrityManager.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.os.RemoteException;
+
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+
+/**
+ * This class provides access to file integrity related operations.
+ */
+@SystemService(Context.FILE_INTEGRITY_SERVICE)
+public final class FileIntegrityManager {
+ @NonNull private final IFileIntegrityService mService;
+
+ /** @hide */
+ public FileIntegrityManager(@NonNull IFileIntegrityService service) {
+ mService = service;
+ }
+
+ /**
+ * Returns true if APK Verity is supported on the device. When supported, an APK can be
+ * installed with a fs-verity signature (if verified with trusted App Source Certificate) for
+ * continuous on-access verification.
+ */
+ public boolean isApkVeritySupported() {
+ try {
+ // Go through the service just to avoid exposing the vendor controlled system property
+ // to all apps.
+ return mService.isApkVeritySupported();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns whether the given certificate can be used to prove app's install source. Always
+ * return false if the feature is not supported.
+ *
+ * <p>A store can use this API to decide if a signature file needs to be downloaded. Also, if a
+ * store has shipped different certificates before (e.g. with stronger and weaker key), it can
+ * also use this API to download the best signature on the running device.
+ *
+ * @return whether the certificate is trusted in the system
+ */
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.INSTALL_PACKAGES,
+ android.Manifest.permission.REQUEST_INSTALL_PACKAGES
+ })
+ public boolean isAppSourceCertificateTrusted(@NonNull X509Certificate certificate)
+ throws CertificateEncodingException {
+ try {
+ return mService.isAppSourceCertificateTrusted(certificate.getEncoded());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainLooper.java b/core/java/android/security/IFileIntegrityService.aidl
index 750d7d72035c..ebb8bcb85350 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainLooper.java
+++ b/core/java/android/security/IFileIntegrityService.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -14,17 +14,13 @@
* limitations under the License.
*/
-package com.android.systemui.dagger.qualifiers;
+package android.security;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface MainLooper {
+/**
+ * Binder interface to communicate with FileIntegrityService.
+ * @hide
+ */
+interface IFileIntegrityService {
+ boolean isApkVeritySupported();
+ boolean isAppSourceCertificateTrusted(in byte[] certificateBytes);
}
diff --git a/core/java/android/service/dataloader/DataLoaderService.java b/core/java/android/service/dataloader/DataLoaderService.java
index 54a4fa6023a1..75f252e23f79 100644
--- a/core/java/android/service/dataloader/DataLoaderService.java
+++ b/core/java/android/service/dataloader/DataLoaderService.java
@@ -16,7 +16,6 @@
package android.service.dataloader;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -27,19 +26,16 @@ import android.content.pm.DataLoaderParamsParcel;
import android.content.pm.FileSystemControlParcel;
import android.content.pm.IDataLoader;
import android.content.pm.IDataLoaderStatusListener;
-import android.content.pm.IPackageInstallerSessionFileSystemConnector;
import android.content.pm.InstallationFile;
import android.content.pm.NamedParcelFileDescriptor;
import android.os.Bundle;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
import android.util.ExceptionUtils;
import android.util.Slog;
import java.io.IOException;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
+import java.util.Collection;
import java.util.List;
/**
@@ -55,88 +51,35 @@ import java.util.List;
*/
@SystemApi
public abstract class DataLoaderService extends Service {
- private static final String TAG = "IncrementalDataLoaderService";
+ private static final String TAG = "DataLoaderService";
private final DataLoaderBinderService mBinder = new DataLoaderBinderService();
- /** @hide */
- public static final int DATA_LOADER_READY =
- IDataLoaderStatusListener.DATA_LOADER_READY;
- /** @hide */
- public static final int DATA_LOADER_NOT_READY =
- IDataLoaderStatusListener.DATA_LOADER_NOT_READY;
- /** @hide */
- public static final int DATA_LOADER_RUNNING =
- IDataLoaderStatusListener.DATA_LOADER_RUNNING;
- /** @hide */
- public static final int DATA_LOADER_STOPPED =
- IDataLoaderStatusListener.DATA_LOADER_STOPPED;
- /** @hide */
- public static final int DATA_LOADER_SLOW_CONNECTION =
- IDataLoaderStatusListener.DATA_LOADER_SLOW_CONNECTION;
- /** @hide */
- public static final int DATA_LOADER_NO_CONNECTION =
- IDataLoaderStatusListener.DATA_LOADER_NO_CONNECTION;
- /** @hide */
- public static final int DATA_LOADER_CONNECTION_OK =
- IDataLoaderStatusListener.DATA_LOADER_CONNECTION_OK;
-
- /** @hide */
- @Retention(RetentionPolicy.SOURCE)
- @IntDef(prefix = {"DATA_LOADER_"}, value = {
- DATA_LOADER_READY,
- DATA_LOADER_NOT_READY,
- DATA_LOADER_RUNNING,
- DATA_LOADER_STOPPED,
- DATA_LOADER_SLOW_CONNECTION,
- DATA_LOADER_NO_CONNECTION,
- DATA_LOADER_CONNECTION_OK
- })
- public @interface DataLoaderStatus {
- }
-
/**
- * Managed DataLoader interface. Each instance corresponds to a single Incremental File System
- * instance.
+ * Managed DataLoader interface. Each instance corresponds to a single installation session.
* @hide
*/
- public abstract static class DataLoader {
+ public interface DataLoader {
/**
- * A virtual constructor used to do simple initialization. Not ready to serve any data yet.
- * All heavy-lifting has to be done in onStart.
+ * A virtual constructor.
*
- * @param params Data loader configuration parameters.
- * @param connector IncFS API wrapper.
- * @param listener Used for reporting internal state to IncrementalService.
+ * @param dataLoaderParams parameters set in the installation session
+ * @param connector FS API wrapper
* @return True if initialization of a Data Loader was successful. False will be reported to
- * IncrementalService and can cause an unmount of an IFS instance.
+ * PackageManager and fail the installation
*/
- public abstract boolean onCreate(@NonNull DataLoaderParams params,
- @NonNull FileSystemConnector connector,
- @NonNull StatusListener listener);
+ boolean onCreate(@NonNull DataLoaderParams dataLoaderParams,
+ @NonNull FileSystemConnector connector);
/**
- * Start the data loader. After this method returns data loader is considered to be ready to
- * receive callbacks from IFS, supply data via connector and send status updates via
- * callbacks.
+ * Prepare installation image. After this method succeeds installer will validate the files
+ * and continue installation.
*
- * @return True if Data Loader was able to start. False will be reported to
- * IncrementalService and can cause an unmount of an IFS instance.
- */
- public abstract boolean onStart();
-
- /**
- * Stop the data loader. Use to stop any additional threads and free up resources. Data
- * loader is not longer responsible for supplying data. Start/Stop pair can be called
- * multiple times e.g. if IFS detects corruption and data needs to be re-loaded.
+ * @param addedFiles list of files created in this installation session.
+ * @param removedFiles list of files removed in this installation session.
+ * @return false if unable to create and populate all addedFiles.
*/
- public abstract void onStop();
-
- /**
- * Virtual destructor. Use to cleanup all internal state. After this method returns, the
- * data loader can no longer use connector or callbacks. For any additional operations with
- * this instance of IFS a new DataLoader will be created using createDataLoader method.
- */
- public abstract void onDestroy();
+ boolean onPrepareImage(Collection<InstallationFile> addedFiles,
+ Collection<String> removedFiles);
}
/**
@@ -145,7 +88,9 @@ public abstract class DataLoaderService extends Service {
* @return An instance of a DataLoader.
* @hide
*/
- public abstract @Nullable DataLoader onCreateDataLoader();
+ public @Nullable DataLoader onCreateDataLoader() {
+ return null;
+ }
/**
* @hide
@@ -160,148 +105,125 @@ public abstract class DataLoaderService extends Service {
@Override
public void create(int id, @NonNull Bundle options,
@NonNull IDataLoaderStatusListener listener)
- throws IllegalArgumentException, RuntimeException {
+ throws IllegalArgumentException, RuntimeException {
mId = id;
- final DataLoaderParamsParcel params = options.getParcelable("params");
+ final DataLoaderParamsParcel params = options.getParcelable("params");
if (params == null) {
- throw new IllegalArgumentException("Must specify Incremental data loader params");
+ throw new IllegalArgumentException("Must specify data loader params");
}
- final FileSystemControlParcel control =
- options.getParcelable("control");
+ final FileSystemControlParcel control = options.getParcelable("control");
if (control == null) {
- throw new IllegalArgumentException("Must specify Incremental control parcel");
+ throw new IllegalArgumentException("Must specify control parcel");
}
- mStatusListener = listener;
try {
if (!nativeCreateDataLoader(id, control, params, listener)) {
Slog.e(TAG, "Failed to create native loader for " + mId);
}
} catch (Exception ex) {
+ Slog.e(TAG, "Failed to create native loader for " + mId, ex);
destroy();
throw new RuntimeException(ex);
} finally {
// Closing FDs.
- if (control.incremental.cmd != null) {
- try {
- control.incremental.cmd.close();
- } catch (IOException e) {
- Slog.e(TAG, "Failed to close IncFs CMD file descriptor " + e);
+ if (control.incremental != null) {
+ if (control.incremental.cmd != null) {
+ try {
+ control.incremental.cmd.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to close IncFs CMD file descriptor " + e);
+ }
}
- }
- if (control.incremental.log != null) {
- try {
- control.incremental.log.close();
- } catch (IOException e) {
- Slog.e(TAG, "Failed to close IncFs LOG file descriptor " + e);
+ if (control.incremental.log != null) {
+ try {
+ control.incremental.log.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to close IncFs LOG file descriptor " + e);
+ }
}
}
- NamedParcelFileDescriptor[] fds = params.dynamicArgs;
- for (NamedParcelFileDescriptor nfd : fds) {
- try {
- nfd.fd.close();
- } catch (IOException e) {
- Slog.e(TAG,
- "Failed to close DynamicArgs parcel file descriptor " + e);
+ if (params.dynamicArgs != null) {
+ NamedParcelFileDescriptor[] fds = params.dynamicArgs;
+ for (NamedParcelFileDescriptor nfd : fds) {
+ try {
+ nfd.fd.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Failed to close DynamicArgs parcel file descriptor " + e);
+ }
}
}
}
}
@Override
- public void start(List<InstallationFile> fileInfos) {
+ public void start() {
if (!nativeStartDataLoader(mId)) {
- Slog.e(TAG, "Failed to start loader: loader not found for " + mId);
+ Slog.e(TAG, "Failed to start loader: " + mId);
}
}
@Override
public void stop() {
if (!nativeStopDataLoader(mId)) {
- Slog.w(TAG, "Failed to stop loader: loader not found for " + mId);
+ Slog.w(TAG, "Failed to stop loader: " + mId);
}
}
@Override
public void destroy() {
if (!nativeDestroyDataLoader(mId)) {
- Slog.w(TAG, "Failed to destroy loader: loader not found for " + mId);
+ Slog.w(TAG, "Failed to destroy loader: " + mId);
+ }
+ }
+
+ @Override
+ public void prepareImage(List<InstallationFile> addedFiles, List<String> removedFiles) {
+ if (!nativePrepareImage(mId, addedFiles, removedFiles)) {
+ Slog.w(TAG, "Failed to destroy loader: " + mId);
}
}
}
/**
- *
* Used by the DataLoaderService implementations.
*
* @hide
*/
public static final class FileSystemConnector {
/**
- * Creates a wrapper for an installation session connector.
+ * Create a wrapper for a native instance.
+ *
* @hide
*/
- FileSystemConnector(IPackageInstallerSessionFileSystemConnector connector) {
- mConnector = connector;
+ FileSystemConnector(long nativeInstance) {
+ mNativeInstance = nativeInstance;
}
/**
* Write data to an installation file from an arbitrary FD.
*
- * @param name name of file previously added to the installation session.
- * @param offsetBytes offset into the file to begin writing at, or 0 to
- * start at the beginning of the file.
- * @param lengthBytes total size of the file being written, used to
- * preallocate the underlying disk space, or -1 if unknown.
- * The system may clear various caches as needed to allocate
- * this space.
- * @param incomingFd FD to read bytes from.
- * @throws IOException if trouble opening the file for writing, such as
- * lack of disk space or unavailable media.
+ * @param name name of file previously added to the installation session.
+ * @param offsetBytes offset into the file to begin writing at, or 0 to start at the
+ * beginning of the file.
+ * @param lengthBytes total size of the file being written, used to preallocate the
+ * underlying disk space, or -1 if unknown. The system may clear various
+ * caches as needed to allocate this space.
+ * @param incomingFd FD to read bytes from.
+ * @throws IOException if trouble opening the file for writing, such as lack of disk space
+ * or unavailable media.
*/
public void writeData(String name, long offsetBytes, long lengthBytes,
ParcelFileDescriptor incomingFd) throws IOException {
try {
- mConnector.writeData(name, offsetBytes, lengthBytes, incomingFd);
+ nativeWriteData(mNativeInstance, name, offsetBytes, lengthBytes, incomingFd);
} catch (RuntimeException e) {
ExceptionUtils.maybeUnwrapIOException(e);
throw e;
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
}
}
- private final IPackageInstallerSessionFileSystemConnector mConnector;
- }
-
- /**
- * Wrapper for native reporting DataLoader statuses.
- * @hide
- */
- public static final class StatusListener {
- /**
- * Creates a wrapper for a native instance.
- * @hide
- */
- StatusListener(long nativeInstance) {
- mNativeInstance = nativeInstance;
- }
-
- /**
- * Report the status of DataLoader. Used for system-wide notifications e.g., disabling
- * applications which rely on this data loader to function properly.
- *
- * @param status status to report.
- * @return True if status was reported successfully.
- */
- public boolean onStatusChanged(@DataLoaderStatus int status) {
- return nativeReportStatus(mNativeInstance, status);
- }
-
private final long mNativeInstance;
}
- private IDataLoaderStatusListener mStatusListener = null;
-
/* Native methods */
private native boolean nativeCreateDataLoader(int storageId,
@NonNull FileSystemControlParcel control,
@@ -314,5 +236,10 @@ public abstract class DataLoaderService extends Service {
private native boolean nativeDestroyDataLoader(int storageId);
- private static native boolean nativeReportStatus(long nativeInstance, int status);
+ private native boolean nativePrepareImage(int storageId,
+ Collection<InstallationFile> addedFiles, Collection<String> removedFiles);
+
+ private static native void nativeWriteData(long nativeInstance, String name, long offsetBytes,
+ long lengthBytes, ParcelFileDescriptor incomingFd);
+
}
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index 51a9c864ee29..7841f991c4bc 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -24,7 +24,6 @@ import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Binder;
import android.os.Build;
-import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
@@ -319,10 +318,8 @@ public class PhoneStateListener {
* Listen for call disconnect causes which contains {@link DisconnectCause} and
* {@link PreciseDisconnectCause}.
*
- * @hide
*/
@RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
- @SystemApi
public static final int LISTEN_CALL_DISCONNECT_CAUSES = 0x02000000;
/**
@@ -342,10 +339,8 @@ public class PhoneStateListener {
* {@link android.telephony.ims.ImsReasonInfo}
*
* @see #onImsCallDisconnectCauseChanged(ImsReasonInfo)
- * @hide
*/
@RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
- @SystemApi
public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 0x08000000;
/**
@@ -661,10 +656,8 @@ public class PhoneStateListener {
* @param disconnectCause {@link DisconnectCause}.
* @param preciseDisconnectCause {@link PreciseDisconnectCause}.
*
- * @hide
*/
@RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
- @SystemApi
public void onCallDisconnectCauseChanged(int disconnectCause, int preciseDisconnectCause) {
// default implementation empty
}
@@ -680,10 +673,8 @@ public class PhoneStateListener {
*
* @param imsReasonInfo {@link ImsReasonInfo} contains details on why IMS call failed.
*
- * @hide
*/
@RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
- @SystemApi
public void onImsCallDisconnectCauseChanged(@NonNull ImsReasonInfo imsReasonInfo) {
// default implementation empty
}
@@ -911,8 +902,7 @@ public class PhoneStateListener {
* subId. Otherwise, this callback applies to
* {@link SubscriptionManager#getDefaultSubscriptionId()}.
*
- * Requires
- * the READ_PRIVILEGED_PHONE_STATE permission.
+ * @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE}
* @param state the modem radio power state
* @hide
*/
@@ -993,8 +983,11 @@ public class PhoneStateListener {
() -> mExecutor.execute(() -> psl.onCallForwardingIndicatorChanged(cfi)));
}
- public void onCellLocationChanged(Bundle bundle) {
- CellLocation location = CellLocation.newFromBundle(bundle);
+ public void onCellLocationChanged(CellIdentity cellIdentity) {
+ // There is no system/public API to create an CellIdentity in system server,
+ // so the server pass a null to indicate an empty initial location.
+ CellLocation location =
+ cellIdentity == null ? CellLocation.getEmpty() : cellIdentity.asCellLocation();
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index f574160e5303..1b2fedad842e 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -22,7 +22,6 @@ import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.content.Context;
import android.os.Binder;
-import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.telephony.Annotation.CallState;
@@ -633,10 +632,14 @@ public class TelephonyRegistryManager {
}
/**
- * TODO change from bundle to CellLocation?
+ * Notify {@link android.telephony.CellLocation} changed.
+ *
+ * <p>To be compatible with {@link TelephonyRegistry}, use {@link CellIdentity} which is
+ * parcelable, and convert to CellLocation in client code.
+ *
* @hide
*/
- public void notifyCellLocation(int subId, Bundle cellLocation) {
+ public void notifyCellLocation(int subId, CellIdentity cellLocation) {
try {
sRegistry.notifyCellLocationForSubscriber(subId, cellLocation);
} catch (RemoteException ex) {
diff --git a/core/java/android/view/RemoteAnimationDefinition.java b/core/java/android/view/RemoteAnimationDefinition.java
index c9bd92ae84ba..5a8ac544e27e 100644
--- a/core/java/android/view/RemoteAnimationDefinition.java
+++ b/core/java/android/view/RemoteAnimationDefinition.java
@@ -22,9 +22,12 @@ import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.app.WindowConfiguration.ActivityType;
import android.compat.annotation.UnsupportedAppUsage;
+import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.RemoteException;
import android.util.ArraySet;
+import android.util.Slog;
import android.util.SparseArray;
import android.view.WindowManager.TransitionType;
@@ -124,6 +127,20 @@ public class RemoteAnimationDefinition implements Parcelable {
}
}
+ /**
+ * Links the death of the runner to the provided death recipient.
+ */
+ public void linkToDeath(IBinder.DeathRecipient deathRecipient) {
+ try {
+ for (int i = 0; i < mTransitionAnimationMap.size(); i++) {
+ mTransitionAnimationMap.valueAt(i).adapter.getRunner().asBinder()
+ .linkToDeath(deathRecipient, 0 /* flags */);
+ }
+ } catch (RemoteException e) {
+ Slog.e("RemoteAnimationDefinition", "Failed to link to death recipient");
+ }
+ }
+
@Override
public int describeContents() {
return 0;
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 93cc626b51a7..c566eaefa0aa 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -158,11 +158,10 @@ public final class SurfaceControl implements Parcelable {
IBinder displayToken, long numFrames, long timestamp);
private static native int nativeGetActiveConfig(IBinder displayToken);
private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
- private static native boolean nativeSetAllowedDisplayConfigs(IBinder displayToken,
- int[] allowedConfigs);
- private static native int[] nativeGetAllowedDisplayConfigs(IBinder displayToken);
private static native boolean nativeSetDesiredDisplayConfigSpecs(IBinder displayToken,
SurfaceControl.DesiredDisplayConfigSpecs desiredDisplayConfigSpecs);
+ private static native SurfaceControl.DesiredDisplayConfigSpecs
+ nativeGetDesiredDisplayConfigSpecs(IBinder displayToken);
private static native int[] nativeGetDisplayColorModes(IBinder displayToken);
private static native SurfaceControl.DisplayPrimaries nativeGetDisplayNativePrimaries(
IBinder displayToken);
@@ -1474,58 +1473,60 @@ public final class SurfaceControl implements Parcelable {
}
/**
+ * Contains information about desired display configuration.
+ *
* @hide
*/
- public static boolean setAllowedDisplayConfigs(IBinder displayToken, int[] allowedConfigs) {
- if (displayToken == null) {
- throw new IllegalArgumentException("displayToken must not be null");
- }
- if (allowedConfigs == null) {
- throw new IllegalArgumentException("allowedConfigs must not be null");
+ public static final class DesiredDisplayConfigSpecs {
+ public int defaultConfig;
+ public float minRefreshRate;
+ public float maxRefreshRate;
+
+ public DesiredDisplayConfigSpecs() {}
+
+ public DesiredDisplayConfigSpecs(DesiredDisplayConfigSpecs other) {
+ copyFrom(other);
}
- return nativeSetAllowedDisplayConfigs(displayToken, allowedConfigs);
- }
+ public DesiredDisplayConfigSpecs(
+ int defaultConfig, float minRefreshRate, float maxRefreshRate) {
+ this.defaultConfig = defaultConfig;
+ this.minRefreshRate = minRefreshRate;
+ this.maxRefreshRate = maxRefreshRate;
+ }
- /**
- * @hide
- */
- public static int[] getAllowedDisplayConfigs(IBinder displayToken) {
- if (displayToken == null) {
- throw new IllegalArgumentException("displayToken must not be null");
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof DesiredDisplayConfigSpecs && equals((DesiredDisplayConfigSpecs) o);
}
- return nativeGetAllowedDisplayConfigs(displayToken);
- }
- /**
- * Contains information about desired display configuration.
- *
- * @hide
- */
- public static final class DesiredDisplayConfigSpecs {
/**
- * @hide
+ * Tests for equality.
*/
- public int mDefaultModeId;
+ public boolean equals(DesiredDisplayConfigSpecs other) {
+ return other != null && defaultConfig == other.defaultConfig
+ && minRefreshRate == other.minRefreshRate
+ && maxRefreshRate == other.maxRefreshRate;
+ }
- /**
- * @hide
- */
- public float mMinRefreshRate;
+ @Override
+ public int hashCode() {
+ return 0; // don't care
+ }
/**
- * @hide
+ * Copies the supplied object's values to this object.
*/
- public float mMaxRefreshRate;
+ public void copyFrom(DesiredDisplayConfigSpecs other) {
+ defaultConfig = other.defaultConfig;
+ minRefreshRate = other.minRefreshRate;
+ maxRefreshRate = other.maxRefreshRate;
+ }
- /**
- * @hide
- */
- public DesiredDisplayConfigSpecs(
- int defaultModeId, float minRefreshRate, float maxRefreshRate) {
- mDefaultModeId = defaultModeId;
- mMinRefreshRate = minRefreshRate;
- mMaxRefreshRate = maxRefreshRate;
+ @Override
+ public String toString() {
+ return String.format("defaultConfig=%d min=%.0f max=%.0f", defaultConfig,
+ minRefreshRate, maxRefreshRate);
}
}
@@ -1544,6 +1545,18 @@ public final class SurfaceControl implements Parcelable {
/**
* @hide
*/
+ public static SurfaceControl.DesiredDisplayConfigSpecs getDesiredDisplayConfigSpecs(
+ IBinder displayToken) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+
+ return nativeGetDesiredDisplayConfigSpecs(displayToken);
+ }
+
+ /**
+ * @hide
+ */
public static int[] getDisplayColorModes(IBinder displayToken) {
if (displayToken == null) {
throw new IllegalArgumentException("displayToken must not be null");
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1a5b3e58f576..0db80e2749c3 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6162,10 +6162,27 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mRenderNode = RenderNode.create(getClass().getName(), new ViewAnimationHostBridge(this));
}
- final boolean debugDraw() {
+ /**
+ * Returns {@code true} when the View is attached and the system developer setting to show
+ * the layout bounds is enabled or {@code false} otherwise.
+ */
+ public final boolean isShowingLayoutBounds() {
return DEBUG_DRAW || mAttachInfo != null && mAttachInfo.mDebugLayout;
}
+ /**
+ * Used to test isShowingLayoutBounds(). This sets the local value used
+ * by that function. This method does nothing if the layout isn't attached.
+ *
+ * @hide
+ */
+ @TestApi
+ public final void setShowingLayoutBounds(boolean debugLayout) {
+ if (mAttachInfo != null) {
+ mAttachInfo.mDebugLayout = debugLayout;
+ }
+ }
+
private static SparseArray<String> getAttributeMap() {
if (mAttributeMap == null) {
mAttributeMap = new SparseArray<>();
@@ -20881,7 +20898,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mOverlay != null && !mOverlay.isEmpty()) {
mOverlay.getOverlayView().draw(canvas);
}
- if (debugDraw()) {
+ if (isShowingLayoutBounds()) {
debugDrawFocus(canvas);
}
} else {
@@ -22026,7 +22043,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Step 7, draw the default focus highlight
drawDefaultFocusHighlight(canvas);
- if (debugDraw()) {
+ if (isShowingLayoutBounds()) {
debugDrawFocus(canvas);
}
@@ -22201,7 +22218,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Step 6, draw decorations (foreground, scrollbars)
onDrawForeground(canvas);
- if (debugDraw()) {
+ if (isShowingLayoutBounds()) {
debugDrawFocus(canvas);
}
}
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 21e9e3185066..5fb71773db8f 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -681,7 +681,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
private void initViewGroup() {
// ViewGroup doesn't draw by default
- if (!debugDraw()) {
+ if (!isShowingLayoutBounds()) {
setFlags(WILL_NOT_DRAW, DRAW_MASK);
}
mGroupFlags |= FLAG_CLIP_CHILDREN;
@@ -4156,7 +4156,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
if (usingRenderNodeProperties) canvas.insertInorderBarrier();
- if (debugDraw()) {
+ if (isShowingLayoutBounds()) {
onDebugDraw(canvas);
}
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index 237d1a9e7838..1aa2aeccc0db 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -42,6 +42,7 @@ import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -110,7 +111,6 @@ public final class TextLinks implements Parcelable {
/**
* Returns the text that was used to generate these links.
- * @hide
*/
@NonNull
public String getText() {
@@ -342,6 +342,7 @@ public final class TextLinks implements Parcelable {
private final boolean mLegacyFallback;
@Nullable private String mCallingPackageName;
private final Bundle mExtras;
+ @Nullable private final ZonedDateTime mReferenceTime;
@UserIdInt
private int mUserId = UserHandle.USER_NULL;
@@ -350,11 +351,13 @@ public final class TextLinks implements Parcelable {
LocaleList defaultLocales,
EntityConfig entityConfig,
boolean legacyFallback,
+ ZonedDateTime referenceTime,
Bundle extras) {
mText = text;
mDefaultLocales = defaultLocales;
mEntityConfig = entityConfig;
mLegacyFallback = legacyFallback;
+ mReferenceTime = referenceTime;
mExtras = extras;
}
@@ -395,6 +398,15 @@ public final class TextLinks implements Parcelable {
}
/**
+ * @return reference time based on which relative dates (e.g. "tomorrow") should be
+ * interpreted.
+ */
+ @Nullable
+ public ZonedDateTime getReferenceTime() {
+ return mReferenceTime;
+ }
+
+ /**
* Sets the name of the package that is sending this request.
* <p>
* Package-private for SystemTextClassifier's use.
@@ -454,6 +466,7 @@ public final class TextLinks implements Parcelable {
@Nullable private EntityConfig mEntityConfig;
private boolean mLegacyFallback = true; // Use legacy fall back by default.
@Nullable private Bundle mExtras;
+ @Nullable private ZonedDateTime mReferenceTime;
public Builder(@NonNull CharSequence text) {
mText = Objects.requireNonNull(text);
@@ -511,13 +524,26 @@ public final class TextLinks implements Parcelable {
}
/**
+ * @param referenceTime reference time based on which relative dates (e.g. "tomorrow"
+ * should be interpreted. This should usually be the time when the text was
+ * originally composed.
+ *
+ * @return this builder
+ */
+ @NonNull
+ public Builder setReferenceTime(@Nullable ZonedDateTime referenceTime) {
+ mReferenceTime = referenceTime;
+ return this;
+ }
+
+ /**
* Builds and returns the request object.
*/
@NonNull
public Request build() {
return new Request(
mText, mDefaultLocales, mEntityConfig,
- mLegacyFallback,
+ mLegacyFallback, mReferenceTime,
mExtras == null ? Bundle.EMPTY : mExtras);
}
}
@@ -535,6 +561,7 @@ public final class TextLinks implements Parcelable {
dest.writeString(mCallingPackageName);
dest.writeInt(mUserId);
dest.writeBundle(mExtras);
+ dest.writeString(mReferenceTime == null ? null : mReferenceTime.toString());
}
private static Request readFromParcel(Parcel in) {
@@ -544,9 +571,12 @@ public final class TextLinks implements Parcelable {
final String callingPackageName = in.readString();
final int userId = in.readInt();
final Bundle extras = in.readBundle();
+ final String referenceTimeString = in.readString();
+ final ZonedDateTime referenceTime = referenceTimeString == null
+ ? null : ZonedDateTime.parse(referenceTimeString);
final Request request = new Request(text, defaultLocales, entityConfig,
- /* legacyFallback= */ true, extras);
+ /* legacyFallback= */ true, referenceTime, extras);
request.setCallingPackageName(callingPackageName);
request.setUserId(userId);
return request;
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 246a92cc6e1c..a86b56602efc 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -120,7 +120,6 @@ import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.content.PackageMonitor;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.util.ImageUtils;
import com.android.internal.widget.GridLayoutManager;
import com.android.internal.widget.RecyclerView;
import com.android.internal.widget.ResolverDrawerLayout;
@@ -345,7 +344,9 @@ public class ChooserActivity extends ResolverActivity implements
mHandler.sendEmptyMessageDelayed(IMAGE_LOAD_TIMEOUT, mImageLoadTimeoutMillis);
AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
- final Bitmap bmp = loadThumbnail(uri, new Size(200, 200));
+ int size = getResources().getDimensionPixelSize(
+ R.dimen.chooser_preview_image_max_dimen);
+ final Bitmap bmp = loadThumbnail(uri, new Size(size, size));
final Message msg = Message.obtain();
msg.what = IMAGE_LOAD_INTO_VIEW;
msg.obj = new LoadUriTask(imageResourceId, uri, extraImages, bmp);
@@ -1438,20 +1439,22 @@ public class ChooserActivity extends ResolverActivity implements
final long selectionCost = System.currentTimeMillis() - mChooserShownTime;
- // Stacked apps get a disambiguation first
if (targetInfo instanceof MultiDisplayResolveInfo) {
MultiDisplayResolveInfo mti = (MultiDisplayResolveInfo) targetInfo;
- CharSequence[] labels = new CharSequence[mti.getTargets().size()];
- int i = 0;
- for (TargetInfo ti : mti.getTargets()) {
- labels[i++] = ti.getResolveInfo().loadLabel(getPackageManager());
- }
- ChooserStackedAppDialogFragment f = new ChooserStackedAppDialogFragment(
- targetInfo.getDisplayLabel(),
- ((MultiDisplayResolveInfo) targetInfo).getTargets(), labels);
+ if (!mti.hasSelected()) {
+ // Stacked apps get a disambiguation first
+ CharSequence[] labels = new CharSequence[mti.getTargets().size()];
+ int i = 0;
+ for (TargetInfo ti : mti.getTargets()) {
+ labels[i++] = ti.getResolveInfo().loadLabel(getPackageManager());
+ }
+ ChooserStackedAppDialogFragment f = new ChooserStackedAppDialogFragment(
+ targetInfo.getDisplayLabel(),
+ ((MultiDisplayResolveInfo) targetInfo), labels, which);
- f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG);
- return;
+ f.show(getFragmentManager(), TARGET_DETAILS_FRAGMENT_TAG);
+ return;
+ }
}
super.startSelected(which, always, filtered);
@@ -2127,7 +2130,7 @@ public class ChooserActivity extends ResolverActivity implements
}
try {
- return ImageUtils.loadThumbnail(getContentResolver(), uri, size);
+ return getContentResolver().loadThumbnail(uri, size, null);
} catch (IOException | NullPointerException | SecurityException ex) {
logContentPreviewWarning(uri);
}
diff --git a/core/java/com/android/internal/app/ChooserStackedAppDialogFragment.java b/core/java/com/android/internal/app/ChooserStackedAppDialogFragment.java
index ff6582d10535..f4c69a51ece1 100644
--- a/core/java/com/android/internal/app/ChooserStackedAppDialogFragment.java
+++ b/core/java/com/android/internal/app/ChooserStackedAppDialogFragment.java
@@ -24,10 +24,7 @@ import android.content.DialogInterface;
import android.content.res.Configuration;
import android.os.Bundle;
-import com.android.internal.app.chooser.DisplayResolveInfo;
-
-import java.util.ArrayList;
-import java.util.List;
+import com.android.internal.app.chooser.MultiDisplayResolveInfo;
/**
* Shows individual actions for a "stacked" app target - such as an app with multiple posting
@@ -38,24 +35,20 @@ public class ChooserStackedAppDialogFragment extends DialogFragment
private static final String TITLE_KEY = "title";
private static final String PINNED_KEY = "pinned";
- private List<DisplayResolveInfo> mTargetInfos = new ArrayList<>();
+ private MultiDisplayResolveInfo mTargetInfos;
private CharSequence[] mLabels;
+ private int mParentWhich;
public ChooserStackedAppDialogFragment() {
}
- public ChooserStackedAppDialogFragment(CharSequence title) {
- Bundle args = new Bundle();
- args.putCharSequence(TITLE_KEY, title);
- setArguments(args);
- }
-
public ChooserStackedAppDialogFragment(CharSequence title,
- List<DisplayResolveInfo> targets, CharSequence[] labels) {
+ MultiDisplayResolveInfo targets, CharSequence[] labels, int parentWhich) {
Bundle args = new Bundle();
args.putCharSequence(TITLE_KEY, title);
mTargetInfos = targets;
mLabels = labels;
+ mParentWhich = parentWhich;
setArguments(args);
}
@@ -72,7 +65,8 @@ public class ChooserStackedAppDialogFragment extends DialogFragment
@Override
public void onClick(DialogInterface dialog, int which) {
final Bundle args = getArguments();
- mTargetInfos.get(which).start(getActivity(), null);
+ mTargetInfos.setSelected(which);
+ ((ChooserActivity) getActivity()).startSelected(mParentWhich, false, true);
dismiss();
}
diff --git a/core/java/com/android/internal/app/SuspendedAppActivity.java b/core/java/com/android/internal/app/SuspendedAppActivity.java
index 33b2113b0674..c610ac4503c9 100644
--- a/core/java/com/android/internal/app/SuspendedAppActivity.java
+++ b/core/java/com/android/internal/app/SuspendedAppActivity.java
@@ -45,12 +45,14 @@ public class SuspendedAppActivity extends AlertActivity
public static final String EXTRA_SUSPENDING_PACKAGE =
PACKAGE_NAME + ".extra.SUSPENDING_PACKAGE";
public static final String EXTRA_DIALOG_INFO = PACKAGE_NAME + ".extra.DIALOG_INFO";
+ public static final String EXTRA_ACTIVITY_OPTIONS = PACKAGE_NAME + ".extra.ACTIVITY_OPTIONS";
private Intent mMoreDetailsIntent;
private int mUserId;
private PackageManager mPm;
private Resources mSuspendingAppResources;
private SuspendDialogInfo mSuppliedDialogInfo;
+ private Bundle mOptions;
private CharSequence getAppLabel(String packageName) {
try {
@@ -143,6 +145,7 @@ public class SuspendedAppActivity extends AlertActivity
getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
final Intent intent = getIntent();
+ mOptions = intent.getBundleExtra(EXTRA_ACTIVITY_OPTIONS);
mUserId = intent.getIntExtra(Intent.EXTRA_USER_ID, -1);
if (mUserId < 0) {
Slog.wtf(TAG, "Invalid user: " + mUserId);
@@ -178,20 +181,22 @@ public class SuspendedAppActivity extends AlertActivity
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case AlertDialog.BUTTON_NEUTRAL:
- startActivityAsUser(mMoreDetailsIntent, UserHandle.of(mUserId));
- Slog.i(TAG, "Started more details activity");
+ startActivityAsUser(mMoreDetailsIntent, mOptions, UserHandle.of(mUserId));
+ Slog.i(TAG, "Started activity: " + mMoreDetailsIntent.getAction()
+ + " in user " + mUserId);
break;
}
finish();
}
public static Intent createSuspendedAppInterceptIntent(String suspendedPackage,
- String suspendingPackage, SuspendDialogInfo dialogInfo, int userId) {
+ String suspendingPackage, SuspendDialogInfo dialogInfo, Bundle options, int userId) {
return new Intent()
.setClassName("android", SuspendedAppActivity.class.getName())
.putExtra(EXTRA_SUSPENDED_PACKAGE, suspendedPackage)
.putExtra(EXTRA_DIALOG_INFO, dialogInfo)
.putExtra(EXTRA_SUSPENDING_PACKAGE, suspendingPackage)
+ .putExtra(EXTRA_ACTIVITY_OPTIONS, options)
.putExtra(Intent.EXTRA_USER_ID, userId)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
diff --git a/core/java/com/android/internal/app/chooser/MultiDisplayResolveInfo.java b/core/java/com/android/internal/app/chooser/MultiDisplayResolveInfo.java
index 55200c8d9d20..e58258352106 100644
--- a/core/java/com/android/internal/app/chooser/MultiDisplayResolveInfo.java
+++ b/core/java/com/android/internal/app/chooser/MultiDisplayResolveInfo.java
@@ -16,6 +16,12 @@
package com.android.internal.app.chooser;
+import android.app.Activity;
+import android.os.Bundle;
+import android.os.UserHandle;
+
+import com.android.internal.app.ResolverActivity;
+
import java.util.ArrayList;
import java.util.List;
@@ -27,6 +33,8 @@ public class MultiDisplayResolveInfo extends DisplayResolveInfo {
List<DisplayResolveInfo> mTargetInfos = new ArrayList<>();
// We'll use this DRI for basic presentation info - eg icon, name.
final DisplayResolveInfo mBaseInfo;
+ // Index of selected target
+ private int mSelected = -1;
/**
* @param firstInfo A representative DRI to use for the main icon, title, etc for this Info.
@@ -57,4 +65,30 @@ public class MultiDisplayResolveInfo extends DisplayResolveInfo {
return mTargetInfos;
}
+ public void setSelected(int selected) {
+ mSelected = selected;
+ }
+
+ /**
+ * Whether or not the user has selected a specific target for this MultiInfo.
+ */
+ public boolean hasSelected() {
+ return mSelected >= 0;
+ }
+
+ @Override
+ public boolean start(Activity activity, Bundle options) {
+ return mTargetInfos.get(mSelected).start(activity, options);
+ }
+
+ @Override
+ public boolean startAsCaller(ResolverActivity activity, Bundle options, int userId) {
+ return mTargetInfos.get(mSelected).startAsCaller(activity, options, userId);
+ }
+
+ @Override
+ public boolean startAsUser(Activity activity, Bundle options, UserHandle user) {
+ return mTargetInfos.get(mSelected).startAsUser(activity, options, user);
+ }
+
}
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index dec9ae701fb2..221cd6d8a5c3 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -66,6 +66,7 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.regex.Pattern;
/**
* A helper class for {@link android.provider.DocumentsProvider} to perform file operations on local
@@ -388,7 +389,9 @@ public abstract class FileSystemProvider extends DocumentsProvider {
resolveProjection(projection), parentDocumentId, parent);
if (parent.isDirectory()) {
for (File file : FileUtils.listFilesOrEmpty(parent)) {
- includeFile(result, null, file);
+ if (!shouldHide(file)) {
+ includeFile(result, null, file);
+ }
}
} else {
Log.w(TAG, "parentDocumentId '" + parentDocumentId + "' is not Directory");
@@ -422,6 +425,8 @@ public abstract class FileSystemProvider extends DocumentsProvider {
pending.add(folder);
while (!pending.isEmpty() && result.getCount() < 24) {
final File file = pending.removeFirst();
+ if (shouldHide(file)) continue;
+
if (file.isDirectory()) {
for (File child : file.listFiles()) {
pending.add(child);
@@ -540,6 +545,7 @@ public abstract class FileSystemProvider extends DocumentsProvider {
} else {
file = getFileForDocId(docId);
}
+
final String mimeType = getDocumentType(docId, file);
row.add(Document.COLUMN_DOCUMENT_ID, docId);
row.add(Document.COLUMN_MIME_TYPE, mimeType);
@@ -598,6 +604,17 @@ public abstract class FileSystemProvider extends DocumentsProvider {
return row;
}
+ private static final Pattern PATTERN_HIDDEN_PATH = Pattern.compile(
+ "(?i)^/storage/[^/]+/(?:[0-9]+/)?Android/(?:data|obb|sandbox)$");
+
+ /**
+ * In a scoped storage world, access to "Android/data" style directories are
+ * hidden for privacy reasons.
+ */
+ protected boolean shouldHide(@NonNull File file) {
+ return (PATTERN_HIDDEN_PATH.matcher(file.getAbsolutePath()).matches());
+ }
+
protected boolean shouldBlockFromTree(@NonNull String docId) {
return false;
}
diff --git a/core/java/com/android/internal/infra/AndroidFuture.aidl b/core/java/com/android/internal/infra/AndroidFuture.aidl
index b19aab8ab0d5..5f623b183168 100644
--- a/core/java/com/android/internal/infra/AndroidFuture.aidl
+++ b/core/java/com/android/internal/infra/AndroidFuture.aidl
@@ -17,4 +17,4 @@
package com.android.internal.infra;
/** @hide */
-parcelable AndroidFuture;
+parcelable AndroidFuture<T>;
diff --git a/core/java/com/android/internal/infra/PerUser.java b/core/java/com/android/internal/infra/PerUser.java
new file mode 100644
index 000000000000..560ca8cff8df
--- /dev/null
+++ b/core/java/com/android/internal/infra/PerUser.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.infra;
+
+import android.annotation.NonNull;
+import android.util.SparseArray;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * A {@link SparseArray} customized for a common use-case of storing state per-user.
+ *
+ * Unlike a normal {@link SparseArray} this will always create a value on {@link #get} if one is
+ * not present instead of returning null.
+ *
+ * @param <T> user state type
+ */
+public abstract class PerUser<T> extends SparseArray<T> {
+
+ /**
+ * Initialize state for the given user
+ */
+ protected abstract @NonNull T create(int userId);
+
+ /**
+ * Same as {@link #get(int)}, renamed for readability.
+ *
+ * This will never return null, deferring to {@link #create} instead
+ * when called for the first time.
+ */
+ public @NonNull T forUser(int userId) {
+ return get(userId);
+ }
+
+ @Override
+ public @NonNull T get(int userId) {
+ T userState = super.get(userId);
+ if (userState != null) {
+ return userState;
+ } else {
+ userState = Preconditions.checkNotNull(create(userId));
+ put(userId, userState);
+ return userState;
+ }
+ }
+}
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index c390a518bb22..2248b8853f8c 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -316,7 +316,9 @@ public final class Zygote {
* @param appDataDir null-ok The data directory of the app.
* @param isTopApp True if the process is for top (high priority) application.
* @param pkgDataInfoList A list that stores related packages and its app data
- * info: volume uuid and inode.
+ * volume uuid and CE dir inode. For example, pkgDataInfoList = [app_a_pkg_name,
+ * app_a_data_volume_uuid, app_a_ce_inode, app_b_pkg_name, app_b_data_volume_uuid,
+ * app_b_ce_inode, ...];
*/
private static void specializeAppProcess(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName,
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index cb67309ce74f..6c7e3dc84425 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -16,8 +16,8 @@
package com.android.internal.telephony;
-import android.os.Bundle;
import android.telephony.CallAttributes;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.PhoneCapability;
@@ -37,8 +37,8 @@ oneway interface IPhoneStateListener {
void onMessageWaitingIndicatorChanged(boolean mwi);
void onCallForwardingIndicatorChanged(boolean cfi);
- // we use bundle here instead of CellLocation so it can get the right subclass
- void onCellLocationChanged(in Bundle location);
+ // Uses CellIdentity which is Parcelable here; will convert to CellLocation in client.
+ void onCellLocationChanged(in CellIdentity location);
void onCallStateChanged(int state, String incomingNumber);
void onDataConnectionStateChanged(int state, int networkType);
void onDataActivity(int direction);
@@ -63,4 +63,3 @@ oneway interface IPhoneStateListener {
void onCallDisconnectCauseChanged(in int disconnectCause, in int preciseDisconnectCause);
void onImsCallDisconnectCauseChanged(in ImsReasonInfo imsReasonInfo);
}
-
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index f954679ebf4d..4e405037f6ef 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -19,8 +19,8 @@ package com.android.internal.telephony;
import android.content.Intent;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
-import android.os.Bundle;
import android.telephony.CallQuality;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.PhoneCapability;
@@ -66,9 +66,9 @@ interface ITelephonyRegistry {
int phoneId, int subId, String apnType, in PreciseDataConnectionState preciseState);
@UnsupportedAppUsage
void notifyDataConnectionFailed(String apnType);
- @UnsupportedAppUsage(maxTargetSdk = 28)
- void notifyCellLocation(in Bundle cellLocation);
- void notifyCellLocationForSubscriber(in int subId, in Bundle cellLocation);
+ // Uses CellIdentity which is Parcelable here; will convert to CellLocation in client.
+ void notifyCellLocation(in CellIdentity cellLocation);
+ void notifyCellLocationForSubscriber(in int subId, in CellIdentity cellLocation);
@UnsupportedAppUsage
void notifyCellInfo(in List<CellInfo> cellInfo);
void notifyPreciseCallState(int phoneId, int subId, int ringingCallState,
diff --git a/core/java/com/android/internal/util/FunctionalUtils.java b/core/java/com/android/internal/util/FunctionalUtils.java
index b955f672fe93..3c9791791a68 100644
--- a/core/java/com/android/internal/util/FunctionalUtils.java
+++ b/core/java/com/android/internal/util/FunctionalUtils.java
@@ -19,6 +19,7 @@ package com.android.internal.util;
import android.os.RemoteException;
import android.util.ExceptionUtils;
+import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -54,6 +55,13 @@ public class FunctionalUtils {
/**
* @see #uncheckExceptions(ThrowingConsumer)
*/
+ public static <A, B> BiConsumer<A, B> uncheckExceptions(ThrowingBiConsumer<A, B> action) {
+ return action;
+ }
+
+ /**
+ * @see #uncheckExceptions(ThrowingConsumer)
+ */
public static <T> Supplier<T> uncheckExceptions(ThrowingSupplier<T> action) {
return action;
}
@@ -185,4 +193,29 @@ public class FunctionalUtils {
}
}
}
+
+ /**
+ * A {@link BiConsumer} that allows throwing checked exceptions from its single abstract method.
+ *
+ * Can be used together with {@link #uncheckExceptions} to effectively turn a lambda expression
+ * that throws a checked exception into a regular {@link Function}
+ *
+ * @param <A> see {@link BiConsumer}
+ * @param <B> see {@link BiConsumer}
+ */
+ @FunctionalInterface
+ @SuppressWarnings("FunctionalInterfaceMethodChanged")
+ public interface ThrowingBiConsumer<A, B> extends BiConsumer<A, B> {
+ /** @see ThrowingFunction */
+ void acceptOrThrow(A a, B b) throws Exception;
+
+ @Override
+ default void accept(A a, B b) {
+ try {
+ acceptOrThrow(a, b);
+ } catch (Exception ex) {
+ throw ExceptionUtils.propagate(ex);
+ }
+ }
+ }
}
diff --git a/core/jni/android_media_AudioFormat.h b/core/jni/android_media_AudioFormat.h
index 99b5f8592e5d..a3c455bfc111 100644
--- a/core/jni/android_media_AudioFormat.h
+++ b/core/jni/android_media_AudioFormat.h
@@ -38,6 +38,7 @@
#define ENCODING_AC4 17
#define ENCODING_E_AC3_JOC 18
#define ENCODING_DOLBY_MAT 19
+#define ENCODING_OPUS 20
#define ENCODING_INVALID 0
#define ENCODING_DEFAULT 1
@@ -88,6 +89,8 @@ static inline audio_format_t audioFormatToNative(int audioFormat)
return AUDIO_FORMAT_DEFAULT;
case ENCODING_DOLBY_MAT:
return AUDIO_FORMAT_MAT;
+ case ENCODING_OPUS:
+ return AUDIO_FORMAT_OPUS;
default:
return AUDIO_FORMAT_INVALID;
}
@@ -142,6 +145,8 @@ static inline int audioFormatFromNative(audio_format_t nativeFormat)
case AUDIO_FORMAT_MAT_2_0:
case AUDIO_FORMAT_MAT_2_1:
return ENCODING_DOLBY_MAT;
+ case AUDIO_FORMAT_OPUS:
+ return ENCODING_OPUS;
case AUDIO_FORMAT_DEFAULT:
return ENCODING_DEFAULT;
default:
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index e21eefb196c9..6e0d5d8f6461 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -828,7 +828,7 @@ static jlong android_os_Debug_getIonMappedSizeKb(JNIEnv* env, jobject clazz) {
}
}
- for (dmabufinfo::DmaBuffer buf : dmabufs) {
+ for (const dmabufinfo::DmaBuffer& buf : dmabufs) {
ionPss += buf.size() / 1024;
}
diff --git a/core/jni/android_service_DataLoaderService.cpp b/core/jni/android_service_DataLoaderService.cpp
index 381b386d7f62..a62d127a968f 100644
--- a/core/jni/android_service_DataLoaderService.cpp
+++ b/core/jni/android_service_DataLoaderService.cpp
@@ -51,13 +51,19 @@ static jboolean nativeDestroyDataLoader(JNIEnv* env,
}
-static jboolean nativeReportStatus(JNIEnv* env,
- jobject clazz,
- jlong self,
- jint status) {
- auto listener = (DataLoaderStatusListenerPtr)self;
- return DataLoader_StatusListener_reportStatus(listener,
- (DataLoaderStatus)status);
+static jboolean nativePrepareImage(JNIEnv* env, jobject thiz, jint storageId, jobject addedFiles, jobject removedFiles) {
+ return DataLoaderService_OnPrepareImage(storageId, addedFiles, removedFiles);
+}
+
+static void nativeWriteData(JNIEnv* env,
+ jobject clazz,
+ jlong self,
+ jstring name,
+ jlong offsetBytes,
+ jlong lengthBytes,
+ jobject incomingFd) {
+ auto connector = (DataLoaderFilesystemConnectorPtr)self;
+ return DataLoader_FilesystemConnector_writeData(connector, name, offsetBytes, lengthBytes, incomingFd);
}
static const JNINativeMethod dlc_method_table[] = {
@@ -69,7 +75,8 @@ static const JNINativeMethod dlc_method_table[] = {
{"nativeStartDataLoader", "(I)Z", (void*)nativeStartDataLoader},
{"nativeStopDataLoader", "(I)Z", (void*)nativeStopDataLoader},
{"nativeDestroyDataLoader", "(I)Z", (void*)nativeDestroyDataLoader},
- {"nativeReportStatus", "(JI)Z", (void*)nativeReportStatus},
+ {"nativePrepareImage", "(ILjava/util/Collection;Ljava/util/Collection;)Z", (void*)nativePrepareImage},
+ {"nativeWriteData", "(JLjava/lang/String;JJLandroid/os/ParcelFileDescriptor;)V", (void*)nativeWriteData},
};
} // namespace
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index c6e678ab50b0..33da34d809eb 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -141,7 +141,7 @@ static struct {
static struct {
jclass clazz;
jmethodID ctor;
- jfieldID defaultModeId;
+ jfieldID defaultConfig;
jfieldID minRefreshRate;
jfieldID maxRefreshRate;
} gDesiredDisplayConfigSpecsClassInfo;
@@ -776,65 +776,40 @@ static jobjectArray nativeGetDisplayConfigs(JNIEnv* env, jclass clazz,
return configArray;
}
-static jboolean nativeSetAllowedDisplayConfigs(JNIEnv* env, jclass clazz,
- jobject tokenObj, jintArray configArray) {
- sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
- if (token == nullptr) return JNI_FALSE;
-
- std::vector<int32_t> allowedConfigs;
- jsize configArraySize = env->GetArrayLength(configArray);
- allowedConfigs.reserve(configArraySize);
-
- jint* configArrayElements = env->GetIntArrayElements(configArray, 0);
- for (int i = 0; i < configArraySize; i++) {
- allowedConfigs.push_back(configArrayElements[i]);
- }
- env->ReleaseIntArrayElements(configArray, configArrayElements, 0);
-
- size_t result = SurfaceComposerClient::setAllowedDisplayConfigs(token, allowedConfigs);
- return result == NO_ERROR ? JNI_TRUE : JNI_FALSE;
-}
-
-static jintArray nativeGetAllowedDisplayConfigs(JNIEnv* env, jclass clazz, jobject tokenObj) {
- sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
- if (token == nullptr) return JNI_FALSE;
-
- std::vector<int32_t> allowedConfigs;
- size_t result = SurfaceComposerClient::getAllowedDisplayConfigs(token, &allowedConfigs);
- if (result != NO_ERROR) {
- return nullptr;
- }
-
- jintArray allowedConfigsArray = env->NewIntArray(allowedConfigs.size());
- if (allowedConfigsArray == nullptr) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
- return nullptr;
- }
- jint* allowedConfigsArrayValues = env->GetIntArrayElements(allowedConfigsArray, 0);
- for (size_t i = 0; i < allowedConfigs.size(); i++) {
- allowedConfigsArrayValues[i] = static_cast<jint>(allowedConfigs[i]);
- }
- env->ReleaseIntArrayElements(allowedConfigsArray, allowedConfigsArrayValues, 0);
- return allowedConfigsArray;
-}
-
static jboolean nativeSetDesiredDisplayConfigSpecs(JNIEnv* env, jclass clazz, jobject tokenObj,
jobject desiredDisplayConfigSpecs) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
if (token == nullptr) return JNI_FALSE;
- jint defaultModeId = env->GetIntField(desiredDisplayConfigSpecs,
- gDesiredDisplayConfigSpecsClassInfo.defaultModeId);
+ jint defaultConfig = env->GetIntField(desiredDisplayConfigSpecs,
+ gDesiredDisplayConfigSpecsClassInfo.defaultConfig);
jfloat minRefreshRate = env->GetFloatField(desiredDisplayConfigSpecs,
gDesiredDisplayConfigSpecsClassInfo.minRefreshRate);
jfloat maxRefreshRate = env->GetFloatField(desiredDisplayConfigSpecs,
gDesiredDisplayConfigSpecsClassInfo.maxRefreshRate);
size_t result = SurfaceComposerClient::setDesiredDisplayConfigSpecs(
- token, defaultModeId, minRefreshRate, maxRefreshRate);
+ token, defaultConfig, minRefreshRate, maxRefreshRate);
return result == NO_ERROR ? JNI_TRUE : JNI_FALSE;
}
+static jobject nativeGetDesiredDisplayConfigSpecs(JNIEnv* env, jclass clazz, jobject tokenObj) {
+ sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+ if (token == nullptr) return nullptr;
+
+ int32_t defaultConfig;
+ float minRefreshRate;
+ float maxRefreshRate;
+ if (SurfaceComposerClient::getDesiredDisplayConfigSpecs(token, &defaultConfig, &minRefreshRate,
+ &maxRefreshRate) != NO_ERROR) {
+ return nullptr;
+ }
+
+ return env->NewObject(gDesiredDisplayConfigSpecsClassInfo.clazz,
+ gDesiredDisplayConfigSpecsClassInfo.ctor, defaultConfig, minRefreshRate,
+ maxRefreshRate);
+}
+
static jint nativeGetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
if (token == NULL) return -1;
@@ -1387,13 +1362,12 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeGetActiveConfig },
{"nativeSetActiveConfig", "(Landroid/os/IBinder;I)Z",
(void*)nativeSetActiveConfig },
- {"nativeSetAllowedDisplayConfigs", "(Landroid/os/IBinder;[I)Z",
- (void*)nativeSetAllowedDisplayConfigs },
- {"nativeGetAllowedDisplayConfigs", "(Landroid/os/IBinder;)[I",
- (void*)nativeGetAllowedDisplayConfigs },
{"nativeSetDesiredDisplayConfigSpecs",
"(Landroid/os/IBinder;Landroid/view/SurfaceControl$DesiredDisplayConfigSpecs;)Z",
(void*)nativeSetDesiredDisplayConfigSpecs },
+ {"nativeGetDesiredDisplayConfigSpecs",
+ "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DesiredDisplayConfigSpecs;",
+ (void*)nativeGetDesiredDisplayConfigSpecs },
{"nativeGetDisplayColorModes", "(Landroid/os/IBinder;)[I",
(void*)nativeGetDisplayColorModes},
{"nativeGetDisplayNativePrimaries", "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DisplayPrimaries;",
@@ -1569,12 +1543,12 @@ int register_android_view_SurfaceControl(JNIEnv* env)
MakeGlobalRefOrDie(env, desiredDisplayConfigSpecsClazz);
gDesiredDisplayConfigSpecsClassInfo.ctor =
GetMethodIDOrDie(env, gDesiredDisplayConfigSpecsClassInfo.clazz, "<init>", "(IFF)V");
- gDesiredDisplayConfigSpecsClassInfo.defaultModeId =
- GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "mDefaultModeId", "I");
+ gDesiredDisplayConfigSpecsClassInfo.defaultConfig =
+ GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "defaultConfig", "I");
gDesiredDisplayConfigSpecsClassInfo.minRefreshRate =
- GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "mMinRefreshRate", "F");
+ GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "minRefreshRate", "F");
gDesiredDisplayConfigSpecsClassInfo.maxRefreshRate =
- GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "mMaxRefreshRate", "F");
+ GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "maxRefreshRate", "F");
return err;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 1165d2d673d5..44a902c830f2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4113,7 +4113,7 @@
<permission android:name="android.permission.INTENT_FILTER_VERIFICATION_AGENT"
android:protectionLevel="signature|privileged" />
- <!-- Must be required by intent filter verifier receiver, to ensure that only the
+ <!-- Must be required by intent filter verifier rintent-filtereceiver, to ensure that only the
system can interact with it.
@hide
-->
@@ -5143,6 +5143,12 @@
android:permission="android.permission.BIND_JOB_SERVICE" >
</service>
-</application>
+ <service android:name="com.android.server.pm.PackageManagerShellCommandDataLoader">
+ <intent-filter>
+ <action android:name="android.intent.action.LOAD_DATA" />
+ </intent-filter>
+ </service>
+
+ </application>
</manifest>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f28f08b8abd1..9073a02e72d3 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3560,13 +3560,14 @@
set to empty string), a default textclassifier will be loaded in the calling app's process.
See android.view.textclassifier.TextClassificationManager.
-->
+ <!-- TODO(b/144896755) remove the config -->
<string name="config_defaultTextClassifierPackage" translatable="false"></string>
- <!-- A list of the default system textclassifier service package name. Only one of the packages
- will be activated and the fist package is the default system textclassifier service. OS
- only tries to bind the first trusted service and the others can be selected via device
- config. These services must be trusted, as they can be activated without explicit consent
- of the user. Example: "com.android.textclassifier"
+ <!-- A list of supported system textClassifier service package names. Only one of the packages
+ will be activated. The first package in the list is the default system textClassifier
+ service. OS only tries to bind and grant permissions to the first trusted service and the
+ others can be selected via device config. These services must be trusted, as they can be
+ activated without explicit consent of the user. Example: "com.android.textclassifier"
-->
<string-array name="config_defaultTextClassifierPackages" translatable="false">
<item>android.ext.services</item>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 2543967be8a8..bf7558c8597a 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -760,6 +760,7 @@
<dimen name="chooser_edge_margin_normal">24dp</dimen>
<dimen name="chooser_preview_image_font_size">20sp</dimen>
<dimen name="chooser_preview_image_border">1dp</dimen>
+ <dimen name="chooser_preview_image_max_dimen">200dp</dimen>
<dimen name="chooser_preview_width">-1px</dimen>
<dimen name="chooser_target_width">90dp</dimen>
<dimen name="chooser_header_scroll_elevation">4dp</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 78c4efec5b72..4bbfeafdfc9c 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3007,8 +3007,6 @@
</public-group>
<public-group type="drawable" first-id="0x010800b5">
- <!-- @hide @SystemApi -->
- <public name="stat_notify_wifi_in_range" />
</public-group>
<public-group type="style" first-id="0x010302e5">
@@ -3019,11 +3017,11 @@
</public-group>
<public-group type="string" first-id="0x01040025">
- <!-- @hide @SystemApi -->
+ <!-- @hide -->
<public name="notification_channel_network_status" />
- <!-- @hide @SystemApi -->
+ <!-- @hide -->
<public name="notification_channel_network_alerts" />
- <!-- @hide @SystemApi -->
+ <!-- @hide -->
<public name="notification_channel_network_available" />
<!-- @hide @SystemApi -->
<public name="config_defaultCallRedirection" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7cf2b784af1b..e82439e5ce34 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1342,6 +1342,7 @@
<java-symbol type="drawable" name="picture_emergency" />
<java-symbol type="drawable" name="platlogo" />
<java-symbol type="drawable" name="stat_notify_sync_error" />
+ <java-symbol type="drawable" name="stat_notify_wifi_in_range" />
<java-symbol type="drawable" name="ic_wifi_signal_0" />
<java-symbol type="drawable" name="ic_wifi_signal_1" />
<java-symbol type="drawable" name="ic_wifi_signal_2" />
@@ -2721,6 +2722,7 @@
<java-symbol type="layout" name="chooser_grid_preview_file" />
<java-symbol type="id" name="chooser_row_text_option" />
<java-symbol type="dimen" name="chooser_row_text_option_translate" />
+ <java-symbol type="dimen" name="chooser_preview_image_max_dimen"/>
<java-symbol type="integer" name="config_maxShortcutTargetsPerApp" />
<java-symbol type="layout" name="resolve_grid_item" />
<java-symbol type="id" name="day_picker_view_pager" />
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
index b9cc8f4ba4a0..ec5813fd4123 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextLinksTest.java
@@ -29,6 +29,9 @@ import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -77,6 +80,7 @@ public class TextLinksTest {
final TextLinks result = TextLinks.CREATOR.createFromParcel(parcel);
final List<TextLinks.TextLink> resultList = new ArrayList<>(result.getLinks());
+ assertEquals(fullText, result.getText());
assertEquals(2, resultList.size());
assertEquals(0, resultList.get(0).getStart());
assertEquals(4, resultList.get(0).getEnd());
@@ -103,10 +107,13 @@ public class TextLinksTest {
Arrays.asList(TextClassifier.HINT_TEXT_IS_EDITABLE),
Arrays.asList("a", "b", "c"),
Arrays.asList("b"));
+ final ZonedDateTime referenceTime = ZonedDateTime.ofInstant(Instant.ofEpochMilli(1000L),
+ ZoneId.of("UTC"));
final TextLinks.Request reference = new TextLinks.Request.Builder("text")
.setDefaultLocales(new LocaleList(Locale.US, Locale.GERMANY))
.setEntityConfig(entityConfig)
.setExtras(BUNDLE)
+ .setReferenceTime(referenceTime)
.build();
reference.setCallingPackageName(packageName);
@@ -124,5 +131,6 @@ public class TextLinksTest {
result.getEntityConfig().resolveEntityListModifications(Collections.emptyList()));
assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
assertEquals(packageName, result.getCallingPackageName());
+ assertEquals(referenceTime, result.getReferenceTime());
}
}
diff --git a/core/tests/overlaytests/device/res/layout/layout.xml b/core/tests/overlaytests/device/res/layout/layout.xml
new file mode 100644
index 000000000000..e12c715a2a32
--- /dev/null
+++ b/core/tests/overlaytests/device/res/layout/layout.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout android:id="@id/view_1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.android.overlaytest.view.TestTextView
+ android:id="@id/view_2"
+ android:layout_width="match_parent"
+ android:layout_height="100dp"
+ app:customAttribute="none"/>
+
+ <com.android.overlaytest.view.TestTextView
+ android:id="@id/view_3"
+ android:layout_width="match_parent"
+ android:layout_height="100dp"
+ app:customAttribute="none" />
+ </LinearLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/core/tests/overlaytests/device/res/values/config.xml b/core/tests/overlaytests/device/res/values/config.xml
index c692a2625199..e918268fa073 100644
--- a/core/tests/overlaytests/device/res/values/config.xml
+++ b/core/tests/overlaytests/device/res/values/config.xml
@@ -56,4 +56,16 @@
<item>17</item>
<item>19</item>
</integer-array>
+
+ <attr name="customAttribute" />
+ <id name="view_1" />
+ <id name="view_2" />
+ <id name="view_3" />
+
+ <!-- Stabilize the ids of attributes and ids used in test layouts so that they differ from the
+ overlay resource ids -->
+ <public type="attr" name="customAttribute" id="0x7f200000"/>
+ <public type="id" name="view_1" id="0x7f210000"/>
+ <public type="id" name="view_2" id="0x7f210001"/>
+ <public type="id" name="view_3" id="0x7f210002"/>
</resources>
diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
index fdb6bbb4550b..636f4c8b59ca 100644
--- a/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
+++ b/core/tests/overlaytests/device/src/com/android/overlaytest/OverlayBaseTest.java
@@ -18,20 +18,26 @@ package com.android.overlaytest;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.LocaleList;
import android.util.AttributeSet;
+import android.util.TypedValue;
import android.util.Xml;
+import android.view.LayoutInflater;
+import android.view.View;
import androidx.test.InstrumentationRegistry;
import com.android.internal.util.ArrayUtils;
+import com.android.overlaytest.view.TestTextView;
import org.junit.Before;
import org.junit.Ignore;
@@ -45,6 +51,7 @@ import java.util.Locale;
@Ignore
public abstract class OverlayBaseTest {
+ private Context mContext;
private Resources mResources;
private final int mMode;
static final int MODE_NO_OVERLAY = 0;
@@ -61,7 +68,8 @@ public abstract class OverlayBaseTest {
@Before
public void setUp() {
- mResources = InstrumentationRegistry.getContext().getResources();
+ mContext = InstrumentationRegistry.getContext();
+ mResources = mContext.getResources();
}
private int calculateRawResourceChecksum(int resId) throws Throwable {
@@ -321,6 +329,50 @@ public abstract class OverlayBaseTest {
assertEquals("com.android.overlaytest", contents);
}
+ @Test
+ public void testRewrite() throws Throwable {
+ final TypedValue result = new TypedValue();
+ mResources.getValue(R.string.str, result, true);
+ assertEquals(result.resourceId & 0xff000000, 0x7f000000);
+ }
+
+ @Test
+ public void testOverlayLayout() throws Throwable {
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ final View layout = inflater.inflate(R.layout.layout, null);
+ assertNotNull(layout.findViewById(R.id.view_1));
+
+ final TestTextView view2 = layout.findViewById(R.id.view_2);
+ assertNotNull(view2);
+ switch (mMode) {
+ case MODE_NO_OVERLAY:
+ assertEquals("none", view2.getCustomAttributeValue());
+ break;
+ case MODE_SINGLE_OVERLAY:
+ assertEquals("single", view2.getCustomAttributeValue());
+ break;
+ case MODE_MULTIPLE_OVERLAYS:
+ assertEquals("multiple", view2.getCustomAttributeValue());
+ break;
+ default:
+ fail("Unknown mode " + mMode);
+ }
+
+ final TestTextView view3 = layout.findViewById(R.id.view_3);
+ assertNotNull(view3);
+ switch (mMode) {
+ case MODE_NO_OVERLAY:
+ assertEquals("none", view3.getCustomAttributeValue());
+ break;
+ case MODE_SINGLE_OVERLAY:
+ case MODE_MULTIPLE_OVERLAYS:
+ assertEquals("overlaid", view3.getCustomAttributeValue());
+ break;
+ default:
+ fail("Unknown mode " + mMode);
+ }
+ }
+
/*
* testMatrix* tests
*
diff --git a/core/tests/overlaytests/device/src/com/android/overlaytest/view/TestTextView.java b/core/tests/overlaytests/device/src/com/android/overlaytest/view/TestTextView.java
new file mode 100644
index 000000000000..2245e2b8121b
--- /dev/null
+++ b/core/tests/overlaytests/device/src/com/android/overlaytest/view/TestTextView.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.overlaytest.view;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+public class TestTextView extends TextView {
+
+ private final String mCustomAttributeValue;
+
+ public TestTextView(Context context, AttributeSet attrs) {
+ this(context, attrs, com.android.internal.R.attr.textViewStyle, 0);
+ }
+
+ public TestTextView(Context context, AttributeSet attrs,
+ int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ int[] testResources = new int[]{com.android.overlaytest.R.attr.customAttribute};
+ final Resources.Theme theme = context.getTheme();
+ TypedArray typedArray = theme.obtainStyledAttributes(attrs, testResources, defStyleAttr,
+ defStyleRes);
+ mCustomAttributeValue = typedArray.getString(0);
+ }
+
+ public String getCustomAttributeValue() {
+ return mCustomAttributeValue;
+ }
+}
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml
index 7d2840886683..873ca3c9b821 100644
--- a/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/AndroidManifest.xml
@@ -19,5 +19,6 @@
android:versionCode="1"
android:versionName="1.0">
<application android:hasCode="false" />
- <overlay android:targetPackage="com.android.overlaytest" />
+ <overlay android:targetPackage="com.android.overlaytest"
+ android:resourcesMap="@xml/overlays"/>
</manifest>
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/layout/layout.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/layout/layout.xml
new file mode 100644
index 000000000000..7b636054c936
--- /dev/null
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/layout/layout.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout android:id="@+id/view_1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.android.overlaytest.view.TestTextView
+ android:id="@+id/view_2"
+ android:layout_width="match_parent"
+ android:layout_height="100dp"
+ app:customAttribute="@string/str" />
+
+ <com.android.overlaytest.view.TestTextView
+ android:id="@+id/view_3"
+ android:layout_width="match_parent"
+ android:layout_height="100dp"
+ app:customAttribute="overlaid" />
+ </LinearLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml
index 972137a3d1bf..74c496386f2f 100644
--- a/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/values/config.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="str">single</string>
- <string name="str2">single</string>
<integer name="matrix_101000">300</integer>
<integer name="matrix_101001">300</integer>
<integer name="matrix_101010">300</integer>
@@ -18,7 +17,6 @@
<integer name="matrix_111101">300</integer>
<integer name="matrix_111110">300</integer>
<integer name="matrix_111111">300</integer>
- <bool name="usually_false">true</bool>
<integer-array name="fibonacci">
<item>21</item>
<item>13</item>
@@ -29,7 +27,10 @@
<item>1</item>
<item>1</item>
</integer-array>
+
<!-- The following integer does not exist in the original package. Idmap
generation should therefore ignore it. -->
<integer name="integer_not_in_original_package">0</integer>
+
+ <attr name="customAttribute" />
</resources>
diff --git a/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/xml/overlays.xml b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/xml/overlays.xml
new file mode 100644
index 000000000000..38e5fa18300c
--- /dev/null
+++ b/core/tests/overlaytests/device/test-apps/AppOverlayOne/res/xml/overlays.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<overlay>
+ <item target="drawable/drawable" value="@drawable/drawable"/>
+ <item target="layout/layout" value="@layout/layout"/>
+ <item target="raw/lorem_ipsum" value="@raw/lorem_ipsum"/>
+ <item target="xml/integer" value="@xml/integer"/>
+ <item target="string/str" value="@string/str"/>
+ <item target="string/str2" value="single"/>
+
+ <item target="integer/matrix_100100" value="@integer/matrix_100100"/>
+ <item target="integer/matrix_100101" value="@integer/matrix_100101"/>
+ <item target="integer/matrix_100110" value="@integer/matrix_100110"/>
+ <item target="integer/matrix_100110" value="@integer/matrix_100110"/>
+ <item target="integer/matrix_100111" value="@integer/matrix_100111"/>
+ <item target="integer/matrix_101000" value="@integer/matrix_101000"/>
+ <item target="integer/matrix_101001" value="@integer/matrix_101001"/>
+ <item target="integer/matrix_101010" value="@integer/matrix_101010"/>
+ <item target="integer/matrix_101011" value="@integer/matrix_101011"/>
+ <item target="integer/matrix_101100" value="@integer/matrix_101100"/>
+ <item target="integer/matrix_101101" value="@integer/matrix_101101"/>
+ <item target="integer/matrix_101110" value="@integer/matrix_101110"/>
+ <item target="integer/matrix_101111" value="@integer/matrix_101111"/>
+ <item target="integer/matrix_110100" value="@integer/matrix_110100"/>
+ <item target="integer/matrix_110101" value="@integer/matrix_110101"/>
+ <item target="integer/matrix_110110" value="@integer/matrix_110110"/>
+ <item target="integer/matrix_110111" value="@integer/matrix_110111"/>
+ <item target="integer/matrix_111000" value="@integer/matrix_111000"/>
+ <item target="integer/matrix_111001" value="@integer/matrix_111001"/>
+ <item target="integer/matrix_111010" value="@integer/matrix_111010"/>
+ <item target="integer/matrix_111011" value="@integer/matrix_111011"/>
+ <item target="integer/matrix_111100" value="@integer/matrix_111100"/>
+ <item target="integer/matrix_111101" value="@integer/matrix_111101"/>
+ <item target="integer/matrix_111110" value="@integer/matrix_111110"/>
+ <item target="integer/matrix_111111" value="@integer/matrix_111111"/>
+
+ <item target="bool/usually_false" value="true"/>
+
+ <item target="array/fibonacci" value="@array/fibonacci"/>
+
+ <item target="attr/customAttribute" value="@attr/customAttribute"/>
+ <item target="id/view_1" value="@id/view_1"/>
+ <item target="id/view_2" value="@id/view_2"/>
+ <item target="id/view_3" value="@id/view_3"/>
+</overlay>
+
+
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index ce3bffff0aa5..0b2fd9ec982d 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -57,7 +57,7 @@ OverlayStringPool::~OverlayStringPool() {
const char16_t* OverlayStringPool::stringAt(size_t idx, size_t* outLen) const {
const size_t offset = dtohl(data_header_->string_pool_index_offset);
- if (idmap_string_pool_ != nullptr && idx >= size() && idx >= offset) {
+ if (idmap_string_pool_ != nullptr && idx >= ResStringPool::size() && idx >= offset) {
return idmap_string_pool_->stringAt(idx - offset, outLen);
}
@@ -66,13 +66,17 @@ const char16_t* OverlayStringPool::stringAt(size_t idx, size_t* outLen) const {
const char* OverlayStringPool::string8At(size_t idx, size_t* outLen) const {
const size_t offset = dtohl(data_header_->string_pool_index_offset);
- if (idmap_string_pool_ != nullptr && idx >= size() && idx >= offset) {
+ if (idmap_string_pool_ != nullptr && idx >= ResStringPool::size() && idx >= offset) {
return idmap_string_pool_->string8At(idx - offset, outLen);
}
return ResStringPool::string8At(idx, outLen);
}
+size_t OverlayStringPool::size() const {
+ return ResStringPool::size() + (idmap_string_pool_ != nullptr ? idmap_string_pool_->size() : 0U);
+}
+
OverlayDynamicRefTable::OverlayDynamicRefTable(const Idmap_data_header* data_header,
const Idmap_overlay_entry* entries,
uint8_t target_assigned_package_id)
diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h
index ab4c9c204842..ccb57f373473 100644
--- a/libs/androidfw/include/androidfw/Idmap.h
+++ b/libs/androidfw/include/androidfw/Idmap.h
@@ -40,8 +40,9 @@ class IdmapResMap;
class OverlayStringPool : public ResStringPool {
public:
virtual ~OverlayStringPool();
- virtual const char16_t* stringAt(size_t idx, size_t* outLen) const;
- virtual const char* string8At(size_t idx, size_t* outLen) const;
+ const char16_t* stringAt(size_t idx, size_t* outLen) const override;
+ const char* string8At(size_t idx, size_t* outLen) const override;
+ size_t size() const override;
explicit OverlayStringPool(const LoadedIdmap* loaded_idmap);
private:
@@ -53,8 +54,8 @@ class OverlayStringPool : public ResStringPool {
// resources to the resource id of corresponding target resources.
class OverlayDynamicRefTable : public DynamicRefTable {
public:
- virtual ~OverlayDynamicRefTable() = default;
- virtual status_t lookupResourceId(uint32_t* resId) const;
+ ~OverlayDynamicRefTable() override = default;
+ status_t lookupResourceId(uint32_t* resId) const override;
private:
explicit OverlayDynamicRefTable(const Idmap_data_header* data_header,
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index b603326cec34..35cebd425dc7 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -520,7 +520,7 @@ public:
ssize_t indexOfString(const char16_t* str, size_t strLen) const;
- size_t size() const;
+ virtual size_t size() const;
size_t styleCount() const;
size_t bytes() const;
const void* data() const;
diff --git a/media/Android.bp b/media/Android.bp
index 75ccb227e5c5..a1365179c53a 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -26,7 +26,8 @@ java_library {
installable: true,
- // Make sure that the implementaion only relies on SDK or system APIs.
+ // TODO: build against stable API surface. Use core_platform for now to avoid
+ // link-check failure with exoplayer building against "current".
sdk_version: "core_platform",
libs: [
// The order matters. android_system_* library should come later.
@@ -101,6 +102,7 @@ java_library {
name: "framework_media_annotation",
srcs: [":framework-media-annotation-srcs"],
installable: false,
+ sdk_version: "core_current",
}
aidl_interface {
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 489d0501280d..7ff15df2d65e 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -281,6 +281,8 @@ public final class AudioFormat implements Parcelable {
* metadata (object audio) over HDMI (e.g. Dolby Atmos content).
**/
public static final int ENCODING_DOLBY_MAT = 19;
+ /** Audio data format: OPUS compressed. */
+ public static final int ENCODING_OPUS = 20;
/** @hide */
public static String toLogFriendlyEncoding(int enc) {
@@ -323,6 +325,8 @@ public final class AudioFormat implements Parcelable {
return "ENCODING_E_AC3_JOC";
case ENCODING_DOLBY_MAT:
return "ENCODING_DOLBY_MAT";
+ case ENCODING_OPUS:
+ return "ENCODING_OPUS";
default :
return "invalid encoding " + enc;
}
@@ -548,6 +552,7 @@ public final class AudioFormat implements Parcelable {
case ENCODING_AC4:
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
+ case ENCODING_OPUS:
return true;
default:
return false;
@@ -576,6 +581,7 @@ public final class AudioFormat implements Parcelable {
case ENCODING_AC4:
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
+ case ENCODING_OPUS:
return true;
default:
return false;
@@ -607,6 +613,7 @@ public final class AudioFormat implements Parcelable {
case ENCODING_AC4:
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
+ case ENCODING_OPUS:
return false;
case ENCODING_INVALID:
default:
@@ -638,6 +645,7 @@ public final class AudioFormat implements Parcelable {
case ENCODING_AC4:
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
+ case ENCODING_OPUS:
return false;
case ENCODING_INVALID:
default:
@@ -917,6 +925,7 @@ public final class AudioFormat implements Parcelable {
case ENCODING_AC4:
case ENCODING_E_AC3_JOC:
case ENCODING_DOLBY_MAT:
+ case ENCODING_OPUS:
mEncoding = encoding;
break;
case ENCODING_INVALID:
@@ -1136,7 +1145,8 @@ public final class AudioFormat implements Parcelable {
ENCODING_AAC_XHE,
ENCODING_AC4,
ENCODING_E_AC3_JOC,
- ENCODING_DOLBY_MAT }
+ ENCODING_DOLBY_MAT,
+ ENCODING_OPUS }
)
@Retention(RetentionPolicy.SOURCE)
public @interface Encoding {}
diff --git a/media/java/android/media/AudioPlaybackConfiguration.java b/media/java/android/media/AudioPlaybackConfiguration.java
index ab80b3af9fc8..515e9d0d4c5c 100644
--- a/media/java/android/media/AudioPlaybackConfiguration.java
+++ b/media/java/android/media/AudioPlaybackConfiguration.java
@@ -400,6 +400,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
* configurations
* @return true if active
*/
+ @SystemApi
public boolean isActive() {
switch (mPlayerState) {
case PLAYER_STATE_STARTED:
@@ -420,18 +421,7 @@ public final class AudioPlaybackConfiguration implements Parcelable {
* @param pw
*/
public void dump(PrintWriter pw) {
- pw.println(" " + toLogFriendlyString(this));
- }
-
- /**
- * @hide
- */
- public static String toLogFriendlyString(AudioPlaybackConfiguration apc) {
- return new String("ID:" + apc.mPlayerIId
- + " -- type:" + toLogFriendlyPlayerType(apc.mPlayerType)
- + " -- u/pid:" + apc.mClientUid +"/" + apc.mClientPid
- + " -- state:" + toLogFriendlyPlayerState(apc.mPlayerState)
- + " -- attr:" + apc.mPlayerAttr);
+ pw.println(" " + this);
}
public static final @android.annotation.NonNull Parcelable.Creator<AudioPlaybackConfiguration> CREATOR
@@ -498,6 +488,15 @@ public final class AudioPlaybackConfiguration implements Parcelable {
&& (mClientPid == that.mClientPid));
}
+ @Override
+ public String toString() {
+ return "AudioPlaybackConfiguration piid:" + mPlayerIId
+ + " type:" + toLogFriendlyPlayerType(mPlayerType)
+ + " u/pid:" + mClientUid + "/" + mClientPid
+ + " state:" + toLogFriendlyPlayerState(mPlayerState)
+ + " attr:" + mPlayerAttr;
+ }
+
//=====================================================================
// Inner class for corresponding IPlayer and its death monitoring
static final class IPlayerShell implements IBinder.DeathRecipient {
diff --git a/media/java/android/media/MediaRoute2ProviderInfo.java b/media/java/android/media/MediaRoute2ProviderInfo.java
index b5de88ae1da9..7078d4a0b568 100644
--- a/media/java/android/media/MediaRoute2ProviderInfo.java
+++ b/media/java/android/media/MediaRoute2ProviderInfo.java
@@ -46,9 +46,9 @@ public final class MediaRoute2ProviderInfo implements Parcelable {
};
@Nullable
- private final String mUniqueId;
+ final String mUniqueId;
@NonNull
- private final ArrayMap<String, MediaRoute2Info> mRoutes;
+ final ArrayMap<String, MediaRoute2Info> mRoutes;
MediaRoute2ProviderInfo(@NonNull Builder builder) {
Objects.requireNonNull(builder, "builder must not be null.");
@@ -142,6 +142,7 @@ public final class MediaRoute2ProviderInfo implements Parcelable {
public Builder(@NonNull MediaRoute2ProviderInfo descriptor) {
Objects.requireNonNull(descriptor, "descriptor must not be null");
+ mUniqueId = descriptor.mUniqueId;
mRoutes = new ArrayMap<>(descriptor.mRoutes);
}
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index 1b6183e361c8..8d6f2551f9f6 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -27,8 +27,13 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.util.ArrayMap;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
/**
@@ -40,10 +45,14 @@ public abstract class MediaRoute2ProviderService extends Service {
public static final String SERVICE_INTERFACE = "android.media.MediaRoute2ProviderService";
private final Handler mHandler;
+ private final Object mSessionLock = new Object();
private ProviderStub mStub;
private IMediaRoute2ProviderClient mClient;
private MediaRoute2ProviderInfo mProviderInfo;
+ @GuardedBy("mSessionLock")
+ private ArrayMap<Integer, RouteSessionInfo> mSessionInfo = new ArrayMap<>();
+
public MediaRoute2ProviderService() {
mHandler = new Handler(Looper.getMainLooper());
}
@@ -93,6 +102,7 @@ public abstract class MediaRoute2ProviderService extends Service {
/**
* Called when requestSetVolume is called on a route of the provider
+ *
* @param routeId the id of the route
* @param volume the target volume
*/
@@ -100,15 +110,164 @@ public abstract class MediaRoute2ProviderService extends Service {
/**
* Called when requestUpdateVolume is called on a route of the provider
+ *
* @param routeId id of the route
* @param delta the delta to add to the current volume
*/
public abstract void onUpdateVolume(@NonNull String routeId, int delta);
/**
- * Updates provider info and publishes routes
+ * Gets information of the session with the given id.
+ *
+ * @param sessionId id of the session
+ * @return information of the session with the given id.
+ * null if the session is destroyed or id is not valid.
+ */
+ @Nullable
+ public final RouteSessionInfo getSessionInfo(int sessionId) {
+ synchronized (mSessionLock) {
+ return mSessionInfo.get(sessionId);
+ }
+ }
+
+ /**
+ * Gets the list of {@link RouteSessionInfo session info} that the provider service maintains.
+ */
+ @NonNull
+ public final List<RouteSessionInfo> getAllSessionInfo() {
+ synchronized (mSessionLock) {
+ return new ArrayList<>(mSessionInfo.values());
+ }
+ }
+
+ /**
+ * Sets the information of the session with the given id.
+ * If there is no session matched with the given id, it will be ignored.
+ * A session will be destroyed if it has no selected route.
+ * Call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify clients of
+ * session info changes.
+ *
+ * @param sessionId id of the session that should update its information
+ * @param sessionInfo new session information
+ */
+ public final void setSessionInfo(int sessionId, @NonNull RouteSessionInfo sessionInfo) {
+ Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
+
+ synchronized (mSessionLock) {
+ if (mSessionInfo.containsKey(sessionId)) {
+ mSessionInfo.put(sessionId, sessionInfo);
+ } else {
+ Log.w(TAG, "Ignoring session info update.");
+ }
+ }
+ }
+
+ /**
+ * Notifies clients of that the session is created and ready for use. If the session can be
+ * controlled, pass a {@link Bundle} that contains how to control it.
+ *
+ * @param sessionId id of the session
+ * @param sessionInfo information of the new session.
+ * Pass {@code null} to reject the request or inform clients that
+ * session creation has failed.
+ * @param controlHints a {@link Bundle} that contains how to control the session.
+ */
+ //TODO: fail reason?
+ public final void notifySessionCreated(int sessionId, @Nullable RouteSessionInfo sessionInfo,
+ @Nullable Bundle controlHints) {
+ //TODO: validate sessionId (it must be in "waiting list")
+ synchronized (mSessionLock) {
+ mSessionInfo.put(sessionId, sessionInfo);
+ //TODO: notify media router service of session creation.
+ }
+ }
+
+ /**
+ * Releases a session with the given id.
+ * {@link #onDestroySession} is called if the session is released.
+ *
+ * @param sessionId id of the session to be released
+ * @see #onDestroySession(int, RouteSessionInfo)
*/
- public final void setProviderInfo(MediaRoute2ProviderInfo info) {
+ public final void releaseSession(int sessionId) {
+ RouteSessionInfo sessionInfo;
+ synchronized (mSessionLock) {
+ sessionInfo = mSessionInfo.put(sessionId, null);
+ }
+ if (sessionInfo != null) {
+ mHandler.sendMessage(obtainMessage(
+ MediaRoute2ProviderService::onDestroySession, this, sessionId, sessionInfo));
+ }
+ }
+
+ /**
+ * Called when a session should be created.
+ * You should create and maintain your own session and notifies the client of
+ * session info. Call {@link #notifySessionCreated(int, RouteSessionInfo, Bundle)}
+ * to notify the information of a new session.
+ * If you can't create the session or want to reject the request, pass {@code null}
+ * as session info in {@link #notifySessionCreated(int, RouteSessionInfo, Bundle)}.
+ *
+ * @param packageName the package name of the application that selected the route
+ * @param routeId the id of the route initially being connected
+ * @param controlCategory the control category of the new session
+ * @param sessionId the id of a new session
+ */
+ public abstract void onCreateSession(@NonNull String packageName, @NonNull String routeId,
+ @NonNull String controlCategory, int sessionId);
+
+ /**
+ * Called when a session is about to be destroyed.
+ * You can clean up your session here. This can happen by the
+ * client or provider itself.
+ *
+ * @param sessionId id of the session being destroyed.
+ * @param lastSessionInfo information of the session being destroyed.
+ * @see #releaseSession(int)
+ */
+ public abstract void onDestroySession(int sessionId, @NonNull RouteSessionInfo lastSessionInfo);
+
+ //TODO: make a way to reject the request
+ /**
+ * Called when a client requests adding a route to a session.
+ * After the route is added, call {@link #setSessionInfo(int, RouteSessionInfo)} to update
+ * session info and call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify
+ * clients of updated session info.
+ *
+ * @param sessionId id of the session
+ * @param routeId id of the route
+ * @see #setSessionInfo(int, RouteSessionInfo)
+ */
+ public abstract void onAddRoute(int sessionId, @NonNull String routeId);
+
+ //TODO: make a way to reject the request
+ /**
+ * Called when a client requests removing a route from a session.
+ * After the route is removed, call {@link #setSessionInfo(int, RouteSessionInfo)} to update
+ * session info and call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify
+ * clients of updated session info.
+ *
+ * @param sessionId id of the session
+ * @param routeId id of the route
+ */
+ public abstract void onRemoveRoute(int sessionId, @NonNull String routeId);
+
+ //TODO: make a way to reject the request
+ /**
+ * Called when a client requests transferring a session to a route.
+ * After the transfer is finished, call {@link #setSessionInfo(int, RouteSessionInfo)} to update
+ * session info and call {@link #updateProviderInfo(MediaRoute2ProviderInfo)} to notify
+ * clients of updated session info.
+ *
+ * @param sessionId id of the session
+ * @param routeId id of the route
+ */
+ public abstract void onTransferRoute(int sessionId, @NonNull String routeId);
+
+ /**
+ * Updates provider info and publishes routes and session info.
+ */
+ public final void updateProviderInfo(MediaRoute2ProviderInfo info) {
mProviderInfo = info;
publishState();
}
@@ -142,6 +301,7 @@ public abstract class MediaRoute2ProviderService extends Service {
}
void publishState() {
+ //TODO: sends session info
if (mClient == null) {
return;
}
@@ -179,35 +339,35 @@ public abstract class MediaRoute2ProviderService extends Service {
}
@Override
- public void requestSelectRoute(String packageName, String id, int seq) {
+ public void requestSelectRoute(String packageName, String routeId, int seq) {
+ //TODO: call onCreateSession instead
mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSelectRoute,
- MediaRoute2ProviderService.this, packageName, id,
- new SelectToken(packageName, id, seq)));
-
+ MediaRoute2ProviderService.this, packageName, routeId,
+ new SelectToken(packageName, routeId, seq)));
}
@Override
- public void unselectRoute(String packageName, String id) {
+ public void unselectRoute(String packageName, String routeId) {
mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onUnselectRoute,
- MediaRoute2ProviderService.this, packageName, id));
+ MediaRoute2ProviderService.this, packageName, routeId));
}
@Override
- public void notifyControlRequestSent(String id, Intent request) {
+ public void notifyControlRequestSent(String routeId, Intent request) {
mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onControlRequest,
- MediaRoute2ProviderService.this, id, request));
+ MediaRoute2ProviderService.this, routeId, request));
}
@Override
- public void requestSetVolume(String id, int volume) {
+ public void requestSetVolume(String routeId, int volume) {
mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetVolume,
- MediaRoute2ProviderService.this, id, volume));
+ MediaRoute2ProviderService.this, routeId, volume));
}
@Override
- public void requestUpdateVolume(String id, int delta) {
+ public void requestUpdateVolume(String routeId, int delta) {
mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onUpdateVolume,
- MediaRoute2ProviderService.this, id, delta));
+ MediaRoute2ProviderService.this, routeId, delta));
}
}
}
diff --git a/media/java/android/media/RouteSessionInfo.java b/media/java/android/media/RouteSessionInfo.java
index 0878e6b31ec6..53c8eec8bb9f 100644
--- a/media/java/android/media/RouteSessionInfo.java
+++ b/media/java/android/media/RouteSessionInfo.java
@@ -218,79 +218,116 @@ public class RouteSessionInfo implements Parcelable {
}
/**
- * Adds a selected route
+ * Clears the selected routes.
*/
@NonNull
- public Builder addSelectedRoute(String routeId) {
- mSelectedRoutes.add(routeId);
+ public Builder clearSelectedRoutes() {
+ mSelectedRoutes.clear();
return this;
}
/**
- * Removes a selected route
+ * Adds a route to the selected routes.
*/
@NonNull
- public Builder removeSelectedRoute(String routeId) {
- mSelectedRoutes.remove(routeId);
+ public Builder addSelectedRoute(@NonNull String routeId) {
+ mSelectedRoutes.add(Objects.requireNonNull(routeId, "routeId must not be null"));
return this;
}
/**
- * Adds a deselectable route
+ * Removes a route from the selected routes.
*/
@NonNull
- public Builder addDeselectableRoute(String routeId) {
- mDeselectableRoutes.add(routeId);
+ public Builder removeSelectedRoute(@NonNull String routeId) {
+ mSelectedRoutes.remove(Objects.requireNonNull(routeId, "routeId must not be null"));
return this;
}
/**
- * Removes a deselecable route
+ * Clears the deselectable routes.
*/
@NonNull
- public Builder removeDeselectableRoute(String routeId) {
- mDeselectableRoutes.remove(routeId);
+ public Builder clearDeselectableRoutes() {
+ mDeselectableRoutes.clear();
return this;
}
/**
- * Adds a groupable route
+ * Adds a route to the deselectable routes.
*/
@NonNull
- public Builder addGroupableRoute(String routeId) {
- mGroupableRoutes.add(routeId);
+ public Builder addDeselectableRoute(@NonNull String routeId) {
+ mDeselectableRoutes.add(Objects.requireNonNull(routeId, "routeId must not be null"));
return this;
}
/**
- * Removes a groupable route
+ * Removes a route from the deselectable routes.
*/
@NonNull
- public Builder removeGroupableRoute(String routeId) {
- mGroupableRoutes.remove(routeId);
+ public Builder removeDeselectableRoute(@NonNull String routeId) {
+ mDeselectableRoutes.remove(Objects.requireNonNull(routeId, "routeId must not be null"));
return this;
}
/**
- * Adds a transferrable route
+ * Clears the groupable routes.
*/
@NonNull
- public Builder addTransferrableRoute(String routeId) {
- mTransferrableRoutes.add(routeId);
+ public Builder clearGroupableRoutes() {
+ mGroupableRoutes.clear();
return this;
}
/**
- * Removes a transferrable route
+ * Adds a route to the groupable routes.
*/
@NonNull
- public Builder removeTransferrableRoute(String routeId) {
- mTransferrableRoutes.remove(routeId);
+ public Builder addGroupableRoute(@NonNull String routeId) {
+ mGroupableRoutes.add(Objects.requireNonNull(routeId, "routeId must not be null"));
return this;
}
/**
- * Builds a route session info
+ * Removes a route from the groupable routes.
+ */
+ @NonNull
+ public Builder removeGroupableRoute(@NonNull String routeId) {
+ mGroupableRoutes.remove(Objects.requireNonNull(routeId, "routeId must not be null"));
+ return this;
+ }
+
+ /**
+ * Clears the transferrable routes.
+ */
+ @NonNull
+ public Builder clearTransferrableRoutes() {
+ mTransferrableRoutes.clear();
+ return this;
+ }
+
+ /**
+ * Adds a route to the transferrable routes.
+ */
+ @NonNull
+ public Builder addTransferrableRoute(@NonNull String routeId) {
+ mTransferrableRoutes.add(Objects.requireNonNull(routeId, "routeId must not be null"));
+ return this;
+ }
+
+ /**
+ * Removes a route from the transferrable routes.
+ */
+ @NonNull
+ public Builder removeTransferrableRoute(@NonNull String routeId) {
+ mTransferrableRoutes.remove(
+ Objects.requireNonNull(routeId, "routeId must not be null"));
+ return this;
+ }
+
+ /**
+ * Builds a route session info.
*/
@NonNull
public RouteSessionInfo build() {
diff --git a/media/java/android/media/tv/tuner/FilterSettings.java b/media/java/android/media/tv/tuner/FilterSettings.java
index d5f100341dc6..673b3d9d8bcc 100644
--- a/media/java/android/media/tv/tuner/FilterSettings.java
+++ b/media/java/android/media/tv/tuner/FilterSettings.java
@@ -17,8 +17,7 @@
package android.media.tv.tuner;
import android.annotation.Nullable;
-import android.hardware.tv.tuner.V1_0.Constants;
-import android.media.tv.tuner.TunerConstants.FilterSettingsType;
+import android.media.tv.tuner.TunerConstants.FilterType;
import java.util.List;
@@ -38,7 +37,8 @@ public abstract class FilterSettings {
/**
* Gets filter settings type
*/
- @FilterSettingsType public abstract int getType();
+ @FilterType
+ public abstract int getType();
// TODO: more builders and getters
@@ -55,7 +55,7 @@ public abstract class FilterSettings {
@Override
public int getType() {
- return TunerConstants.FILTER_SETTINGS_TS;
+ return TunerConstants.FILTER_TYPE_TS;
}
/**
@@ -109,7 +109,7 @@ public abstract class FilterSettings {
@Override
public int getType() {
- return TunerConstants.FILTER_SETTINGS_MMTP;
+ return TunerConstants.FILTER_TYPE_MMTP;
}
}
@@ -130,7 +130,7 @@ public abstract class FilterSettings {
@Override
public int getType() {
- return TunerConstants.FILTER_SETTINGS_IP;
+ return TunerConstants.FILTER_TYPE_IP;
}
}
@@ -149,7 +149,7 @@ public abstract class FilterSettings {
@Override
public int getType() {
- return TunerConstants.FILTER_SETTINGS_TLV;
+ return TunerConstants.FILTER_TYPE_TLV;
}
}
@@ -167,7 +167,7 @@ public abstract class FilterSettings {
@Override
public int getType() {
- return TunerConstants.FILTER_SETTINGS_ALP;
+ return TunerConstants.FILTER_TYPE_ALP;
}
}
@@ -197,24 +197,7 @@ public abstract class FilterSettings {
public static class SectionSettings extends Settings {
private SectionSettings(int mainType) {
- super(SectionSettings.findType(mainType));
- }
-
- private static int findType(int mainType) {
- switch (mainType) {
- case TunerConstants.FILTER_SETTINGS_TS:
- return Constants.DemuxTsFilterType.SECTION;
- case TunerConstants.FILTER_SETTINGS_MMTP:
- return Constants.DemuxMmtpFilterType.SECTION;
- case TunerConstants.FILTER_SETTINGS_IP:
- return Constants.DemuxIpFilterType.SECTION;
- case TunerConstants.FILTER_SETTINGS_TLV:
- return Constants.DemuxTlvFilterType.SECTION;
- case TunerConstants.FILTER_SETTINGS_ALP:
- return Constants.DemuxAlpFilterType.SECTION;
- }
- // UNDEFINED
- return 0;
+ super(TunerUtils.getFilterSubtype(mainType, TunerConstants.FILTER_SUBTYPE_SECTION));
}
}
@@ -251,22 +234,11 @@ public abstract class FilterSettings {
private boolean mIsRaw;
private PesSettings(int mainType, int streamId, boolean isRaw) {
- super(PesSettings.findType(mainType));
+ super(TunerUtils.getFilterSubtype(mainType, TunerConstants.FILTER_SUBTYPE_PES));
mStreamId = streamId;
mIsRaw = isRaw;
}
- private static int findType(int mainType) {
- switch (mainType) {
- case TunerConstants.FILTER_SETTINGS_TS:
- return Constants.DemuxTsFilterType.PES;
- case TunerConstants.FILTER_SETTINGS_MMTP:
- return Constants.DemuxMmtpFilterType.PES;
- }
- // UNDEFINED
- return 0;
- }
-
/**
* Creates a builder for PesSettings.
*/
@@ -319,22 +291,11 @@ public abstract class FilterSettings {
private boolean mIsPassthrough;
private AvSettings(int mainType, boolean isAudio) {
- super(AvSettings.findType(mainType, isAudio));
- }
-
- private static int findType(int mainType, boolean isAudio) {
- switch (mainType) {
- case TunerConstants.FILTER_SETTINGS_TS:
- return isAudio
- ? Constants.DemuxTsFilterType.AUDIO
- : Constants.DemuxTsFilterType.VIDEO;
- case TunerConstants.FILTER_SETTINGS_MMTP:
- return isAudio
- ? Constants.DemuxMmtpFilterType.AUDIO
- : Constants.DemuxMmtpFilterType.VIDEO;
- }
- // UNDEFINED
- return 0;
+ super(TunerUtils.getFilterSubtype(
+ mainType,
+ isAudio
+ ? TunerConstants.FILTER_SUBTYPE_AUDIO
+ : TunerConstants.FILTER_SUBTYPE_VIDEO));
}
}
@@ -345,15 +306,7 @@ public abstract class FilterSettings {
private int mDownloadId;
public DownloadSettings(int mainType) {
- super(DownloadSettings.findType(mainType));
- }
-
- private static int findType(int mainType) {
- if (mainType == TunerConstants.FILTER_SETTINGS_MMTP) {
- return Constants.DemuxMmtpFilterType.DOWNLOAD;
- }
- // UNDEFINED
- return 0;
+ super(TunerUtils.getFilterSubtype(mainType, TunerConstants.FILTER_SUBTYPE_DOWNLOAD));
}
}
@@ -365,18 +318,7 @@ public abstract class FilterSettings {
private int mIndexMask;
public RecordSettings(int mainType) {
- super(RecordSettings.findType(mainType));
- }
-
- private static int findType(int mainType) {
- switch (mainType) {
- case TunerConstants.FILTER_SETTINGS_TS:
- return Constants.DemuxTsFilterType.RECORD;
- case TunerConstants.FILTER_SETTINGS_MMTP:
- return Constants.DemuxMmtpFilterType.RECORD;
- }
- // UNDEFINED
- return 0;
+ super(TunerUtils.getFilterSubtype(mainType, TunerConstants.FILTER_SUBTYPE_RECORD));
}
}
diff --git a/media/java/android/media/tv/tuner/ScanMessage.java b/media/java/android/media/tv/tuner/ScanMessage.java
new file mode 100644
index 000000000000..35f54f8447c0
--- /dev/null
+++ b/media/java/android/media/tv/tuner/ScanMessage.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner;
+
+import android.media.tv.tuner.TunerConstants.ScanMessageType;
+
+/**
+ * Message from frontend during scan operations.
+ *
+ * @hide
+ */
+public class ScanMessage {
+ private final int mType;
+ private final Object mValue;
+
+ private ScanMessage(int type, Object value) {
+ mType = type;
+ mValue = value;
+ }
+
+ /** Gets scan message type. */
+ @ScanMessageType
+ public int getMessageType() {
+ return mType;
+ }
+ /** Message indicates whether frontend is locked or not. */
+ public boolean getIsLocked() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_LOCKED) {
+ throw new IllegalStateException();
+ }
+ return (Boolean) mValue;
+ }
+ /** Message indicates whether the scan has reached the end or not. */
+ public boolean getIsEnd() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_END) {
+ throw new IllegalStateException();
+ }
+ return (Boolean) mValue;
+ }
+ /** Progress message in percent. */
+ public int getProgressPercent() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_PROGRESS_PERCENT) {
+ throw new IllegalStateException();
+ }
+ return (Integer) mValue;
+ }
+ /** Gets frequency. */
+ public int getFrequency() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_FREQUENCY) {
+ throw new IllegalStateException();
+ }
+ return (Integer) mValue;
+ }
+ /** Gets symbol rate. */
+ public int getSymbolRate() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_SYMBOL_RATE) {
+ throw new IllegalStateException();
+ }
+ return (Integer) mValue;
+ }
+ /** Gets PLP IDs. */
+ public int[] getPlpIds() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_PLP_IDS) {
+ throw new IllegalStateException();
+ }
+ return (int[]) mValue;
+ }
+ /** Gets group IDs. */
+ public int[] getGroupIds() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_GROUP_IDS) {
+ throw new IllegalStateException();
+ }
+ return (int[]) mValue;
+ }
+ /** Gets Input stream IDs. */
+ public int[] getInputStreamIds() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_INPUT_STREAM_IDS) {
+ throw new IllegalStateException();
+ }
+ return (int[]) mValue;
+ }
+ /** Gets the DVB-T or DVB-S standard. */
+ public int getStandard() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_STANDARD) {
+ throw new IllegalStateException();
+ }
+ return (int) mValue;
+ }
+
+ /** Gets PLP information for ATSC3. */
+ public Atsc3PlpInfo[] getAtsc3PlpInfos() {
+ if (mType != TunerConstants.SCAN_MESSAGE_TYPE_ATSC3_PLP_INFO) {
+ throw new IllegalStateException();
+ }
+ return (Atsc3PlpInfo[]) mValue;
+ }
+
+ /** PLP information for ATSC3. */
+ public static class Atsc3PlpInfo {
+ private final int mPlpId;
+ private final boolean mLlsFlag;
+
+ private Atsc3PlpInfo(int plpId, boolean llsFlag) {
+ mPlpId = plpId;
+ mLlsFlag = llsFlag;
+ }
+
+ /** Gets PLP IDs. */
+ public int getPlpId() {
+ return mPlpId;
+ }
+ /** Gets LLS flag. */
+ public boolean getLlsFlag() {
+ return mLlsFlag;
+ }
+ }
+}
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index 4947700f6952..f02c4aa10311 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -21,8 +21,10 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.media.tv.tuner.TunerConstants.DemuxPidType;
+import android.media.tv.tuner.TunerConstants.FilterSubtype;
+import android.media.tv.tuner.TunerConstants.FilterType;
+import android.media.tv.tuner.TunerConstants.FrontendScanType;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -43,7 +45,6 @@ public final class Tuner implements AutoCloseable {
private static final String TAG = "MediaTvTuner";
private static final boolean DEBUG = false;
- private static final String PERMISSION = android.Manifest.permission.ACCESS_TV_TUNER;
private static final int MSG_ON_FRONTEND_EVENT = 1;
private static final int MSG_ON_FILTER_EVENT = 2;
private static final int MSG_ON_FILTER_STATUS = 3;
@@ -73,13 +74,6 @@ public final class Tuner implements AutoCloseable {
nativeSetup();
}
- private void checkPermission() {
- if (mContext.checkCallingOrSelfPermission(PERMISSION)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Caller must have " + PERMISSION + " permission.");
- }
- }
-
private long mNativeContext; // used by native jMediaTuner
/** @hide */
@@ -106,7 +100,10 @@ public final class Tuner implements AutoCloseable {
*/
private native Frontend nativeOpenFrontendById(int id);
private native int nativeTune(int type, FrontendSettings settings);
-
+ private native int nativeStopTune();
+ private native int nativeScan(int settingsType, FrontendSettings settings, int scanType);
+ private native int nativeSetLnb(int lnbId);
+ private native int nativeSetLna(boolean enable);
private native Filter nativeOpenFilter(int type, int subType, int bufferSize);
private native List<Integer> nativeGetLnbIds();
@@ -127,6 +124,12 @@ public final class Tuner implements AutoCloseable {
* Invoked when there is a frontend event.
*/
void onEvent(int frontendEventType);
+
+ /**
+ * Invoked when there is a scan message.
+ * @param msg
+ */
+ void onScanMessage(ScanMessage msg);
}
/**
@@ -252,10 +255,58 @@ public final class Tuner implements AutoCloseable {
*/
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
public int tune(@NonNull FrontendSettings settings) {
- checkPermission();
+ TunerUtils.checkTunerPermission(mContext);
return nativeTune(settings.getType(), settings);
}
+ /**
+ * Stops a previous tuning.
+ *
+ * If the method completes successfully the frontend is no longer tuned and no data
+ * will be sent to attached filters.
+ *
+ * @return result status of the operation.
+ * @hide
+ */
+ public int stopTune() {
+ return nativeStopTune();
+ }
+
+ /**
+ * Scan channels.
+ * @hide
+ */
+ public int scan(@NonNull FrontendSettings settings, @FrontendScanType int scanType) {
+ return nativeScan(settings.getType(), settings, scanType);
+ }
+
+ /**
+ * Sets Low-Noise Block downconverter (LNB) for satellite frontend.
+ *
+ * This assigns a hardware LNB resource to the satellite tuner. It can be
+ * called multiple times to update LNB assignment.
+ *
+ * @param lnb the LNB instance.
+ *
+ * @return result status of the operation.
+ * @hide
+ */
+ public int setLnb(@NonNull Lnb lnb) {
+ return nativeSetLnb(lnb.mId);
+ }
+
+ /**
+ * Enable or Disable Low Noise Amplifier (LNA).
+ *
+ * @param enable true to activate LNA module; false to deactivate LNA
+ *
+ * @return result status of the operation.
+ * @hide
+ */
+ public int setLna(boolean enable) {
+ return nativeSetLna(enable);
+ }
+
private List<Integer> getFrontendIds() {
mFrontendIds = nativeGetFrontendIds();
return mFrontendIds;
@@ -327,8 +378,10 @@ public final class Tuner implements AutoCloseable {
}
}
- private Filter openFilter(int type, int subType, int bufferSize, FilterCallback cb) {
- Filter filter = nativeOpenFilter(type, subType, bufferSize);
+ private Filter openFilter(@FilterType int mainType, @FilterSubtype int subType, int bufferSize,
+ FilterCallback cb) {
+ Filter filter = nativeOpenFilter(
+ mainType, TunerUtils.getFilterSubtype(mainType, subType), bufferSize);
if (filter != null) {
filter.mCallback = cb;
if (mHandler == null) {
@@ -416,7 +469,7 @@ public final class Tuner implements AutoCloseable {
@RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
@Nullable
public Descrambler openDescrambler() {
- checkPermission();
+ TunerUtils.checkTunerPermission(mContext);
return nativeOpenDescrambler();
}
diff --git a/media/java/android/media/tv/tuner/TunerConstants.java b/media/java/android/media/tv/tuner/TunerConstants.java
index 261b2deebac9..2c6d850b10da 100644
--- a/media/java/android/media/tv/tuner/TunerConstants.java
+++ b/media/java/android/media/tv/tuner/TunerConstants.java
@@ -75,6 +75,7 @@ final class TunerConstants {
public static final int DEMUX_T_PID = 1;
public static final int DEMUX_MMPT_PID = 2;
+ @Retention(RetentionPolicy.SOURCE)
@IntDef({FRONTEND_SETTINGS_ANALOG, FRONTEND_SETTINGS_ATSC, FRONTEND_SETTINGS_ATSC3,
FRONTEND_SETTINGS_DVBS, FRONTEND_SETTINGS_DVBC, FRONTEND_SETTINGS_DVBT,
FRONTEND_SETTINGS_ISDBS, FRONTEND_SETTINGS_ISDBS3, FRONTEND_SETTINGS_ISDBT})
@@ -91,6 +92,75 @@ final class TunerConstants {
public static final int FRONTEND_SETTINGS_ISDBT = 9;
@Retention(RetentionPolicy.SOURCE)
+ @IntDef({FILTER_TYPE_TS, FILTER_TYPE_MMTP, FILTER_TYPE_IP, FILTER_TYPE_TLV, FILTER_TYPE_ALP})
+ public @interface FilterType {}
+
+ public static final int FILTER_TYPE_TS = Constants.DemuxFilterMainType.TS;
+ public static final int FILTER_TYPE_MMTP = Constants.DemuxFilterMainType.MMTP;
+ public static final int FILTER_TYPE_IP = Constants.DemuxFilterMainType.IP;
+ public static final int FILTER_TYPE_TLV = Constants.DemuxFilterMainType.TLV;
+ public static final int FILTER_TYPE_ALP = Constants.DemuxFilterMainType.ALP;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({FILTER_SUBTYPE_UNDEFINED, FILTER_SUBTYPE_SECTION, FILTER_SUBTYPE_PES,
+ FILTER_SUBTYPE_AUDIO, FILTER_SUBTYPE_VIDEO, FILTER_SUBTYPE_DOWNLOAD,
+ FILTER_SUBTYPE_RECORD, FILTER_SUBTYPE_TS, FILTER_SUBTYPE_PCR, FILTER_SUBTYPE_TEMI,
+ FILTER_SUBTYPE_MMPT, FILTER_SUBTYPE_NTP, FILTER_SUBTYPE_IP_PAYLOAD, FILTER_SUBTYPE_IP,
+ FILTER_SUBTYPE_PAYLOAD_THROUGH, FILTER_SUBTYPE_TLV, FILTER_SUBTYPE_PTP, })
+ public @interface FilterSubtype {}
+
+ public static final int FILTER_SUBTYPE_UNDEFINED = 0;
+ public static final int FILTER_SUBTYPE_SECTION = 1;
+ public static final int FILTER_SUBTYPE_PES = 2;
+ public static final int FILTER_SUBTYPE_AUDIO = 3;
+ public static final int FILTER_SUBTYPE_VIDEO = 4;
+ public static final int FILTER_SUBTYPE_DOWNLOAD = 5;
+ public static final int FILTER_SUBTYPE_RECORD = 6;
+ public static final int FILTER_SUBTYPE_TS = 7;
+ public static final int FILTER_SUBTYPE_PCR = 8;
+ public static final int FILTER_SUBTYPE_TEMI = 9;
+ public static final int FILTER_SUBTYPE_MMPT = 10;
+ public static final int FILTER_SUBTYPE_NTP = 11;
+ public static final int FILTER_SUBTYPE_IP_PAYLOAD = 12;
+ public static final int FILTER_SUBTYPE_IP = 13;
+ public static final int FILTER_SUBTYPE_PAYLOAD_THROUGH = 14;
+ public static final int FILTER_SUBTYPE_TLV = 15;
+ public static final int FILTER_SUBTYPE_PTP = 16;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({FRONTEND_SCAN_UNDEFINED, FRONTEND_SCAN_AUTO, FRONTEND_SCAN_BLIND})
+ public @interface FrontendScanType {}
+
+ public static final int FRONTEND_SCAN_UNDEFINED = Constants.FrontendScanType.SCAN_UNDEFINED;
+ public static final int FRONTEND_SCAN_AUTO = Constants.FrontendScanType.SCAN_AUTO;
+ public static final int FRONTEND_SCAN_BLIND = Constants.FrontendScanType.SCAN_BLIND;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({SCAN_MESSAGE_TYPE_LOCKED, SCAN_MESSAGE_TYPE_END, SCAN_MESSAGE_TYPE_PROGRESS_PERCENT,
+ SCAN_MESSAGE_TYPE_FREQUENCY, SCAN_MESSAGE_TYPE_SYMBOL_RATE, SCAN_MESSAGE_TYPE_PLP_IDS,
+ SCAN_MESSAGE_TYPE_GROUP_IDS, SCAN_MESSAGE_TYPE_INPUT_STREAM_IDS,
+ SCAN_MESSAGE_TYPE_STANDARD, SCAN_MESSAGE_TYPE_ATSC3_PLP_INFO})
+ public @interface ScanMessageType {}
+
+ public static final int SCAN_MESSAGE_TYPE_LOCKED = Constants.FrontendScanMessageType.LOCKED;
+ public static final int SCAN_MESSAGE_TYPE_END = Constants.FrontendScanMessageType.END;
+ public static final int SCAN_MESSAGE_TYPE_PROGRESS_PERCENT =
+ Constants.FrontendScanMessageType.PROGRESS_PERCENT;
+ public static final int SCAN_MESSAGE_TYPE_FREQUENCY =
+ Constants.FrontendScanMessageType.FREQUENCY;
+ public static final int SCAN_MESSAGE_TYPE_SYMBOL_RATE =
+ Constants.FrontendScanMessageType.SYMBOL_RATE;
+ public static final int SCAN_MESSAGE_TYPE_PLP_IDS = Constants.FrontendScanMessageType.PLP_IDS;
+ public static final int SCAN_MESSAGE_TYPE_GROUP_IDS =
+ Constants.FrontendScanMessageType.GROUP_IDS;
+ public static final int SCAN_MESSAGE_TYPE_INPUT_STREAM_IDS =
+ Constants.FrontendScanMessageType.INPUT_STREAM_IDS;
+ public static final int SCAN_MESSAGE_TYPE_STANDARD =
+ Constants.FrontendScanMessageType.STANDARD;
+ public static final int SCAN_MESSAGE_TYPE_ATSC3_PLP_INFO =
+ Constants.FrontendScanMessageType.ATSC3_PLP_INFO;
+
+ @Retention(RetentionPolicy.SOURCE)
@IntDef({FILTER_SETTINGS_TS, FILTER_SETTINGS_MMTP, FILTER_SETTINGS_IP, FILTER_SETTINGS_TLV,
FILTER_SETTINGS_ALP})
public @interface FilterSettingsType {}
diff --git a/media/java/android/media/tv/tuner/TunerUtils.java b/media/java/android/media/tv/tuner/TunerUtils.java
new file mode 100644
index 000000000000..b3bd78076b60
--- /dev/null
+++ b/media/java/android/media/tv/tuner/TunerUtils.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.tv.tuner;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.tv.tuner.V1_0.Constants;
+import android.media.tv.tuner.TunerConstants.FilterSubtype;
+import android.media.tv.tuner.TunerConstants.FilterType;
+
+/**
+ * Utility class for tuner framework.
+ *
+ * @hide
+ */
+public final class TunerUtils {
+ private static final String PERMISSION = android.Manifest.permission.ACCESS_TV_TUNER;
+
+ static void checkTunerPermission(Context context) {
+ if (context.checkCallingOrSelfPermission(PERMISSION)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Caller must have " + PERMISSION + " permission.");
+ }
+ }
+
+ static int getFilterSubtype(@FilterType int mainType, @FilterSubtype int subtype) {
+ if (mainType == TunerConstants.FILTER_TYPE_TS) {
+ switch (subtype) {
+ case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
+ return Constants.DemuxTsFilterType.UNDEFINED;
+ case TunerConstants.FILTER_SUBTYPE_SECTION:
+ return Constants.DemuxTsFilterType.SECTION;
+ case TunerConstants.FILTER_SUBTYPE_PES:
+ return Constants.DemuxTsFilterType.PES;
+ case TunerConstants.FILTER_SUBTYPE_TS:
+ return Constants.DemuxTsFilterType.TS;
+ case TunerConstants.FILTER_SUBTYPE_AUDIO:
+ return Constants.DemuxTsFilterType.AUDIO;
+ case TunerConstants.FILTER_SUBTYPE_VIDEO:
+ return Constants.DemuxTsFilterType.VIDEO;
+ case TunerConstants.FILTER_SUBTYPE_PCR:
+ return Constants.DemuxTsFilterType.PCR;
+ case TunerConstants.FILTER_SUBTYPE_RECORD:
+ return Constants.DemuxTsFilterType.RECORD;
+ case TunerConstants.FILTER_SUBTYPE_TEMI:
+ return Constants.DemuxTsFilterType.TEMI;
+ default:
+ break;
+ }
+ } else if (mainType == TunerConstants.FILTER_TYPE_MMTP) {
+ switch (subtype) {
+ case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
+ return Constants.DemuxMmtpFilterType.UNDEFINED;
+ case TunerConstants.FILTER_SUBTYPE_SECTION:
+ return Constants.DemuxMmtpFilterType.SECTION;
+ case TunerConstants.FILTER_SUBTYPE_PES:
+ return Constants.DemuxMmtpFilterType.PES;
+ case TunerConstants.FILTER_SUBTYPE_MMPT:
+ return Constants.DemuxMmtpFilterType.MMTP;
+ case TunerConstants.FILTER_SUBTYPE_AUDIO:
+ return Constants.DemuxMmtpFilterType.AUDIO;
+ case TunerConstants.FILTER_SUBTYPE_VIDEO:
+ return Constants.DemuxMmtpFilterType.VIDEO;
+ case TunerConstants.FILTER_SUBTYPE_RECORD:
+ return Constants.DemuxMmtpFilterType.RECORD;
+ case TunerConstants.FILTER_SUBTYPE_DOWNLOAD:
+ return Constants.DemuxMmtpFilterType.DOWNLOAD;
+ default:
+ break;
+ }
+
+ } else if (mainType == TunerConstants.FILTER_TYPE_IP) {
+ switch (subtype) {
+ case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
+ return Constants.DemuxIpFilterType.UNDEFINED;
+ case TunerConstants.FILTER_SUBTYPE_SECTION:
+ return Constants.DemuxIpFilterType.SECTION;
+ case TunerConstants.FILTER_SUBTYPE_NTP:
+ return Constants.DemuxIpFilterType.NTP;
+ case TunerConstants.FILTER_SUBTYPE_IP_PAYLOAD:
+ return Constants.DemuxIpFilterType.IP_PAYLOAD;
+ case TunerConstants.FILTER_SUBTYPE_IP:
+ return Constants.DemuxIpFilterType.IP;
+ case TunerConstants.FILTER_SUBTYPE_PAYLOAD_THROUGH:
+ return Constants.DemuxIpFilterType.PAYLOAD_THROUGH;
+ default:
+ break;
+ }
+ } else if (mainType == TunerConstants.FILTER_TYPE_TLV) {
+ switch (subtype) {
+ case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
+ return Constants.DemuxTlvFilterType.UNDEFINED;
+ case TunerConstants.FILTER_SUBTYPE_SECTION:
+ return Constants.DemuxTlvFilterType.SECTION;
+ case TunerConstants.FILTER_SUBTYPE_TLV:
+ return Constants.DemuxTlvFilterType.TLV;
+ case TunerConstants.FILTER_SUBTYPE_PAYLOAD_THROUGH:
+ return Constants.DemuxTlvFilterType.PAYLOAD_THROUGH;
+ default:
+ break;
+ }
+ } else if (mainType == TunerConstants.FILTER_TYPE_ALP) {
+ switch (subtype) {
+ case TunerConstants.FILTER_SUBTYPE_UNDEFINED:
+ return Constants.DemuxAlpFilterType.UNDEFINED;
+ case TunerConstants.FILTER_SUBTYPE_SECTION:
+ return Constants.DemuxAlpFilterType.SECTION;
+ case TunerConstants.FILTER_SUBTYPE_PTP:
+ return Constants.DemuxAlpFilterType.PTP;
+ case TunerConstants.FILTER_SUBTYPE_PAYLOAD_THROUGH:
+ return Constants.DemuxAlpFilterType.PAYLOAD_THROUGH;
+ default:
+ break;
+ }
+ }
+ throw new IllegalArgumentException(
+ "Invalid filter types. Main type=" + mainType + ", subtype=" + subtype);
+ }
+
+ private TunerUtils() {}
+}
diff --git a/media/jni/android_media_MediaMetricsJNI.cpp b/media/jni/android_media_MediaMetricsJNI.cpp
index 37aca08643b2..c064de299b19 100644
--- a/media/jni/android_media_MediaMetricsJNI.cpp
+++ b/media/jni/android_media_MediaMetricsJNI.cpp
@@ -18,6 +18,7 @@
#include <binder/Parcel.h>
#include <jni.h>
+#include <media/IMediaMetricsService.h>
#include <media/MediaMetricsItem.h>
#include <nativehelper/JNIHelp.h>
#include <variant>
@@ -120,15 +121,15 @@ jobject MediaMetricsJNI::writeMetricsToBundle(
return nullptr;
}
- bh.put("__key", item->getKey().c_str());
+ bh.put(mediametrics::BUNDLE_KEY, item->getKey().c_str());
if (item->getPid() != -1) {
- bh.put("__pid", (int32_t)item->getPid());
+ bh.put(mediametrics::BUNDLE_PID, (int32_t)item->getPid());
}
if (item->getTimestamp() > 0) {
- bh.put("__timestamp", (int64_t)item->getTimestamp());
+ bh.put(mediametrics::BUNDLE_TIMESTAMP, (int64_t)item->getTimestamp());
}
if (item->getUid() != -1) {
- bh.put("__uid", (int32_t)item->getUid());
+ bh.put(mediametrics::BUNDLE_UID, (int32_t)item->getUid());
}
for (const auto &prop : *item) {
const char *name = prop.getName();
@@ -150,14 +151,12 @@ static jint android_media_MediaMetrics_submit_bytebuffer(
return (jint)BAD_VALUE;
}
- // TODO: directly record item to MediaMetrics service.
- mediametrics::Item item;
- if (item.readFromByteString((char *)buffer, length) != NO_ERROR) {
- ALOGW("%s: cannot read from byte string", __func__);
- return (jint)BAD_VALUE;
+ sp<IMediaMetricsService> service = mediametrics::BaseItem::getService();
+ if (service == nullptr) {
+ ALOGW("Cannot retrieve mediametrics service");
+ return (jint)NO_INIT;
}
- item.selfrecord();
- return (jint)NO_ERROR;
+ return (jint)service->submitBuffer((char *)buffer, length);
}
// Helper function to convert a native PersistableBundle to a Java
diff --git a/media/jni/android_media_MediaMuxer.cpp b/media/jni/android_media_MediaMuxer.cpp
index f0aa4c3f1ab6..0c1e9a2ad7bd 100644
--- a/media/jni/android_media_MediaMuxer.cpp
+++ b/media/jni/android_media_MediaMuxer.cpp
@@ -26,11 +26,15 @@
#include <unistd.h>
#include <fcntl.h>
+#include <android/api-level.h>
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaMuxer.h>
+extern "C" int android_get_application_target_sdk_version();
+
namespace android {
struct fields_t {
@@ -229,10 +233,31 @@ static void android_media_MediaMuxer_stop(JNIEnv *env, jclass /* clazz */,
status_t err = muxer->stop();
- if (err != OK) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "Failed to stop the muxer");
- return;
+ if (android_get_application_target_sdk_version() >= __ANDROID_API_R__) {
+ switch (err) {
+ case OK:
+ break;
+ case ERROR_IO: {
+ jniThrowException(env, "java/lang/UncheckedIOException",
+ "Muxer stopped unexpectedly");
+ return;
+ }
+ case ERROR_MALFORMED: {
+ jniThrowException(env, "java/io/IOError",
+ "Failure of reading or writing operation");
+ return;
+ }
+ default: {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Failed to stop the muxer");
+ return;
+ }
+ }
+ } else {
+ if (err != OK) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Failed to stop the muxer");
+ return;
+ }
}
}
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 9304450dc271..0cac2af9adc3 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -312,6 +312,15 @@ int JTuner::tune(const FrontendSettings& settings) {
return (int)result;
}
+int JTuner::scan(const FrontendSettings& settings, FrontendScanType scanType) {
+ if (mFe == NULL) {
+ ALOGE("frontend is not initialized");
+ return (int)Result::INVALID_STATE;
+ }
+ Result result = mFe->scan(settings, scanType);
+ return (int)result;
+}
+
bool JTuner::openDemux() {
if (mTuner == nullptr) {
return false;
@@ -600,6 +609,25 @@ static int android_media_tv_Tuner_tune(JNIEnv *env, jobject thiz, jint type, job
return tuner->tune(getFrontendSettings(env, type, settings));
}
+static int android_media_tv_Tuner_stop_tune(JNIEnv, jobject) {
+ return 0;
+}
+
+static int android_media_tv_Tuner_scan(
+ JNIEnv *env, jobject thiz, jint settingsType, jobject settings, jint scanType) {
+ sp<JTuner> tuner = getTuner(env, thiz);
+ return tuner->scan(getFrontendSettings(
+ env, settingsType, settings), static_cast<FrontendScanType>(scanType));
+}
+
+static int android_media_tv_Tuner_set_lnb(JNIEnv, jobject, jint) {
+ return 0;
+}
+
+static int android_media_tv_Tuner_set_lna(JNIEnv, jobject, jint, jboolean) {
+ return 0;
+}
+
static jobject android_media_tv_Tuner_get_lnb_ids(JNIEnv *env, jobject thiz) {
sp<JTuner> tuner = getTuner(env, thiz);
return tuner->getLnbIds();
@@ -850,6 +878,11 @@ static const JNINativeMethod gTunerMethods[] = {
(void *)android_media_tv_Tuner_open_frontend_by_id },
{ "nativeTune", "(ILandroid/media/tv/tuner/FrontendSettings;)I",
(void *)android_media_tv_Tuner_tune },
+ { "nativeStopTune", "()I", (void *)android_media_tv_Tuner_stop_tune },
+ { "nativeScan", "(ILandroid/media/tv/tuner/FrontendSettings;I)I",
+ (void *)android_media_tv_Tuner_scan },
+ { "nativeSetLnb", "(I)I", (void *)android_media_tv_Tuner_set_lnb },
+ { "nativeSetLna", "(Z)I", (void *)android_media_tv_Tuner_set_lna },
{ "nativeOpenFilter", "(III)Landroid/media/tv/tuner/Tuner$Filter;",
(void *)android_media_tv_Tuner_open_filter },
{ "nativeGetLnbIds", "()Ljava/util/List;",
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index 9f9fb2748581..d37a2d96c60b 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -39,6 +39,7 @@ using ::android::hardware::tv::tuner::V1_0::FrontendEventType;
using ::android::hardware::tv::tuner::V1_0::FrontendId;
using ::android::hardware::tv::tuner::V1_0::FrontendScanMessage;
using ::android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
+using ::android::hardware::tv::tuner::V1_0::FrontendScanType;
using ::android::hardware::tv::tuner::V1_0::FrontendSettings;
using ::android::hardware::tv::tuner::V1_0::IDemux;
using ::android::hardware::tv::tuner::V1_0::IDescrambler;
@@ -122,6 +123,7 @@ struct JTuner : public RefBase {
jobject getFrontendIds();
jobject openFrontendById(int id);
int tune(const FrontendSettings& settings);
+ int scan(const FrontendSettings& settings, FrontendScanType scanType);
jobject getLnbIds();
jobject openLnbById(int id);
jobject openFilter(DemuxFilterType type, int bufferSize);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraErrorCollector.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraErrorCollector.java
index 6facec4bfe5b..41914b887b2b 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraErrorCollector.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraErrorCollector.java
@@ -969,7 +969,7 @@ public class CameraErrorCollector extends ErrorCollector {
*/
private static class IntInMatcher extends InMatcher<Integer> {
public IntInMatcher(int[] values) {
- Preconditions.checkNotNull("values", values);
+ Objects.requireNonNull(values, "values");
mValues = new ArrayList<>(values.length);
for (int i : values) {
mValues.add(i);
@@ -1005,7 +1005,7 @@ public class CameraErrorCollector extends ErrorCollector {
*/
private static class BooleanInMatcher extends InMatcher<Boolean> {
public BooleanInMatcher(boolean[] values) {
- Preconditions.checkNotNull("values", values);
+ Objects.requireNonNull(values, "values");
mValues = new ArrayList<>(values.length);
for (boolean i : values) {
mValues.add(i);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/InMatcher.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/InMatcher.java
index e25a140378d8..c77a042ae38b 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/InMatcher.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/InMatcher.java
@@ -36,7 +36,7 @@ public class InMatcher<T> extends BaseMatcher<T> {
protected Collection<T> mValues;
public InMatcher(Collection<T> values) {
- Preconditions.checkNotNull("values", values);
+ Objects.requireNonNull(values, "values");
mValues = values;
}
diff --git a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
index 6650f9618638..df6345fb7db0 100644
--- a/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouteProvider/src/com/android/mediarouteprovider/example/SampleMediaRoute2ProviderService.java
@@ -20,6 +20,7 @@ import android.content.Intent;
import android.media.MediaRoute2Info;
import android.media.MediaRoute2ProviderInfo;
import android.media.MediaRoute2ProviderService;
+import android.media.RouteSessionInfo;
import android.os.Bundle;
import android.os.IBinder;
@@ -159,10 +160,55 @@ public class SampleMediaRoute2ProviderService extends MediaRoute2ProviderService
publishRoutes();
}
+ @Override
+ public void onCreateSession(String packageName, String routeId, String controlCategory,
+ int sessionId) {
+ RouteSessionInfo sessionInfo = new RouteSessionInfo.Builder(
+ sessionId, packageName, controlCategory)
+ .addSelectedRoute(routeId)
+ .build();
+ notifySessionCreated(sessionId, sessionInfo, null);
+ }
+
+ @Override
+ public void onDestroySession(int sessionId, RouteSessionInfo lastSessionInfo) {}
+
+ @Override
+ public void onAddRoute(int sessionId, String routeId) {
+ RouteSessionInfo sessionInfo = getSessionInfo(sessionId);
+ //TODO: we may want to remove route if it belongs to another session
+ RouteSessionInfo newSessionInfo = new RouteSessionInfo.Builder(sessionInfo)
+ .addSelectedRoute(routeId)
+ .build();
+ setSessionInfo(sessionId, newSessionInfo);
+ publishRoutes();
+ }
+
+ @Override
+ public void onRemoveRoute(int sessionId, String routeId) {
+ RouteSessionInfo sessionInfo = getSessionInfo(sessionId);
+ RouteSessionInfo newSessionInfo = new RouteSessionInfo.Builder(sessionInfo)
+ .removeSelectedRoute(routeId)
+ .build();
+ setSessionInfo(sessionId, newSessionInfo);
+ publishRoutes();
+ }
+
+ @Override
+ public void onTransferRoute(int sessionId, String routeId) {
+ RouteSessionInfo sessionInfo = getSessionInfo(sessionId);
+ RouteSessionInfo newSessionInfo = new RouteSessionInfo.Builder(sessionInfo)
+ .clearSelectedRoutes()
+ .addSelectedRoute(routeId)
+ .build();
+ setSessionInfo(sessionId, newSessionInfo);
+ publishRoutes();
+ }
+
void publishRoutes() {
MediaRoute2ProviderInfo info = new MediaRoute2ProviderInfo.Builder()
.addRoutes(mRoutes.values())
.build();
- setProviderInfo(info);
+ updateProviderInfo(info);
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java
index ab1feefd8b3c..38d5211bd0d4 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/CarDeviceProvisionedControllerImpl.java
@@ -27,7 +27,7 @@ import android.provider.Settings;
import com.android.systemui.Dependency;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
import javax.inject.Inject;
@@ -54,7 +54,7 @@ public class CarDeviceProvisionedControllerImpl extends DeviceProvisionedControl
private final ContentResolver mContentResolver;
@Inject
- public CarDeviceProvisionedControllerImpl(Context context, @MainHandler Handler mainHandler,
+ public CarDeviceProvisionedControllerImpl(Context context, @Main Handler mainHandler,
BroadcastDispatcher broadcastDispatcher) {
super(context, mainHandler, broadcastDispatcher);
mContentResolver = context.getContentResolver();
diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
index e0b0922e913f..59a084e337ad 100644
--- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java
@@ -35,7 +35,7 @@ import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.CarDeviceProvisionedListener;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NavigationBarController;
@@ -93,7 +93,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
DeviceProvisionedController deviceProvisionedController,
CommandQueue commandQueue,
Lazy<FacetButtonTaskStackListener> facetButtonTaskStackListenerLazy,
- @MainHandler Handler mainHandler,
+ @Main Handler mainHandler,
Lazy<KeyguardStateController> keyguardStateControllerLazy,
Lazy<NavigationBarController> navigationBarControllerLazy,
SuperStatusBarViewFactory superStatusBarViewFactory,
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 1b171e87bf4a..867100fe5351 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -59,7 +59,6 @@ import com.android.systemui.BatteryMeterView;
import com.android.systemui.Dependency;
import com.android.systemui.Prefs;
import com.android.systemui.R;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
@@ -68,6 +67,7 @@ import com.android.systemui.car.CarDeviceProvisionedListener;
import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.classifier.FalsingLog;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -141,6 +141,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Optional;
+import java.util.concurrent.Executor;
import javax.inject.Named;
import javax.inject.Provider;
@@ -273,7 +274,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
NotificationAlertingManager notificationAlertingManager,
DisplayMetrics displayMetrics,
MetricsLogger metricsLogger,
- UiOffloadThread uiOffloadThread,
+ @UiBackground Executor uiBgExecutor,
NotificationMediaManager notificationMediaManager,
NotificationLockscreenUserManager lockScreenUserManager,
NotificationRemoteInputManager remoteInputManager,
@@ -353,7 +354,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
notificationAlertingManager,
displayMetrics,
metricsLogger,
- uiOffloadThread,
+ uiBgExecutor,
notificationMediaManager,
lockScreenUserManager,
remoteInputManager,
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
index 7b21d9d8a2d7..e3bb293fa6f9 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
@@ -25,12 +25,12 @@ import android.util.DisplayMetrics;
import com.android.internal.logging.MetricsLogger;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
@@ -96,6 +96,7 @@ import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.volume.VolumeComponent;
import java.util.Optional;
+import java.util.concurrent.Executor;
import javax.inject.Named;
import javax.inject.Provider;
@@ -143,7 +144,7 @@ public class CarStatusBarModule {
NotificationAlertingManager notificationAlertingManager,
DisplayMetrics displayMetrics,
MetricsLogger metricsLogger,
- UiOffloadThread uiOffloadThread,
+ @UiBackground Executor uiBgExecutor,
NotificationMediaManager notificationMediaManager,
NotificationLockscreenUserManager lockScreenUserManager,
NotificationRemoteInputManager remoteInputManager,
@@ -222,7 +223,7 @@ public class CarStatusBarModule {
notificationAlertingManager,
displayMetrics,
metricsLogger,
- uiOffloadThread,
+ uiBgExecutor,
notificationMediaManager,
lockScreenUserManager,
remoteInputManager,
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
index 2d57be177333..b2f8aad77dd4 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
@@ -37,7 +37,7 @@ import android.widget.TextView;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -68,7 +68,7 @@ class CarTrustAgentUnlockDialogHelper extends BroadcastReceiver{
private OnHideListener mOnHideListener;
@Inject
- CarTrustAgentUnlockDialogHelper(Context context, @MainResources Resources resources,
+ CarTrustAgentUnlockDialogHelper(Context context, @Main Resources resources,
UserManager userManager, WindowManager windowManager) {
mContext = context;
mResources = resources;
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 3d7486859686..f8fc3bbefb01 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -38,7 +38,7 @@ import androidx.recyclerview.widget.GridLayoutManager;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.R;
import com.android.systemui.car.CarServiceProvider;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.car.CarTrustAgentUnlockDialogHelper.OnHideListener;
import com.android.systemui.statusbar.car.UserGridRecyclerView.UserRecord;
@@ -78,7 +78,7 @@ public class FullscreenUserSwitcher {
@Inject
public FullscreenUserSwitcher(
Context context,
- @MainResources Resources resources,
+ @Main Resources resources,
UserManager userManager,
CarServiceProvider carServiceProvider,
CarTrustAgentUnlockDialogHelper carTrustAgentUnlockDialogHelper) {
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index d11b5c573ca9..7aa997e39307 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -37,12 +37,12 @@ import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
+import android.companion.Association;
import android.companion.AssociationRequest;
import android.companion.BluetoothDeviceFilter;
import android.companion.BluetoothLeDeviceFilter;
import android.companion.DeviceFilter;
import android.companion.ICompanionDeviceDiscoveryService;
-import android.companion.ICompanionDeviceDiscoveryServiceCallback;
import android.companion.IFindDeviceCallback;
import android.companion.WifiDeviceFilter;
import android.content.BroadcastReceiver;
@@ -63,6 +63,7 @@ import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
+import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.Preconditions;
@@ -97,7 +98,7 @@ public class DeviceDiscoveryService extends Service {
DevicesAdapter mDevicesAdapter;
IFindDeviceCallback mFindCallback;
- ICompanionDeviceDiscoveryServiceCallback mServiceCallback;
+ AndroidFuture<Association> mServiceCallback;
boolean mIsScanning = false;
@Nullable DeviceChooserActivity mActivity = null;
@@ -107,7 +108,7 @@ public class DeviceDiscoveryService extends Service {
public void startDiscovery(AssociationRequest request,
String callingPackage,
IFindDeviceCallback findCallback,
- ICompanionDeviceDiscoveryServiceCallback serviceCallback) {
+ AndroidFuture serviceCallback) {
if (DEBUG) {
Log.i(LOG_TAG,
"startDiscovery() called with: filter = [" + request
@@ -303,23 +304,12 @@ public class DeviceDiscoveryService extends Service {
}
void onDeviceSelected(String callingPackage, String deviceAddress) {
- try {
- mServiceCallback.onDeviceSelected(
- //TODO is this the right userId?
- callingPackage, getUserId(), deviceAddress);
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Failed to record association: "
- + callingPackage + " <-> " + deviceAddress);
- }
+ mServiceCallback.complete(new Association(getUserId(), deviceAddress, callingPackage));
}
void onCancel() {
if (DEBUG) Log.i(LOG_TAG, "onCancel()");
- try {
- mServiceCallback.onDeviceSelectionCancel();
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
+ mServiceCallback.cancel(true);
}
class DevicesAdapter extends ArrayAdapter<DeviceFilterPair> {
diff --git a/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp b/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp
index de92fcd5b2e8..4e49302debcd 100644
--- a/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp
+++ b/packages/Incremental/NativeAdbDataLoader/jni/com_android_incremental_nativeadb_DataLoaderService.cpp
@@ -177,8 +177,7 @@ private:
android::dataloader::ServiceParamsPtr) final {
CHECK(ifs) << "ifs can't be null";
CHECK(statusListener) << "statusListener can't be null";
- ALOGE("[AdbDataLoader] onCreate: %s/%s/%d", params.staticArgs().c_str(),
- params.packageName().c_str(), (int)params.dynamicArgs().size());
+ ALOGE("[AdbDataLoader] onCreate: %d/%s/%s/%s/%d", params.type(), params.packageName().c_str(), params.className().c_str(), params.arguments().c_str(), (int)params.dynamicArgs().size());
if (params.dynamicArgs().empty()) {
ALOGE("[AdbDataLoader] Invalid DataLoaderParams. Need in/out FDs.");
@@ -204,7 +203,7 @@ private:
}
std::string logFile;
- if (const auto packageName = extractPackageName(params.staticArgs()); !packageName.empty()) {
+ if (const auto packageName = extractPackageName(params.arguments()); !packageName.empty()) {
logFile = android::base::GetProperty("adb.readlog." + packageName, "");
}
if (logFile.empty()) {
@@ -288,8 +287,7 @@ private:
"inode=%d. Ignore.",
static_cast<int>(ino));
mRequestedFiles.erase(fileId);
- mStatusListener->reportStatus(
- INCREMENTAL_DATA_LOADER_NO_CONNECTION);
+ mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
}
}
sendRequest(mOutFd, BLOCK_MISSING, fileId, blockIdx);
@@ -337,7 +335,7 @@ private:
}
if (res < 0) {
ALOGE("[AdbDataLoader] failed to poll. Abort.");
- mStatusListener->reportStatus(INCREMENTAL_DATA_LOADER_NO_CONNECTION);
+ mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
break;
}
if (res == mEventFd) {
@@ -346,7 +344,7 @@ private:
}
if (!readChunk(mInFd, data)) {
ALOGE("[AdbDataLoader] failed to read a message. Abort.");
- mStatusListener->reportStatus(INCREMENTAL_DATA_LOADER_NO_CONNECTION);
+ mStatusListener->reportStatus(DATA_LOADER_NO_CONNECTION);
break;
}
auto remainingData = std::span(data);
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
index 23e2949372aa..ebca962a918e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java
@@ -46,7 +46,7 @@ public class DataUsageUtils {
}
final String[] mergedSubscriberIds = telephonyManager.createForSubscriptionId(subId)
- .getMergedSubscriberIdsFromGroup();
+ .getMergedImsisFromGroup();
if (ArrayUtils.isEmpty(mergedSubscriberIds)) {
Log.i(TAG, "mergedSubscriberIds is null.");
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
index 5cae6116a59c..d98f50beadf5 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java
@@ -87,7 +87,7 @@ public class DataUsageUtilsTest {
public void getMobileTemplate_groupUuidNull_returnMobileAll() {
when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(mInfo1);
when(mInfo1.getGroupUuid()).thenReturn(null);
- when(mTelephonyManager.getMergedSubscriberIdsFromGroup())
+ when(mTelephonyManager.getMergedImsisFromGroup())
.thenReturn(new String[] {SUBSCRIBER_ID});
final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID);
@@ -99,7 +99,7 @@ public class DataUsageUtilsTest {
public void getMobileTemplate_groupUuidExist_returnMobileMerged() {
when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(mInfo1);
when(mInfo1.getGroupUuid()).thenReturn(mParcelUuid);
- when(mTelephonyManager.getMergedSubscriberIdsFromGroup())
+ when(mTelephonyManager.getMergedImsisFromGroup())
.thenReturn(new String[] {SUBSCRIBER_ID, SUBSCRIBER_ID_2});
final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID);
diff --git a/packages/SettingsProvider/res/values/blocked_settings.xml b/packages/SettingsProvider/res/values/blocked_settings.xml
new file mode 100644
index 000000000000..b54b74ee1d3e
--- /dev/null
+++ b/packages/SettingsProvider/res/values/blocked_settings.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!-- These are arrays of settings which should not be restored to this device -->
+<resources>
+ <string-array name="restore_blocked_device_specific_settings" />
+ <string-array name="restore_blocked_global_settings" />
+ <string-array name="restore_blocked_secure_settings" />
+ <string-array name="restore_blocked_system_settings" />
+</resources> \ No newline at end of file
diff --git a/packages/SettingsProvider/res/values/overlayable.xml b/packages/SettingsProvider/res/values/overlayable.xml
new file mode 100644
index 000000000000..dc41a77d0e2d
--- /dev/null
+++ b/packages/SettingsProvider/res/values/overlayable.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+ <overlayable name="SettingsToNotRestore">
+ <policy type="product|system|vendor">
+ <item type="array" name="restore_blocked_device_specific_settings" />
+ <item type="array" name="restore_blocked_global_settings" />
+ <item type="array" name="restore_blocked_secure_settings" />
+ <item type="array" name="restore_blocked_system_settings" />
+ </policy>
+ </overlayable>
+</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index c19a340498e7..fb558abe3865 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -66,6 +66,7 @@ import java.io.IOException;
import java.io.OutputStream;
import java.time.DateTimeException;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
@@ -250,7 +251,13 @@ public class SettingsBackupAgent extends BackupAgentHelper {
@Override
public void onRestore(BackupDataInput data, int appVersionCode,
- ParcelFileDescriptor newState) throws IOException {
+ ParcelFileDescriptor newState) {
+ throw new RuntimeException("SettingsBackupAgent has been migrated to use key exclusion");
+ }
+
+ @Override
+ public void onRestore(BackupDataInput data, long appVersionCode,
+ ParcelFileDescriptor newState, Set<String> dynamicBlockList) throws IOException {
if (DEBUG) {
Log.d(TAG, "onRestore(): appVersionCode: " + appVersionCode
@@ -266,7 +273,7 @@ public class SettingsBackupAgent extends BackupAgentHelper {
}
// versionCode of com.android.providers.settings corresponds to SDK_INT
- mRestoredFromSdkInt = appVersionCode;
+ mRestoredFromSdkInt = (int) appVersionCode;
HashSet<String> movedToGlobal = new HashSet<String>();
Settings.System.getMovedToGlobalSettings(movedToGlobal);
@@ -292,16 +299,29 @@ public class SettingsBackupAgent extends BackupAgentHelper {
switch (key) {
case KEY_SYSTEM :
restoreSettings(data, Settings.System.CONTENT_URI, movedToGlobal,
- movedToSecure);
+ movedToSecure, R.array.restore_blocked_system_settings,
+ dynamicBlockList);
mSettingsHelper.applyAudioSettings();
break;
case KEY_SECURE :
- restoreSettings(data, Settings.Secure.CONTENT_URI, movedToGlobal, null);
+ restoreSettings(
+ data,
+ Settings.Secure.CONTENT_URI,
+ movedToGlobal,
+ null,
+ R.array.restore_blocked_secure_settings,
+ dynamicBlockList);
break;
case KEY_GLOBAL :
- restoreSettings(data, Settings.Global.CONTENT_URI, null, movedToSecure);
+ restoreSettings(
+ data,
+ Settings.Global.CONTENT_URI,
+ null,
+ movedToSecure,
+ R.array.restore_blocked_global_settings,
+ dynamicBlockList);
break;
case KEY_WIFI_SUPPLICANT :
@@ -345,7 +365,10 @@ public class SettingsBackupAgent extends BackupAgentHelper {
case KEY_DEVICE_SPECIFIC_CONFIG:
byte[] restoredDeviceSpecificConfig = new byte[size];
data.readEntityData(restoredDeviceSpecificConfig, 0, size);
- restoreDeviceSpecificConfig(restoredDeviceSpecificConfig);
+ restoreDeviceSpecificConfig(
+ restoredDeviceSpecificConfig,
+ R.array.restore_blocked_device_specific_settings,
+ dynamicBlockList);
break;
default :
@@ -394,14 +417,22 @@ public class SettingsBackupAgent extends BackupAgentHelper {
byte[] buffer = new byte[nBytes];
in.readFully(buffer, 0, nBytes);
restoreSettings(buffer, nBytes, Settings.System.CONTENT_URI, movedToGlobal,
- movedToSecure);
+ movedToSecure, R.array.restore_blocked_system_settings,
+ Collections.emptySet());
// secure settings
nBytes = in.readInt();
if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of secure settings data");
if (nBytes > buffer.length) buffer = new byte[nBytes];
in.readFully(buffer, 0, nBytes);
- restoreSettings(buffer, nBytes, Settings.Secure.CONTENT_URI, movedToGlobal, null);
+ restoreSettings(
+ buffer,
+ nBytes,
+ Settings.Secure.CONTENT_URI,
+ movedToGlobal,
+ null,
+ R.array.restore_blocked_secure_settings,
+ Collections.emptySet());
// Global only if sufficiently new
if (version >= FULL_BACKUP_ADDED_GLOBAL) {
@@ -411,7 +442,8 @@ public class SettingsBackupAgent extends BackupAgentHelper {
in.readFully(buffer, 0, nBytes);
movedToGlobal.clear(); // no redirection; this *is* the global namespace
restoreSettings(buffer, nBytes, Settings.Global.CONTENT_URI, movedToGlobal,
- movedToSecure);
+ movedToSecure, R.array.restore_blocked_global_settings,
+ Collections.emptySet());
}
// locale
@@ -612,8 +644,13 @@ public class SettingsBackupAgent extends BackupAgentHelper {
return baos.toByteArray();
}
- private void restoreSettings(BackupDataInput data, Uri contentUri,
- HashSet<String> movedToGlobal, Set<String> movedToSecure) {
+ private void restoreSettings(
+ BackupDataInput data,
+ Uri contentUri,
+ HashSet<String> movedToGlobal,
+ Set<String> movedToSecure,
+ int blockedSettingsArrayId,
+ Set<String> dynamicBlockList) {
byte[] settings = new byte[data.getDataSize()];
try {
data.readEntityData(settings, 0, settings.length);
@@ -621,16 +658,44 @@ public class SettingsBackupAgent extends BackupAgentHelper {
Log.e(TAG, "Couldn't read entity data");
return;
}
- restoreSettings(settings, settings.length, contentUri, movedToGlobal, movedToSecure);
+ restoreSettings(
+ settings,
+ settings.length,
+ contentUri,
+ movedToGlobal,
+ movedToSecure,
+ blockedSettingsArrayId,
+ dynamicBlockList);
}
- private void restoreSettings(byte[] settings, int bytes, Uri contentUri,
- HashSet<String> movedToGlobal, Set<String> movedToSecure) {
- restoreSettings(settings, 0, bytes, contentUri, movedToGlobal, movedToSecure);
+ private void restoreSettings(
+ byte[] settings,
+ int bytes,
+ Uri contentUri,
+ HashSet<String> movedToGlobal,
+ Set<String> movedToSecure,
+ int blockedSettingsArrayId,
+ Set<String> dynamicBlockList) {
+ restoreSettings(
+ settings,
+ 0,
+ bytes,
+ contentUri,
+ movedToGlobal,
+ movedToSecure,
+ blockedSettingsArrayId,
+ dynamicBlockList);
}
- private void restoreSettings(byte[] settings, int pos, int bytes, Uri contentUri,
- HashSet<String> movedToGlobal, Set<String> movedToSecure) {
+ private void restoreSettings(
+ byte[] settings,
+ int pos,
+ int bytes,
+ Uri contentUri,
+ HashSet<String> movedToGlobal,
+ Set<String> movedToSecure,
+ int blockedSettingsArrayId,
+ Set<String> dynamicBlockList) {
if (DEBUG) {
Log.i(TAG, "restoreSettings: " + contentUri);
}
@@ -662,9 +727,20 @@ public class SettingsBackupAgent extends BackupAgentHelper {
SettingsHelper settingsHelper = mSettingsHelper;
ContentResolver cr = getContentResolver();
- final int whiteListSize = whitelist.length;
- for (int i = 0; i < whiteListSize; i++) {
- String key = whitelist[i];
+ Set<String> blockedSettings = getBlockedSettings(blockedSettingsArrayId);
+
+ for (String key : whitelist) {
+ boolean isBlockedBySystem = blockedSettings != null && blockedSettings.contains(key);
+ if (isBlockedBySystem || isBlockedByDynamicList(dynamicBlockList, contentUri, key)) {
+ Log.i(
+ TAG,
+ "Key "
+ + key
+ + " removed from restore by "
+ + (isBlockedBySystem ? "system" : "dynamic")
+ + " block list");
+ continue;
+ }
String value = null;
boolean hasValueToRestore = false;
@@ -722,6 +798,19 @@ public class SettingsBackupAgent extends BackupAgentHelper {
}
}
+ private boolean isBlockedByDynamicList(Set<String> dynamicBlockList, Uri areaUri, String key) {
+ String contentKey = Uri.withAppendedPath(areaUri, key).toString();
+ return dynamicBlockList.contains(contentKey);
+ }
+
+ // There may be other sources of blocked settings, so I'm separating out this
+ // code to make it easy to modify in the future.
+ @VisibleForTesting
+ protected Set<String> getBlockedSettings(int blockedSettingsArrayId) {
+ String[] blockedSettings = getResources().getStringArray(blockedSettingsArrayId);
+ return new HashSet<>(Arrays.asList(blockedSettings));
+ }
+
private boolean isValidSettingValue(String key, String value,
Map<String, Validator> validators) {
if (key == null || validators == null) {
@@ -998,10 +1087,13 @@ public class SettingsBackupAgent extends BackupAgentHelper {
* Restore the device specific settings.
*
* @param data The byte array holding a backed up version of another devices settings.
+ * @param blockedSettingsArrayId The string array resource holding the settings not to restore.
+ * @param dynamicBlocklist The dynamic list of settings not to restore fed into this agent.
* @return true if the restore succeeded, false if it was stopped.
*/
@VisibleForTesting
- boolean restoreDeviceSpecificConfig(byte[] data) {
+ boolean restoreDeviceSpecificConfig(byte[] data, int blockedSettingsArrayId,
+ Set<String> dynamicBlocklist) {
// We're using an AtomicInteger to wrap the position int and allow called methods to
// modify it.
AtomicInteger pos = new AtomicInteger(0);
@@ -1013,7 +1105,14 @@ public class SettingsBackupAgent extends BackupAgentHelper {
int dataStart = pos.get();
restoreSettings(
- data, dataStart, data.length, Settings.Secure.CONTENT_URI, null, null);
+ data,
+ dataStart,
+ data.length,
+ Settings.Secure.CONTENT_URI,
+ null,
+ null,
+ blockedSettingsArrayId,
+ dynamicBlocklist);
updateWindowManagerIfNeeded(originalDensity);
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
index 57e22db6a55c..e6508823c7e3 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
@@ -37,14 +37,14 @@ import android.test.mock.MockContentResolver;
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.annotations.VisibleForTesting;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -85,12 +85,33 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
assertEquals("Not all values backed up.", TEST_VALUES.keySet(), helper.mReadEntries);
- mAgentUnderTest.restoreDeviceSpecificConfig(settingsBackup);
+ mAgentUnderTest.restoreDeviceSpecificConfig(
+ settingsBackup,
+ R.array.restore_blocked_device_specific_settings,
+ Collections.emptySet());
assertEquals("Not all values were restored.", TEST_VALUES, helper.mWrittenValues);
}
@Test
+ public void testRoundTripDeviceSpecificSettingsWithBlock() throws IOException {
+ TestSettingsHelper helper = new TestSettingsHelper(mContext);
+ mAgentUnderTest.mSettingsHelper = helper;
+
+ byte[] settingsBackup = mAgentUnderTest.getDeviceSpecificConfiguration();
+
+ assertEquals("Not all values backed up.", TEST_VALUES.keySet(), helper.mReadEntries);
+ mAgentUnderTest.setBlockedSettings(TEST_VALUES.keySet().toArray(new String[0]));
+
+ mAgentUnderTest.restoreDeviceSpecificConfig(
+ settingsBackup,
+ R.array.restore_blocked_device_specific_settings,
+ Collections.emptySet());
+
+ assertTrue("Not all values were blocked.", helper.mWrittenValues.isEmpty());
+ }
+
+ @Test
public void testGeneratedHeaderMatchesCurrentDevice() throws IOException {
mAgentUnderTest.mSettingsHelper = new TestSettingsHelper(mContext);
@@ -148,7 +169,10 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
assertFalse(
"Blocking isSourceAcceptable did not stop restore",
- mAgentUnderTest.restoreDeviceSpecificConfig(data));
+ mAgentUnderTest.restoreDeviceSpecificConfig(
+ data,
+ R.array.restore_blocked_device_specific_settings,
+ Collections.emptySet()));
}
private byte[] generateUncorruptedHeader() throws IOException {
@@ -184,14 +208,34 @@ public class SettingsBackupAgentTest extends BaseSettingsProviderTest {
}
}
+ private byte[] generateSingleKeyTestBackupData(String key, String value) throws IOException {
+ try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
+ os.write(SettingsBackupAgent.toByteArray(key));
+ os.write(SettingsBackupAgent.toByteArray(value));
+ return os.toByteArray();
+ }
+ }
+
private static class TestFriendlySettingsBackupAgent extends SettingsBackupAgent {
private Boolean mForcedDeviceInfoRestoreAcceptability = null;
+ private String[] mBlockedSettings = null;
void setForcedDeviceInfoRestoreAcceptability(boolean value) {
mForcedDeviceInfoRestoreAcceptability = value;
}
- @VisibleForTesting
+ void setBlockedSettings(String... blockedSettings) {
+ mBlockedSettings = blockedSettings;
+ }
+
+ @Override
+ protected Set<String> getBlockedSettings(int blockedSettingsArrayId) {
+ return mBlockedSettings == null
+ ? super.getBlockedSettings(blockedSettingsArrayId)
+ : new HashSet<>(Arrays.asList(mBlockedSettings));
+ }
+
+ @Override
boolean isSourceAcceptable(byte[] data, AtomicInteger pos) {
return mForcedDeviceInfoRestoreAcceptability == null
? super.isSourceAcceptable(data, pos)
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 4fb3be2d588f..c238d7d49f9b 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -42,6 +42,7 @@ android_library {
"res",
],
static_libs: [
+ "WindowManager-Shell",
"SystemUIPluginLib",
"SystemUISharedLib",
"SettingsLib",
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java
index 18dc185c6fbe..0c7e56e0715e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java
@@ -37,6 +37,13 @@ public class ActivityCompat {
}
/**
+ * @see Activity#unregisterRemoteAnimations
+ */
+ public void unregisterRemoteAnimations() {
+ mWrapped.unregisterRemoteAnimations();
+ }
+
+ /**
* @see android.view.ViewDebug#dumpv2(View, ByteArrayOutputStream)
*/
public boolean encodeViewHierarchy(ByteArrayOutputStream out) {
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index caf5ee02df06..255693bd6471 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -43,7 +43,7 @@ import com.android.internal.telephony.TelephonyIntents;
import com.android.settingslib.WirelessUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import java.util.List;
@@ -608,7 +608,7 @@ public class CarrierTextController {
private boolean mShowMissingSim;
@Inject
- public Builder(Context context, @MainResources Resources resources) {
+ public Builder(Context context, @Main Resources resources) {
mContext = context;
mSeparator = resources.getString(
com.android.internal.R.string.kg_text_message_separator);
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index fb7a269863a2..694c623ac11f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -101,7 +101,7 @@ import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainLooper;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -1496,7 +1496,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@VisibleForTesting
@Inject
- protected KeyguardUpdateMonitor(Context context, @MainLooper Looper mainLooper,
+ protected KeyguardUpdateMonitor(Context context, @Main Looper mainLooper,
BroadcastDispatcher broadcastDispatcher,
DumpController dumpController) {
mContext = context;
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 94e7c68c831d..a9ca04b499a5 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -39,10 +39,8 @@ import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.dagger.qualifiers.BgHandler;
-import com.android.systemui.dagger.qualifiers.BgLooper;
-import com.android.systemui.dagger.qualifiers.MainHandler;
-import com.android.systemui.dagger.qualifiers.MainLooper;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.ScreenLifecycle;
@@ -297,10 +295,10 @@ public class Dependency {
@Inject Lazy<SensorPrivacyManager> mSensorPrivacyManager;
@Inject Lazy<AutoHideController> mAutoHideController;
@Inject Lazy<ForegroundServiceNotificationListener> mForegroundServiceNotificationListener;
- @Inject @BgLooper Lazy<Looper> mBgLooper;
- @Inject @BgHandler Lazy<Handler> mBgHandler;
- @Inject @MainLooper Lazy<Looper> mMainLooper;
- @Inject @MainHandler Lazy<Handler> mMainHandler;
+ @Inject @Background Lazy<Looper> mBgLooper;
+ @Inject @Background Lazy<Handler> mBgHandler;
+ @Inject @Main Lazy<Looper> mMainLooper;
+ @Inject @Main Lazy<Handler> mMainHandler;
@Inject @Named(TIME_TICK_HANDLER_NAME) Lazy<Handler> mTimeTickHandler;
@Nullable
@Inject @Named(LEAK_REPORT_EMAIL_NAME) Lazy<String> mLeakReportEmail;
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
index 41dd5bbf272b..82e665bdf5ac 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
@@ -24,7 +24,7 @@ import android.util.SparseArray;
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.util.Assert;
@@ -50,7 +50,7 @@ public class ForegroundServiceController {
@Inject
public ForegroundServiceController(NotificationEntryManager entryManager,
- AppOpsController appOpsController, @MainHandler Handler mainHandler) {
+ AppOpsController appOpsController, @Main Handler mainHandler) {
mEntryManager = entryManager;
mMainHandler = mainHandler;
appOpsController.addCallback(APP_OPS, (code, uid, packageName, active) -> {
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 9ce277eabbe8..0e736dcd11a8 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -68,7 +68,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.util.Preconditions;
import com.android.systemui.RegionInterceptingFrameLayout.RegionInterceptableView;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.plugins.qs.QS;
@@ -147,7 +147,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
@Inject
public ScreenDecorations(Context context,
Lazy<StatusBar> statusBarLazy,
- @MainHandler Handler handler,
+ @Main Handler handler,
BroadcastDispatcher broadcastDispatcher,
TunerService tunerService) {
super(context);
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index 164595742ae0..41d83148e093 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -27,7 +27,7 @@ import android.os.SystemProperties;
import android.util.Slog;
import com.android.internal.os.BinderInternal;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginManagerImpl;
@@ -41,7 +41,7 @@ public class SystemUIService extends Service {
private final Handler mMainHandler;
@Inject
- public SystemUIService(@MainHandler Handler mainHandler) {
+ public SystemUIService(@Main Handler mainHandler) {
super();
mMainHandler = mainHandler;
}
diff --git a/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java b/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java
index a726b42f714f..d5a46de980f9 100644
--- a/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java
+++ b/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui;
@@ -36,7 +36,7 @@ public class UiOffloadThread {
public UiOffloadThread() {
}
- public Future<?> submit(Runnable runnable) {
+ public Future<?> execute(Runnable runnable) {
return mExecutorService.submit(runnable);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
index 6178ff2ab2cb..895207d37816 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
@@ -22,7 +22,7 @@ import android.os.Handler;
import android.provider.Settings;
import com.android.systemui.SystemUI;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -36,7 +36,7 @@ public class WindowMagnification extends SystemUI {
private final Handler mHandler;
@Inject
- public WindowMagnification(Context context, @MainHandler Handler mainHandler) {
+ public WindowMagnification(Context context, @Main Handler mainHandler) {
super(context);
mHandler = mainHandler;
}
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index bad6b5458aa3..b0831232bcd4 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -30,7 +30,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.Background;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -81,7 +81,7 @@ public class AppOpsControllerImpl implements AppOpsController,
};
@Inject
- public AppOpsControllerImpl(Context context, @BgLooper Looper bgLooper,
+ public AppOpsControllerImpl(Context context, @Background Looper bgLooper,
DumpController dumpController) {
this(context, bgLooper, new PermissionFlagsCache(context), dumpController);
}
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
index 5cc70bc27c2a..8cb0cc5db1d3 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
@@ -28,8 +28,8 @@ import android.util.Log
import android.util.SparseArray
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.Dumpable
-import com.android.systemui.dagger.qualifiers.BgLooper
-import com.android.systemui.dagger.qualifiers.MainHandler
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
import java.io.FileDescriptor
import java.io.PrintWriter
import javax.inject.Inject
@@ -62,8 +62,8 @@ private const val DEBUG = true
@Singleton
open class BroadcastDispatcher @Inject constructor (
private val context: Context,
- @MainHandler private val mainHandler: Handler,
- @BgLooper private val bgLooper: Looper
+ @Main private val mainHandler: Handler,
+ @Background private val bgLooper: Looper
) : Dumpable {
// Only modify in BG thread
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
index 20742d6d2358..eb014ed0fc48 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
@@ -37,8 +37,8 @@ import com.android.internal.logging.MetricsLogger;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dependency;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.analytics.DataCollector;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
@@ -46,6 +46,7 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.util.sensors.AsyncSensorManager;
import java.io.PrintWriter;
+import java.util.concurrent.Executor;
/**
* When the phone is locked, listens to touch, sensor and phone events and sends them to
@@ -77,7 +78,7 @@ public class FalsingManagerImpl implements FalsingManager {
private final DataCollector mDataCollector;
private final HumanInteractionClassifier mHumanInteractionClassifier;
private final AccessibilityManager mAccessibilityManager;
- private final UiOffloadThread mUiOffloadThread;
+ private final Executor mUiBgExecutor;
private boolean mEnforceBouncer = false;
private boolean mBouncerOn = false;
@@ -137,13 +138,13 @@ public class FalsingManagerImpl implements FalsingManager {
}
};
- FalsingManagerImpl(Context context) {
+ FalsingManagerImpl(Context context, @UiBackground Executor uiBgExecutor) {
mContext = context;
mSensorManager = Dependency.get(AsyncSensorManager.class);
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
mDataCollector = DataCollector.getInstance(mContext);
mHumanInteractionClassifier = HumanInteractionClassifier.getInstance(mContext);
- mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+ mUiBgExecutor = uiBgExecutor;
mScreenOn = context.getSystemService(PowerManager.class).isInteractive();
mMetricsLogger = new MetricsLogger();
@@ -196,7 +197,7 @@ public class FalsingManagerImpl implements FalsingManager {
}
// This can be expensive, and doesn't need to happen on the main thread.
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
mSensorManager.unregisterListener(mSensorEventListener);
});
}
@@ -237,7 +238,7 @@ public class FalsingManagerImpl implements FalsingManager {
if (s != null) {
// This can be expensive, and doesn't need to happen on the main thread.
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
mSensorManager.registerListener(
mSensorEventListener, s, SensorManager.SENSOR_DELAY_GAME);
});
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
index db85fa0a3203..f475948b43f7 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java
@@ -30,7 +30,8 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.classifier.brightline.BrightLineFalsingManager;
import com.android.systemui.classifier.brightline.FalsingDataProvider;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.FalsingPlugin;
import com.android.systemui.plugins.PluginListener;
@@ -39,6 +40,7 @@ import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.sensors.ProximitySensor;
import java.io.PrintWriter;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -58,13 +60,16 @@ public class FalsingManagerProxy implements FalsingManager {
private DeviceConfig.OnPropertiesChangedListener mDeviceConfigListener;
private final DeviceConfigProxy mDeviceConfig;
private boolean mBrightlineEnabled;
+ private Executor mUiBgExecutor;
@Inject
FalsingManagerProxy(Context context, PluginManager pluginManager,
- @MainHandler Handler handler,
+ @Main Handler handler,
ProximitySensor proximitySensor,
- DeviceConfigProxy deviceConfig) {
+ DeviceConfigProxy deviceConfig,
+ @UiBackground Executor uiBgExecutor) {
mProximitySensor = proximitySensor;
+ mUiBgExecutor = uiBgExecutor;
mProximitySensor.setTag(PROXIMITY_SENSOR_TAG);
mProximitySensor.setSensorDelay(SensorManager.SENSOR_DELAY_GAME);
mDeviceConfig = deviceConfig;
@@ -87,7 +92,7 @@ public class FalsingManagerProxy implements FalsingManager {
}
public void onPluginDisconnected(FalsingPlugin plugin) {
- mInternalFalsingManager = new FalsingManagerImpl(context);
+ mInternalFalsingManager = new FalsingManagerImpl(context, mUiBgExecutor);
}
};
@@ -117,7 +122,7 @@ public class FalsingManagerProxy implements FalsingManager {
mInternalFalsingManager.cleanup();
}
if (!brightlineEnabled) {
- mInternalFalsingManager = new FalsingManagerImpl(context);
+ mInternalFalsingManager = new FalsingManagerImpl(context, mUiBgExecutor);
} else {
mInternalFalsingManager = new BrightLineFalsingManager(
new FalsingDataProvider(context.getResources().getDisplayMetrics()),
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index 0d161ceeecd5..8d10552332ba 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -25,8 +25,6 @@ import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.display.NightDisplayListener;
import android.os.Handler;
import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.Process;
import android.os.ServiceManager;
import android.util.DisplayMetrics;
import android.view.IWindowManager;
@@ -35,10 +33,8 @@ import android.view.LayoutInflater;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.dagger.qualifiers.BgHandler;
-import com.android.systemui.dagger.qualifiers.BgLooper;
-import com.android.systemui.dagger.qualifiers.MainHandler;
-import com.android.systemui.dagger.qualifiers.MainLooper;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.AlwaysOnDisplayPolicy;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.PluginInitializerImpl;
@@ -82,35 +78,6 @@ public class DependencyProvider {
return new Handler(thread.getLooper());
}
- @Singleton
- @Provides
- @BgLooper
- public Looper provideBgLooper() {
- HandlerThread thread = new HandlerThread("SysUiBg",
- Process.THREAD_PRIORITY_BACKGROUND);
- thread.start();
- return thread.getLooper();
- }
-
- /** Main Looper */
- @Provides
- @MainLooper
- public Looper provideMainLooper() {
- return Looper.getMainLooper();
- }
-
- @Provides
- @BgHandler
- public Handler provideBgHandler(@BgLooper Looper bgLooper) {
- return new Handler(bgLooper);
- }
-
- @Provides
- @MainHandler
- public Handler provideMainHandler(@MainLooper Looper mainLooper) {
- return new Handler(mainLooper);
- }
-
/** */
@Provides
public AmbientDisplayConfiguration provideAmbientDispalyConfiguration(Context context) {
@@ -175,7 +142,7 @@ public class DependencyProvider {
@Singleton
@Provides
public NightDisplayListener provideNightDisplayListener(Context context,
- @BgHandler Handler bgHandler) {
+ @Background Handler bgHandler) {
return new NightDisplayListener(context, bgHandler);
}
@@ -188,7 +155,7 @@ public class DependencyProvider {
@Singleton
@Provides
public NavigationBarController provideNavigationBarController(Context context,
- @MainHandler Handler mainHandler, CommandQueue commandQueue) {
+ @Main Handler mainHandler, CommandQueue commandQueue) {
return new NavigationBarController(context, mainHandler, commandQueue);
}
@@ -201,7 +168,7 @@ public class DependencyProvider {
@Singleton
@Provides
public AutoHideController provideAutoHideController(Context context,
- @MainHandler Handler mainHandler,
+ @Main Handler mainHandler,
NotificationRemoteInputManager notificationRemoteInputManager,
IWindowManager iWindowManager) {
return new AutoHideController(context, mainHandler, notificationRemoteInputManager,
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
index 534f350e4898..0b73ab6f9136 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
@@ -44,8 +44,8 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.LatencyTracker;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.systemui.dagger.qualifiers.BgHandler;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shared.system.PackageManagerWrapper;
import javax.inject.Singleton;
@@ -126,7 +126,7 @@ public class SystemServicesModule {
@Provides
@Nullable
static LocalBluetoothManager provideLocalBluetoothController(Context context,
- @BgHandler Handler bgHandler) {
+ @Background Handler bgHandler) {
return LocalBluetoothManager.create(context, bgHandler, UserHandle.ALL);
}
@@ -150,7 +150,7 @@ public class SystemServicesModule {
}
@Provides
- @MainResources
+ @Main
static Resources provideResources(Context context) {
return context.getResources();
}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainResources.java b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainResources.java
deleted file mode 100644
index 3daeda550b4c..000000000000
--- a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainResources.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.dagger.qualifiers;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface MainResources {
- // TODO: use attribute to get other, non-main resources?
-}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainHandler.java b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/UiBackground.java
index 79661fa4a738..bf2237aa8c11 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/MainHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/UiBackground.java
@@ -23,8 +23,12 @@ import java.lang.annotation.Retention;
import javax.inject.Qualifier;
+
+/**
+ * An annotation for injecting instances related to UI operations off the main-thread.
+ */
@Qualifier
@Documented
@Retention(RUNTIME)
-public @interface MainHandler {
+public @interface UiBackground {
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
index 25ac8f868435..f6f3b9985371 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/DismissCallbackRegistry.java
@@ -11,16 +11,16 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.keyguard;
import com.android.internal.policy.IKeyguardDismissCallback;
-import com.android.systemui.Dependency;
-import com.android.systemui.UiOffloadThread;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import java.util.ArrayList;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -32,10 +32,12 @@ import javax.inject.Singleton;
public class DismissCallbackRegistry {
private final ArrayList<DismissCallbackWrapper> mDismissCallbacks = new ArrayList<>();
- private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+ private final Executor mUiBgExecutor;
@Inject
- public DismissCallbackRegistry() {}
+ public DismissCallbackRegistry(@UiBackground Executor uiBgExecutor) {
+ mUiBgExecutor = uiBgExecutor;
+ }
public void addCallback(IKeyguardDismissCallback callback) {
mDismissCallbacks.add(new DismissCallbackWrapper(callback));
@@ -44,7 +46,7 @@ public class DismissCallbackRegistry {
public void notifyDismissCancelled() {
for (int i = mDismissCallbacks.size() - 1; i >= 0; i--) {
DismissCallbackWrapper callback = mDismissCallbacks.get(i);
- mUiOffloadThread.submit(callback::notifyDismissCancelled);
+ mUiBgExecutor.execute(callback::notifyDismissCancelled);
}
mDismissCallbacks.clear();
}
@@ -52,7 +54,7 @@ public class DismissCallbackRegistry {
public void notifyDismissSucceeded() {
for (int i = mDismissCallbacks.size() - 1; i >= 0; i--) {
DismissCallbackWrapper callback = mDismissCallbacks.get(i);
- mUiOffloadThread.submit(callback::notifyDismissSucceeded);
+ mUiBgExecutor.execute(callback::notifyDismissSucceeded);
}
mDismissCallbacks.clear();
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index beba203b9702..9fcf0221e41a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.keyguard;
@@ -81,8 +81,8 @@ import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -95,6 +95,7 @@ import com.android.systemui.util.InjectionInflationController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -211,7 +212,7 @@ public class KeyguardViewMediator extends SystemUI {
private AudioManager mAudioManager;
private StatusBarManager mStatusBarManager;
private final StatusBarWindowController mStatusBarWindowController;
- private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+ private final Executor mUiBgExecutor;
private boolean mSystemReady;
private boolean mBootCompleted;
@@ -689,7 +690,8 @@ public class KeyguardViewMediator extends SystemUI {
BroadcastDispatcher broadcastDispatcher,
StatusBarWindowController statusBarWindowController,
Lazy<StatusBarKeyguardViewManager> statusBarKeyguardViewManagerLazy,
- DismissCallbackRegistry dismissCallbackRegistry) {
+ DismissCallbackRegistry dismissCallbackRegistry,
+ @UiBackground Executor uiBgExecutor) {
super(context);
mFalsingManager = falsingManager;
mLockPatternUtils = lockPatternUtils;
@@ -697,6 +699,7 @@ public class KeyguardViewMediator extends SystemUI {
mStatusBarWindowController = statusBarWindowController;
mStatusBarKeyguardViewManagerLazy = statusBarKeyguardViewManagerLazy;
mDismissCallbackRegistry = dismissCallbackRegistry;
+ mUiBgExecutor = uiBgExecutor;
}
public void userActivity() {
@@ -1662,7 +1665,7 @@ public class KeyguardViewMediator extends SystemUI {
private void handleKeyguardDone() {
Trace.beginSection("KeyguardViewMediator#handleKeyguardDone");
final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
if (mLockPatternUtils.isSecure(currentUser)) {
mLockPatternUtils.getDevicePolicyManager().reportKeyguardDismissed(currentUser);
}
@@ -1705,7 +1708,7 @@ public class KeyguardViewMediator extends SystemUI {
final UserHandle currentUser = new UserHandle(currentUserId);
final UserManager um = (UserManager) mContext.getSystemService(
Context.USER_SERVICE);
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
for (int profileId : um.getProfileIdsWithDisabled(currentUser.getIdentifier())) {
mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, UserHandle.of(profileId));
}
@@ -1756,7 +1759,7 @@ public class KeyguardViewMediator extends SystemUI {
mUiSoundsStreamType = mAudioManager.getUiSoundsStreamType();
}
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
// If the stream is muted, don't play the sound
if (mAudioManager.isStreamMute(mUiSoundsStreamType)) return;
@@ -1775,7 +1778,7 @@ public class KeyguardViewMediator extends SystemUI {
}
private void updateActivityLockScreenState(boolean showing, boolean aodShowing) {
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
if (DEBUG) {
Log.d(TAG, "updateActivityLockScreenState(" + showing + ", " + aodShowing + ")");
}
@@ -1854,7 +1857,7 @@ public class KeyguardViewMediator extends SystemUI {
// Posting to mUiOffloadThread to ensure that calls to ActivityTaskManager will be in
// order.
final int keyguardFlag = flags;
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
ActivityTaskManager.getService().keyguardGoingAway(keyguardFlag);
} catch (RemoteException e) {
@@ -2217,7 +2220,7 @@ public class KeyguardViewMediator extends SystemUI {
}
});
updateInputRestrictedLocked();
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
mTrustManager.reportKeyguardShowingChanged();
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
index 0a89017ff05d..f39d1ecb0585 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipManager.java
@@ -100,7 +100,7 @@ public class PipManager implements BasePipManager {
mMenuController.onActivityPinned();
mAppOpsListener.onActivityPinned(packageName);
- Dependency.get(UiOffloadThread.class).submit(() -> {
+ Dependency.get(UiOffloadThread.class).execute(() -> {
WindowManagerWrapper.getInstance().setPipVisibility(true);
});
}
@@ -114,7 +114,7 @@ public class PipManager implements BasePipManager {
mTouchHandler.onActivityUnpinned(topActivity);
mAppOpsListener.onActivityUnpinned();
- Dependency.get(UiOffloadThread.class).submit(() -> {
+ Dependency.get(UiOffloadThread.class).execute(() -> {
WindowManagerWrapper.getInstance().setPipVisibility(topActivity != null);
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
index 696db683a7d0..1d92375a7541 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
@@ -750,7 +750,7 @@ public class PipManager implements BasePipManager {
}
private void updatePipVisibility(final boolean visible) {
- Dependency.get(UiOffloadThread.class).submit(() -> {
+ Dependency.get(UiOffloadThread.class).execute(() -> {
WindowManagerWrapper.getInstance().setPipVisibility(visible);
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroupController.java
index ac94858cff27..fb106425ec63 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroupController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroupController.java
@@ -32,8 +32,8 @@ import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
import com.android.keyguard.CarrierTextController;
-import com.android.systemui.dagger.qualifiers.BgHandler;
-import com.android.systemui.dagger.qualifiers.MainLooper;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.policy.NetworkController;
@@ -111,7 +111,7 @@ public class QSCarrierGroupController {
}
private QSCarrierGroupController(QSCarrierGroup view, ActivityStarter activityStarter,
- @BgHandler Handler bgHandler, @MainLooper Looper mainLooper,
+ @Background Handler bgHandler, @Main Looper mainLooper,
NetworkController networkController,
CarrierTextController.Builder carrierTextControllerBuilder) {
mActivityStarter = activityStarter;
@@ -308,8 +308,8 @@ public class QSCarrierGroupController {
private final CarrierTextController.Builder mCarrierTextControllerBuilder;
@Inject
- public Builder(ActivityStarter activityStarter, @BgHandler Handler handler,
- @MainLooper Looper looper, NetworkController networkController,
+ public Builder(ActivityStarter activityStarter, @Background Handler handler,
+ @Main Looper looper, NetworkController networkController,
CarrierTextController.Builder carrierTextControllerBuilder) {
mActivityStarter = activityStarter;
mHandler = handler;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index c01bc8fe19e6..86ed274e9b5c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -34,8 +34,8 @@ import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.BgLooper;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.PluginListener;
import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTile;
@@ -96,8 +96,8 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D
public QSTileHost(Context context,
StatusBarIconController iconController,
QSFactoryImpl defaultFactory,
- @MainHandler Handler mainHandler,
- @BgLooper Looper bgLooper,
+ @Main Handler mainHandler,
+ @Background Looper bgLooper,
PluginManager pluginManager,
TunerService tunerService,
Provider<AutoTileManager> autoTiles,
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index c9813db525f9..02c4beb7ac1b 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -68,7 +68,7 @@ import android.widget.TextView;
import android.widget.Toast;
import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -186,7 +186,7 @@ public class GlobalScreenshot {
*/
@Inject
public GlobalScreenshot(
- Context context, @MainResources Resources resources, LayoutInflater layoutInflater,
+ Context context, @Main Resources resources, LayoutInflater layoutInflater,
ScreenshotNotificationsController screenshotNotificationsController) {
mContext = context;
mNotificationsController = screenshotNotificationsController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
index 61043fbc1bc9..a8188b3ca35c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -35,7 +35,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.RegisterStatusBarResult;
import com.android.systemui.Dependency;
import com.android.systemui.assist.AssistHandleViewController;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.statusbar.CommandQueue.Callbacks;
@@ -65,7 +65,7 @@ public class NavigationBarController implements Callbacks {
SparseArray<NavigationBarFragment> mNavigationBars = new SparseArray<>();
@Inject
- public NavigationBarController(Context context, @MainHandler Handler handler,
+ public NavigationBarController(Context context, @Main Handler handler,
CommandQueue commandQueue) {
mContext = context;
mHandler = handler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index 97dd3daae341..8dd801b0484f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -30,7 +30,7 @@ import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.util.Log;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.phone.NotificationListenerWithPlugins;
import java.util.ArrayList;
@@ -58,7 +58,7 @@ public class NotificationListener extends NotificationListenerWithPlugins {
public NotificationListener(
Context context,
NotificationManager notificationManager,
- @MainHandler Handler mainHandler) {
+ @Main Handler mainHandler) {
mContext = context;
mNotificationManager = notificationManager;
mMainHandler = mainHandler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 0f3f6b7d9222..2e369b3295b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -48,7 +48,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.recents.OverviewProxyService;
@@ -190,7 +190,7 @@ public class NotificationLockscreenUserManagerImpl implements
IStatusBarService iStatusBarService,
KeyguardManager keyguardManager,
StatusBarStateController statusBarStateController,
- @MainHandler Handler mainHandler,
+ @Main Handler mainHandler,
DeviceProvisionedController deviceProvisionedController,
KeyguardStateController keyguardStateController) {
mContext = context;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index f6f3ac1b5aaf..43d0399c6d62 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -50,7 +50,7 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -263,7 +263,7 @@ public class NotificationRemoteInputManager implements Dumpable {
NotificationEntryManager notificationEntryManager,
Lazy<StatusBar> statusBarLazy,
StatusBarStateController statusBarStateController,
- @MainHandler Handler mainHandler,
+ @Main Handler mainHandler,
RemoteInputUriController remoteInputUriController) {
mContext = context;
mLockscreenUserManager = lockscreenUserManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 1648196ec0ea..6b0b5dfeaf40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -27,7 +27,7 @@ import android.view.ViewGroup;
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -93,7 +93,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
private boolean mIsHandleDynamicPrivacyChangeScheduled;
@Inject
- public NotificationViewHierarchyManager(Context context, @MainHandler Handler mainHandler,
+ public NotificationViewHierarchyManager(Context context, @Main Handler mainHandler,
NotificationLockscreenUserManager notificationLockscreenUserManager,
NotificationGroupManager groupManager,
VisualStabilityManager visualStabilityManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index 49bed15c79a8..93f58053f486 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -54,12 +54,13 @@ import com.android.systemui.Dependency;
import com.android.systemui.DockedStackExistsListener;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
-import com.android.systemui.UiOffloadThread;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.NotificationChannels;
import java.util.List;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -74,16 +75,18 @@ public class InstantAppNotifier extends SystemUI
public static final int NUM_TASKS_FOR_INSTANT_APP_INFO = 5;
private final Handler mHandler = new Handler();
- private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+ private final Executor mUiBgExecutor;
private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
private final CommandQueue mCommandQueue;
private boolean mDockedStackExists;
private KeyguardStateController mKeyguardStateController;
@Inject
- public InstantAppNotifier(Context context, CommandQueue commandQueue) {
+ public InstantAppNotifier(Context context, CommandQueue commandQueue,
+ @UiBackground Executor uiBgExecutor) {
super(context);
mCommandQueue = commandQueue;
+ mUiBgExecutor = uiBgExecutor;
}
@Override
@@ -151,7 +154,7 @@ public class InstantAppNotifier extends SystemUI
private void updateForegroundInstantApps() {
NotificationManager noMan = mContext.getSystemService(NotificationManager.class);
IPackageManager pm = AppGlobals.getPackageManager();
- mUiOffloadThread.submit(
+ mUiBgExecutor.execute(
() -> {
ArraySet<Pair<String, Integer>> notifs = new ArraySet<>(mCurrentNotifs);
try {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
index 1b57308f1c0f..99718abb6492 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
@@ -23,7 +23,7 @@ import android.view.View;
import androidx.collection.ArraySet;
import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -62,7 +62,7 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener, Dumpabl
@Inject
public VisualStabilityManager(
- NotificationEntryManager notificationEntryManager, @MainHandler Handler handler) {
+ NotificationEntryManager notificationEntryManager, @Main Handler handler) {
mHandler = handler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
index ee841c2b4e14..62342b13f9cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
@@ -24,7 +24,7 @@ import android.util.ArraySet;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.notification.collection.NotifCollection;
import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
@@ -63,7 +63,7 @@ public class ForegroundCoordinator implements Coordinator {
public ForegroundCoordinator(
ForegroundServiceController foregroundServiceController,
AppOpsController appOpsController,
- @MainHandler Handler mainHandler) {
+ @Main Handler mainHandler) {
mForegroundServiceController = foregroundServiceController;
mAppOpsController = appOpsController;
mMainHandler = mainHandler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index 77ccf19f65ee..3e1b5bd0571e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.statusbar.notification.logging;
@@ -32,7 +32,7 @@ import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.UiOffloadThread;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.NotificationListener;
@@ -47,6 +47,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -68,7 +69,7 @@ public class NotificationLogger implements StateListener {
// Dependencies:
private final NotificationListenerService mNotificationListener;
- private final UiOffloadThread mUiOffloadThread;
+ private final Executor mUiBgExecutor;
private final NotificationEntryManager mEntryManager;
private HeadsUpManager mHeadsUpManager;
private final ExpansionStateLogger mExpansionStateLogger;
@@ -193,12 +194,12 @@ public class NotificationLogger implements StateListener {
@Inject
public NotificationLogger(NotificationListener notificationListener,
- UiOffloadThread uiOffloadThread,
+ @UiBackground Executor uiBgExecutor,
NotificationEntryManager entryManager,
StatusBarStateController statusBarStateController,
ExpansionStateLogger expansionStateLogger) {
mNotificationListener = notificationListener;
- mUiOffloadThread = uiOffloadThread;
+ mUiBgExecutor = uiBgExecutor;
mEntryManager = entryManager;
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -319,7 +320,7 @@ public class NotificationLogger implements StateListener {
final NotificationVisibility[] newlyVisibleAr = cloneVisibilitiesAsArr(newlyVisible);
final NotificationVisibility[] noLongerVisibleAr = cloneVisibilitiesAsArr(noLongerVisible);
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
mBarService.onNotificationVisibilityChanged(newlyVisibleAr, noLongerVisibleAr);
} catch (RemoteException e) {
@@ -429,13 +430,13 @@ public class NotificationLogger implements StateListener {
* Notification key -> last logged expansion state, should be accessed in UI thread only.
*/
private final Map<String, Boolean> mLoggedExpansionState = new ArrayMap<>();
- private final UiOffloadThread mUiOffloadThread;
+ private final Executor mUiBgExecutor;
@VisibleForTesting
IStatusBarService mBarService;
@Inject
- public ExpansionStateLogger(UiOffloadThread uiOffloadThread) {
- mUiOffloadThread = uiOffloadThread;
+ public ExpansionStateLogger(@UiBackground Executor uiBgExecutor) {
+ mUiBgExecutor = uiBgExecutor;
mBarService =
IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -513,7 +514,7 @@ public class NotificationLogger implements StateListener {
}
mLoggedExpansionState.put(key, state.mIsExpanded);
final State stateToBeLogged = new State(state);
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
mBarService.onNotificationExpansionChanged(key, stateToBeLogged.mIsUserAction,
stateToBeLogged.mIsExpanded, stateToBeLogged.mLocation.ordinal());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
index e9d6a0fcde83..ec1d6deb1b8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
@@ -23,7 +23,7 @@ import android.os.Handler
import android.os.UserHandle
import android.provider.Settings
import android.view.View
-import com.android.systemui.dagger.qualifiers.MainHandler
+import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager
import javax.inject.Inject
@@ -164,7 +164,7 @@ private class PeopleHubViewModelFactoryImpl(
@Singleton
class PeopleHubSettingChangeDataSourceImpl @Inject constructor(
- @MainHandler private val handler: Handler,
+ @Main private val handler: Handler,
context: Context
) : DataSource<Boolean> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 9dd7f48086c9..6f2abba128d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -42,7 +42,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
import com.android.systemui.Dependency;
import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.NotificationLifetimeExtender;
@@ -108,7 +108,7 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
@Inject
public NotificationGutsManager(Context context, VisualStabilityManager visualStabilityManager,
- Lazy<StatusBar> statusBarLazy, @MainHandler Handler mainHandler,
+ Lazy<StatusBar> statusBarLazy, @Main Handler mainHandler,
AccessibilityManager accessibilityManager) {
mContext = context;
mVisualStabilityManager = visualStabilityManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
index 90ea6e344226..0a1a2fe3ee54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationTemplateViewWrapper.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.statusbar.notification.row.wrapper;
@@ -244,17 +244,18 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
mUiOffloadThread = Dependency.get(UiOffloadThread.class);
}
if (view.isAttachedToWindow()) {
- mUiOffloadThread.submit(() -> pendingIntent.registerCancelListener(listener));
+ mUiOffloadThread.execute(() -> pendingIntent.registerCancelListener(listener));
}
view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
- mUiOffloadThread.submit(() -> pendingIntent.registerCancelListener(listener));
+ mUiOffloadThread.execute(() -> pendingIntent.registerCancelListener(listener));
}
@Override
public void onViewDetachedFromWindow(View v) {
- mUiOffloadThread.submit(() -> pendingIntent.unregisterCancelListener(listener));
+ mUiOffloadThread.execute(
+ () -> pendingIntent.unregisterCancelListener(listener));
}
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
index f9b936763308..3165597d4b9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoHideController.java
@@ -23,7 +23,7 @@ import android.util.Log;
import android.view.IWindowManager;
import android.view.MotionEvent;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import javax.inject.Inject;
@@ -52,7 +52,7 @@ public class AutoHideController {
};
@Inject
- public AutoHideController(Context context, @MainHandler Handler handler,
+ public AutoHideController(Context context, @Main Handler handler,
NotificationRemoteInputManager notificationRemoteInputManager,
IWindowManager iWindowManager) {
mHandler = handler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 837517e2cc9b..0680c7f70b97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -21,7 +21,7 @@ import android.os.Handler;
import android.provider.Settings.Secure;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.qs.AutoAddTracker;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.qs.SecureSetting;
@@ -57,7 +57,7 @@ public class AutoTileManager {
@Inject
public AutoTileManager(Context context, AutoAddTracker autoAddTracker, QSTileHost host,
- @BgHandler Handler handler,
+ @Background Handler handler,
HotspotController hotspotController,
DataSaverController dataSaverController,
ManagedProfileController managedProfileController,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 250f7300ba56..48805204160f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -37,7 +37,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dependency;
import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
@@ -165,7 +165,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
StatusBarWindowController statusBarWindowController,
KeyguardStateController keyguardStateController, Handler handler,
KeyguardUpdateMonitor keyguardUpdateMonitor,
- @MainResources Resources resources,
+ @Main Resources resources,
KeyguardBypassController keyguardBypassController, DozeParameters dozeParameters,
MetricsLogger metricsLogger, DumpController dumpController) {
mContext = context;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index bc482353753d..f5999f5c8294 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -25,7 +25,7 @@ import android.provider.Settings;
import android.util.MathUtils;
import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.AlwaysOnDisplayPolicy;
import com.android.systemui.doze.DozeScreenState;
import com.android.systemui.tuner.TunerService;
@@ -58,7 +58,7 @@ public class DozeParameters implements TunerService.Tunable,
@Inject
protected DozeParameters(
- @MainResources Resources resources,
+ @Main Resources resources,
AmbientDisplayConfiguration ambientDisplayConfiguration,
AlwaysOnDisplayPolicy alwaysOnDisplayPolicy,
PowerManager powerManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index 183adeb037d6..4ee13bf754dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -43,7 +43,7 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.DumpController;
import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.statusbar.NotificationMediaManager;
import libcore.io.IoUtils;
@@ -83,7 +83,7 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen
KeyguardUpdateMonitor keyguardUpdateMonitor,
DumpController dumpController,
NotificationMediaManager mediaManager,
- @MainHandler Handler mainHandler) {
+ @Main Handler mainHandler) {
dumpController.registerDumpable(getClass().getSimpleName(), this);
mWallpaperManager = wallpaperManager;
mCurrentUserId = ActivityManager.getCurrentUser();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index ebe211754b2b..d4cf272e8077 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -93,7 +93,7 @@ import com.android.systemui.R;
import com.android.systemui.assist.AssistHandleViewController;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.model.SysUiState;
@@ -274,7 +274,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
CommandQueue commandQueue, Divider divider,
Optional<Recents> recentsOptional, Lazy<StatusBar> statusBarLazy,
ShadeController shadeController,
- @MainHandler Handler mainHandler) {
+ @Main Handler mainHandler) {
mAccessibilityManagerWrapper = accessibilityManagerWrapper;
mDeviceProvisionedController = deviceProvisionedController;
mStatusBarStateController = statusBarStateController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
index 1df9411019d2..d6336ed3e18a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationModeController.java
@@ -53,7 +53,7 @@ import android.util.Log;
import android.util.SparseBooleanArray;
import com.android.systemui.Dumpable;
-import com.android.systemui.UiOffloadThread;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -61,6 +61,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.concurrent.Executor;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -82,7 +83,7 @@ public class NavigationModeController implements Dumpable {
private Context mCurrentUserContext;
private final IOverlayManager mOverlayManager;
private final DeviceProvisionedController mDeviceProvisionedController;
- private final UiOffloadThread mUiOffloadThread;
+ private final Executor mUiBgExecutor;
private SparseBooleanArray mRestoreGesturalNavBarMode = new SparseBooleanArray();
@@ -146,12 +147,12 @@ public class NavigationModeController implements Dumpable {
@Inject
public NavigationModeController(Context context,
DeviceProvisionedController deviceProvisionedController,
- UiOffloadThread uiOffloadThread) {
+ @UiBackground Executor uiBgExecutor) {
mContext = context;
mCurrentUserContext = context;
mOverlayManager = IOverlayManager.Stub.asInterface(
ServiceManager.getService(Context.OVERLAY_SERVICE));
- mUiOffloadThread = uiOffloadThread;
+ mUiBgExecutor = uiBgExecutor;
mDeviceProvisionedController = deviceProvisionedController;
mDeviceProvisionedController.addCallback(mDeviceProvisionedCallback);
@@ -242,7 +243,7 @@ public class NavigationModeController implements Dumpable {
mCurrentUserContext = getCurrentUserContext();
int mode = getCurrentInteractionMode(mCurrentUserContext);
mMode = mode;
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
Settings.Secure.putString(mCurrentUserContext.getContentResolver(),
Secure.NAVIGATION_MODE, String.valueOf(mode));
});
@@ -379,7 +380,7 @@ public class NavigationModeController implements Dumpable {
}
public void setModeOverlay(String overlayPkg, int userId) {
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
mOverlayManager.setEnabledExclusiveInCategory(overlayPkg, userId);
if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 2f39c138bce1..5b34aa7781c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -40,8 +40,8 @@ import android.util.Log;
import com.android.internal.telephony.TelephonyIntents;
import com.android.systemui.Dependency;
import com.android.systemui.R;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.qs.tiles.DndTile;
import com.android.systemui.qs.tiles.RotationLockTile;
import com.android.systemui.statusbar.CommandQueue;
@@ -63,6 +63,7 @@ import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.ZenModeController;
import java.util.Locale;
+import java.util.concurrent.Executor;
/**
* This class contains all of the policy about which icons are installed in the status bar at boot
@@ -114,7 +115,7 @@ public class PhoneStatusBarPolicy
private final DeviceProvisionedController mProvisionedController;
private final KeyguardStateController mKeyguardStateController;
private final LocationController mLocationController;
- private final UiOffloadThread mUiOffloadThread = Dependency.get(UiOffloadThread.class);
+ private final Executor mUiBgExecutor;
private final SensorPrivacyController mSensorPrivacyController;
// Assume it's all good unless we hear otherwise. We don't always seem
@@ -131,7 +132,8 @@ public class PhoneStatusBarPolicy
private AlarmManager.AlarmClockInfo mNextAlarm;
public PhoneStatusBarPolicy(Context context, StatusBarIconController iconController,
- CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher) {
+ CommandQueue commandQueue, BroadcastDispatcher broadcastDispatcher,
+ @UiBackground Executor uiBgExecutor) {
mContext = context;
mIconController = iconController;
mCast = Dependency.get(CastController.class);
@@ -148,6 +150,7 @@ public class PhoneStatusBarPolicy
mKeyguardStateController = Dependency.get(KeyguardStateController.class);
mLocationController = Dependency.get(LocationController.class);
mSensorPrivacyController = Dependency.get(SensorPrivacyController.class);
+ mUiBgExecutor = uiBgExecutor;
mSlotCast = context.getString(com.android.internal.R.string.status_bar_cast);
mSlotHotspot = context.getString(com.android.internal.R.string.status_bar_hotspot);
@@ -452,7 +455,7 @@ public class PhoneStatusBarPolicy
// getLastResumedActivityUserId needds to acquire the AM lock, which may be contended in
// some cases. Since it doesn't really matter here whether it's updated in this frame
// or in the next one, we call this method from our UI offload thread.
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
final int userId;
try {
userId = ActivityTaskManager.getService().getLastResumedActivityUserId();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 4c5bbce05261..2b9fc8d3bfbe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -45,7 +45,7 @@ import com.android.systemui.DejankUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dock.DockManager;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.notification.stack.ViewState;
@@ -192,7 +192,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, OnCo
@Inject
public ScrimController(LightBarController lightBarController, DozeParameters dozeParameters,
AlarmManager alarmManager, KeyguardStateController keyguardStateController,
- @MainResources Resources resources,
+ @Main Resources resources,
DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler,
KeyguardUpdateMonitor keyguardUpdateMonitor, SysuiColorExtractor sysuiColorExtractor,
DockManager dockManager) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 312f9c181121..aaed61041c6a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -136,13 +136,13 @@ import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.SystemUIFactory;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.charging.WirelessChargingAnimation;
import com.android.systemui.classifier.FalsingLog;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.fragments.ExtensionFragmentListener;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
@@ -232,6 +232,7 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;
import java.util.Optional;
+import java.util.concurrent.Executor;
import javax.inject.Named;
import javax.inject.Provider;
@@ -471,7 +472,7 @@ public class StatusBar extends SystemUI implements DemoMode,
private ViewMediatorCallback mKeyguardViewMediatorCallback;
private final ScrimController mScrimController;
protected DozeScrimController mDozeScrimController;
- private final UiOffloadThread mUiOffloadThread;
+ private final Executor mUiBgExecutor;
protected boolean mDozing;
@@ -634,7 +635,7 @@ public class StatusBar extends SystemUI implements DemoMode,
NotificationAlertingManager notificationAlertingManager,
DisplayMetrics displayMetrics,
MetricsLogger metricsLogger,
- UiOffloadThread uiOffloadThread,
+ @UiBackground Executor uiBgExecutor,
NotificationMediaManager notificationMediaManager,
NotificationLockscreenUserManager lockScreenUserManager,
NotificationRemoteInputManager remoteInputManager,
@@ -708,7 +709,7 @@ public class StatusBar extends SystemUI implements DemoMode,
mNotificationAlertingManager = notificationAlertingManager;
mDisplayMetrics = displayMetrics;
mMetricsLogger = metricsLogger;
- mUiOffloadThread = uiOffloadThread;
+ mUiBgExecutor = uiBgExecutor;
mMediaManager = notificationMediaManager;
mLockscreenUserManager = lockScreenUserManager;
mRemoteInputManager = remoteInputManager;
@@ -885,7 +886,7 @@ public class StatusBar extends SystemUI implements DemoMode,
// Lastly, call to the icon policy to install/update all the icons.
mIconPolicy = new PhoneStatusBarPolicy(mContext, mIconController, mCommandQueue,
- mBroadcastDispatcher);
+ mBroadcastDispatcher, mUiBgExecutor);
mSignalPolicy = new StatusBarSignalPolicy(mContext, mIconController);
mKeyguardStateController.addCallback(this);
@@ -2840,7 +2841,7 @@ public class StatusBar extends SystemUI implements DemoMode,
notificationLoad = 1;
}
final int finalNotificationLoad = notificationLoad;
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
mBarService.onPanelRevealed(clearNotificationEffects,
finalNotificationLoad);
@@ -2849,7 +2850,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
});
} else {
- mUiOffloadThread.submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
mBarService.onPanelHidden();
} catch (RemoteException ex) {
@@ -4019,7 +4020,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
void awakenDreams() {
- Dependency.get(UiOffloadThread.class).submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
mDreamManager.awaken();
} catch (RemoteException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
index e31c53abe988..ce563813953f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarModule.java
@@ -27,11 +27,11 @@ import androidx.annotation.Nullable;
import com.android.internal.logging.MetricsLogger;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
@@ -75,6 +75,7 @@ import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.volume.VolumeComponent;
import java.util.Optional;
+import java.util.concurrent.Executor;
import javax.inject.Named;
import javax.inject.Provider;
@@ -122,7 +123,7 @@ public class StatusBarModule {
NotificationAlertingManager notificationAlertingManager,
DisplayMetrics displayMetrics,
MetricsLogger metricsLogger,
- UiOffloadThread uiOffloadThread,
+ @UiBackground Executor uiBgExecutor,
NotificationMediaManager notificationMediaManager,
NotificationLockscreenUserManager lockScreenUserManager,
NotificationRemoteInputManager remoteInputManager,
@@ -197,7 +198,7 @@ public class StatusBarModule {
notificationAlertingManager,
displayMetrics,
metricsLogger,
- uiOffloadThread,
+ uiBgExecutor,
notificationMediaManager,
lockScreenUserManager,
remoteInputManager,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 3123f8dacada..661a7b1319a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -47,13 +47,12 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.widget.LockPatternUtils;
import com.android.systemui.ActivityIntentHelper;
-import com.android.systemui.Dependency;
import com.android.systemui.EventLogTags;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.bubbles.BubbleController;
-import com.android.systemui.dagger.qualifiers.BgHandler;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
@@ -74,6 +73,8 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.policy.HeadsUpUtil;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import java.util.concurrent.Executor;
+
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -115,6 +116,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private final Handler mBackgroundHandler;
private final ActivityIntentHelper mActivityIntentHelper;
private final BubbleController mBubbleController;
+ private final Executor mUiBgExecutor;
private boolean mIsCollapsingToShowActivityOverLockscreen;
@@ -133,7 +135,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
KeyguardStateController keyguardStateController,
NotificationInterruptionStateProvider notificationInterruptionStateProvider,
MetricsLogger metricsLogger, LockPatternUtils lockPatternUtils,
- Handler mainThreadHandler, Handler backgroundHandler,
+ Handler mainThreadHandler, Handler backgroundHandler, Executor uiBgExecutor,
ActivityIntentHelper activityIntentHelper, BubbleController bubbleController) {
mContext = context;
mNotificationPanel = panel;
@@ -160,6 +162,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mGroupManager = groupManager;
mLockPatternUtils = lockPatternUtils;
mBackgroundHandler = backgroundHandler;
+ mUiBgExecutor = uiBgExecutor;
mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
@Override
public void onPendingEntryAdded(NotificationEntry entry) {
@@ -418,7 +421,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
} else {
// Stop screensaver if the notification has a fullscreen intent.
// (like an incoming phone call)
- Dependency.get(UiOffloadThread.class).submit(() -> {
+ mUiBgExecutor.execute(() -> {
try {
mDreamManager.awaken();
} catch (RemoteException e) {
@@ -521,6 +524,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
private final LockPatternUtils mLockPatternUtils;
private final Handler mMainThreadHandler;
private final Handler mBackgroundHandler;
+ private final Executor mUiBgExecutor;
private final ActivityIntentHelper mActivityIntentHelper;
private final BubbleController mBubbleController;
private final SuperStatusBarViewFactory mSuperStatusBarViewFactory;
@@ -549,8 +553,9 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
NotificationInterruptionStateProvider notificationInterruptionStateProvider,
MetricsLogger metricsLogger,
LockPatternUtils lockPatternUtils,
- @MainHandler Handler mainThreadHandler,
- @BgHandler Handler backgroundHandler,
+ @Main Handler mainThreadHandler,
+ @Background Handler backgroundHandler,
+ @UiBackground Executor uiBgExecutor,
ActivityIntentHelper activityIntentHelper,
BubbleController bubbleController,
ShadeController shadeController,
@@ -576,6 +581,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mLockPatternUtils = lockPatternUtils;
mMainThreadHandler = mainThreadHandler;
mBackgroundHandler = backgroundHandler;
+ mUiBgExecutor = uiBgExecutor;
mActivityIntentHelper = activityIntentHelper;
mBubbleController = bubbleController;
mShadeController = shadeController;
@@ -624,6 +630,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
mLockPatternUtils,
mMainThreadHandler,
mBackgroundHandler,
+ mUiBgExecutor,
mActivityIntentHelper,
mBubbleController);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index f94b2eea8154..ce498a39d941 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -41,7 +41,7 @@ import android.view.WindowManager.LayoutParams;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
@@ -105,7 +105,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
ConfigurationController configurationController,
KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor,
SuperStatusBarViewFactory superStatusBarViewFactory,
- @MainResources Resources resources) {
+ @Main Resources resources) {
mContext = context;
mWindowManager = windowManager;
mActivityManager = activityManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index dc809066524f..f132058b5329 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -34,8 +34,8 @@ import com.android.settingslib.fuelgauge.BatterySaverUtils;
import com.android.settingslib.fuelgauge.Estimate;
import com.android.settingslib.utils.PowerUtil;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.BgHandler;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.power.EnhancedEstimates;
import java.io.FileDescriptor;
@@ -82,7 +82,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
@Inject
BatteryControllerImpl(Context context, EnhancedEstimates enhancedEstimates,
PowerManager powerManager, BroadcastDispatcher broadcastDispatcher,
- @MainHandler Handler mainHandler, @BgHandler Handler bgHandler) {
+ @Main Handler mainHandler, @Background Handler bgHandler) {
mContext = context;
mMainHandler = mainHandler;
mBgHandler = bgHandler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index 6ededd2460ce..0fc3d8481907 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -34,8 +34,8 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfile;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
-import com.android.systemui.dagger.qualifiers.BgLooper;
-import com.android.systemui.dagger.qualifiers.MainLooper;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -75,8 +75,8 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
/**
*/
@Inject
- public BluetoothControllerImpl(Context context, @BgLooper Looper bgLooper,
- @MainLooper Looper mainLooper, @Nullable LocalBluetoothManager localBluetoothManager) {
+ public BluetoothControllerImpl(Context context, @Background Looper bgLooper,
+ @Main Looper mainLooper, @Nullable LocalBluetoothManager localBluetoothManager) {
mLocalBluetoothManager = localBluetoothManager;
mBgHandler = new Handler(bgLooper);
mHandler = new H(mainLooper);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
index f6b770cd16b9..a3e2e7619bac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
@@ -25,7 +25,7 @@ import android.provider.Settings.Secure;
import android.util.Log;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.settings.CurrentUserTracker;
import java.util.ArrayList;
@@ -50,7 +50,7 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen
/**
*/
@Inject
- public DeviceProvisionedControllerImpl(Context context, @MainHandler Handler mainHandler,
+ public DeviceProvisionedControllerImpl(Context context, @Main Handler mainHandler,
BroadcastDispatcher broadcastDispatcher) {
super(broadcastDispatcher);
mContext = context;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index cd6ec05d90ec..df9c3f4d6e26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -26,7 +26,7 @@ import android.os.HandlerExecutor;
import android.os.UserManager;
import android.util.Log;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -59,7 +59,7 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof
* Controller used to retrieve information related to a hotspot.
*/
@Inject
- public HotspotControllerImpl(Context context, @MainHandler Handler mainHandler) {
+ public HotspotControllerImpl(Context context, @Main Handler mainHandler) {
mContext = context;
mConnectivityManager =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index d36bd75dfdba..570f153a62c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -37,7 +37,7 @@ import androidx.annotation.VisibleForTesting;
import com.android.systemui.BootCompleteCache;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.util.Utils;
import java.util.ArrayList;
@@ -69,7 +69,7 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
private final H mHandler = new H();
@Inject
- public LocationControllerImpl(Context context, @BgLooper Looper bgLooper,
+ public LocationControllerImpl(Context context, @Background Looper bgLooper,
BroadcastDispatcher broadcastDispatcher, BootCompleteCache bootCompleteCache) {
mContext = context;
mBroadcastDispatcher = broadcastDispatcher;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 24492bf3ca5b..f20a47babe5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -64,7 +64,7 @@ import com.android.systemui.DemoMode;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup;
@@ -177,7 +177,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
* Construct this controller object and register for updates.
*/
@Inject
- public NetworkControllerImpl(Context context, @BgLooper Looper bgLooper,
+ public NetworkControllerImpl(Context context, @Background Looper bgLooper,
DeviceProvisionedController deviceProvisionedController,
BroadcastDispatcher broadcastDispatcher) {
this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index c1614587ea35..019ef3bca709 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -49,7 +49,7 @@ import com.android.internal.net.LegacyVpnInfo;
import com.android.internal.net.VpnConfig;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.settings.CurrentUserTracker;
import java.io.FileDescriptor;
@@ -101,7 +101,7 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi
/**
*/
@Inject
- public SecurityControllerImpl(Context context, @BgHandler Handler bgHandler,
+ public SecurityControllerImpl(Context context, @Background Handler bgHandler,
BroadcastDispatcher broadcastDispatcher) {
this(context, bgHandler, broadcastDispatcher, null);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
index 347d3009c3ec..86fe300820a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyConstants.java
@@ -28,7 +28,7 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -65,7 +65,7 @@ public final class SmartReplyConstants {
private final KeyValueListParser mParser = new KeyValueListParser(',');
@Inject
- public SmartReplyConstants(@MainHandler Handler handler, Context context) {
+ public SmartReplyConstants(@Main Handler handler, Context context) {
mHandler = handler;
mContext = context;
final Resources resources = mContext.getResources();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 13c0db938ca0..2907cd41a0db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -60,7 +60,7 @@ import com.android.systemui.Prefs.Key;
import com.android.systemui.R;
import com.android.systemui.SystemUISecondaryUserService;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.DetailAdapter;
import com.android.systemui.qs.tiles.UserDetailView;
@@ -113,7 +113,7 @@ public class UserSwitcherController implements Dumpable {
@Inject
public UserSwitcherController(Context context, KeyguardStateController keyguardStateController,
- @MainHandler Handler handler, ActivityStarter activityStarter,
+ @Main Handler handler, ActivityStarter activityStarter,
BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mBroadcastDispatcher = broadcastDispatcher;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index a2028e6c0c33..4376a0145826 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -40,7 +40,7 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dumpable;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.qs.GlobalSetting;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.util.Utils;
@@ -78,7 +78,7 @@ public class ZenModeControllerImpl extends CurrentUserTracker
private NotificationManager.Policy mConsolidatedNotificationPolicy;
@Inject
- public ZenModeControllerImpl(Context context, @MainHandler Handler handler,
+ public ZenModeControllerImpl(Context context, @Main Handler handler,
BroadcastDispatcher broadcastDispatcher) {
super(broadcastDispatcher);
mContext = context;
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index f9d39b0e6f96..7758aba52918 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -36,7 +36,7 @@ import android.util.Log;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.Background;
import com.google.android.collect.Sets;
@@ -70,7 +70,7 @@ public class ThemeOverlayController extends SystemUI {
@Inject
public ThemeOverlayController(Context context, BroadcastDispatcher broadcastDispatcher,
- @BgHandler Handler bgHandler) {
+ @Background Handler bgHandler) {
super(context);
mBroadcastDispatcher = broadcastDispatcher;
mBgHandler = bgHandler;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index ce0032e619e7..19f0ba24b0fd 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -35,7 +35,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.systemui.DejankUtils;
import com.android.systemui.DemoMode;
import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.settings.CurrentUserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -82,7 +82,7 @@ public class TunerServiceImpl extends TunerService {
/**
*/
@Inject
- public TunerServiceImpl(Context context, @MainHandler Handler mainHandler,
+ public TunerServiceImpl(Context context, @Main Handler mainHandler,
LeakDetector leakDetector, BroadcastDispatcher broadcastDispatcher) {
mContext = context;
mContentResolver = mContext.getContentResolver();
diff --git a/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java b/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java
index 3e90581292ce..7cdba8607d86 100644
--- a/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/util/concurrency/ConcurrencyModule.java
@@ -18,14 +18,18 @@ package com.android.systemui.util.concurrency;
import android.content.Context;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
+import android.os.Process;
import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.BgLooper;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.dagger.qualifiers.MainLooper;
+import com.android.systemui.dagger.qualifiers.UiBackground;
import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@@ -35,11 +39,51 @@ import dagger.Provides;
*/
@Module
public abstract class ConcurrencyModule {
+ /** Background Looper */
+ @Provides
+ @Singleton
+ @Background
+ public static Looper provideBgLooper() {
+ HandlerThread thread = new HandlerThread("SysUiBg",
+ Process.THREAD_PRIORITY_BACKGROUND);
+ thread.start();
+ return thread.getLooper();
+ }
+
+ /** Main Looper */
+ @Provides
+ @Main
+ public static Looper provideMainLooper() {
+ return Looper.getMainLooper();
+ }
+
+ /**
+ * Background Handler.
+ *
+ * Prefer the Background Executor when possible.
+ */
+ @Provides
+ @Background
+ public static Handler provideBgHandler(@Background Looper bgLooper) {
+ return new Handler(bgLooper);
+ }
+
+ /**
+ * Main Handler.
+ *
+ * Prefer the Main Executor when possible.
+ */
+ @Provides
+ @Main
+ public static Handler provideMainHandler(@Main Looper mainLooper) {
+ return new Handler(mainLooper);
+ }
+
/**
* Provide a Background-Thread Executor by default.
*/
@Provides
- public static Executor provideExecutor(@BgLooper Looper looper) {
+ public static Executor provideExecutor(@Background Looper looper) {
return new ExecutorImpl(new Handler(looper));
}
@@ -48,7 +92,7 @@ public abstract class ConcurrencyModule {
*/
@Provides
@Background
- public static Executor provideBackgroundExecutor(@BgLooper Looper looper) {
+ public static Executor provideBackgroundExecutor(@Background Looper looper) {
return new ExecutorImpl(new Handler(looper));
}
@@ -65,7 +109,7 @@ public abstract class ConcurrencyModule {
* Provide a Background-Thread Executor by default.
*/
@Provides
- public static DelayableExecutor provideDelayableExecutor(@BgLooper Looper looper) {
+ public static DelayableExecutor provideDelayableExecutor(@Background Looper looper) {
return new ExecutorImpl(new Handler(looper));
}
@@ -74,7 +118,7 @@ public abstract class ConcurrencyModule {
*/
@Provides
@Background
- public static DelayableExecutor provideBackgroundDelayableExecutor(@BgLooper Looper looper) {
+ public static DelayableExecutor provideBackgroundDelayableExecutor(@Background Looper looper) {
return new ExecutorImpl(new Handler(looper));
}
@@ -83,7 +127,19 @@ public abstract class ConcurrencyModule {
*/
@Provides
@Main
- public static DelayableExecutor provideMainDelayableExecutor(@MainLooper Looper looper) {
+ public static DelayableExecutor provideMainDelayableExecutor(@Main Looper looper) {
return new ExecutorImpl(new Handler(looper));
}
+
+ /**
+ * Provide an Executor specifically for running UI operations on a separate thread.
+ *
+ * Keep submitted runnables short and to the point, just as with any other UI code.
+ */
+ @Provides
+ @Singleton
+ @UiBackground
+ public static Executor provideUiBackgroundExecutor() {
+ return Executors.newSingleThreadExecutor();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index bff405c0bee6..2c7c52e1c51f 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -47,7 +47,7 @@ import android.util.LongSparseArray;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
-import com.android.systemui.dagger.qualifiers.BgLooper;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSHost;
@@ -109,7 +109,7 @@ public class GarbageMonitor implements Dumpable {
@Inject
public GarbageMonitor(
Context context,
- @BgLooper Looper bgLooper,
+ @Background Looper bgLooper,
LeakDetector leakDetector,
LeakReporter leakReporter) {
mContext = context.getApplicationContext();
diff --git a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
index a96977a338a9..b5bede4ad31c 100644
--- a/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/sensors/ProximitySensor.java
@@ -26,7 +26,7 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
-import com.android.systemui.dagger.qualifiers.MainResources;
+import com.android.systemui.dagger.qualifiers.Main;
import java.util.ArrayList;
import java.util.List;
@@ -65,7 +65,7 @@ public class ProximitySensor {
};
@Inject
- public ProximitySensor(@MainResources Resources resources,
+ public ProximitySensor(@Main Resources resources,
AsyncSensorManager sensorManager) {
mSensorManager = sensorManager;
Sensor sensor = findBrightnessSensor(resources);
diff --git a/packages/SystemUI/src/com/android/systemui/util/time/SystemClock.java b/packages/SystemUI/src/com/android/systemui/util/time/SystemClock.java
index 4316df1ced04..6fef59f6b995 100644
--- a/packages/SystemUI/src/com/android/systemui/util/time/SystemClock.java
+++ b/packages/SystemUI/src/com/android/systemui/util/time/SystemClock.java
@@ -37,10 +37,4 @@ public interface SystemClock {
/** @see android.os.SystemClock#currentThreadTimeMillis() */
long currentThreadTimeMillis();
-
- /** @see android.os.SystemClock#currentThreadTimeMicro() */
- long currentThreadTimeMicro();
-
- /** @see android.os.SystemClock#currentTimeMicro() */
- long currentTimeMicro();
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/time/SystemClockImpl.java b/packages/SystemUI/src/com/android/systemui/util/time/SystemClockImpl.java
index 532ea050bfdd..f0c701490f13 100644
--- a/packages/SystemUI/src/com/android/systemui/util/time/SystemClockImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/util/time/SystemClockImpl.java
@@ -42,14 +42,4 @@ public class SystemClockImpl implements SystemClock {
public long currentThreadTimeMillis() {
return android.os.SystemClock.currentThreadTimeMillis();
}
-
- @Override
- public long currentThreadTimeMicro() {
- return android.os.SystemClock.currentThreadTimeMicro();
- }
-
- @Override
- public long currentTimeMicro() {
- return android.os.SystemClock.currentTimeMicro();
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
index aa56ffb18554..951d6dd4c3a3 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayWindowController.java
@@ -31,7 +31,7 @@ import android.view.IDisplayWindowRotationController;
import android.view.IWindowManager;
import android.view.WindowContainerTransaction;
-import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.dagger.qualifiers.Main;
import java.util.ArrayList;
@@ -99,13 +99,17 @@ public class DisplayWindowController {
if (mDisplays.get(displayId) != null) {
return;
}
+ Display display = getDisplay(displayId);
+ if (display == null) {
+ // It's likely that the display is private to some app and thus not
+ // accessible by system-ui.
+ return;
+ }
DisplayRecord record = new DisplayRecord();
record.mDisplayId = displayId;
- // TODO(b/146566787): disabled for MultiDisplayActivityLaunchTests
- // Display display = getDisplay(displayId);
- // record.mContext = (displayId == Display.DEFAULT_DISPLAY) ? mContext
- // : mContext.createDisplayContext(display);
- // record.mDisplayLayout = new DisplayLayout(record.mContext, display);
+ record.mContext = (displayId == Display.DEFAULT_DISPLAY) ? mContext
+ : mContext.createDisplayContext(display);
+ record.mDisplayLayout = new DisplayLayout(record.mContext, display);
mDisplays.put(displayId, record);
for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
mDisplayChangedListeners.get(i).onDisplayAdded(displayId);
@@ -124,14 +128,13 @@ public class DisplayWindowController {
+ " display.");
return;
}
- // TODO(b/146566787): disabled for MultiDisplaySystemDecorationTests
- // Display display = getDisplay(displayId);
- // Context perDisplayContext = mContext;
- // if (displayId != Display.DEFAULT_DISPLAY) {
- // perDisplayContext = mContext.createDisplayContext(display);
- // }
- // dr.mContext = perDisplayContext.createConfigurationContext(newConfig);
- // dr.mDisplayLayout = new DisplayLayout(dr.mContext, display);
+ Display display = getDisplay(displayId);
+ Context perDisplayContext = mContext;
+ if (displayId != Display.DEFAULT_DISPLAY) {
+ perDisplayContext = mContext.createDisplayContext(display);
+ }
+ dr.mContext = perDisplayContext.createConfigurationContext(newConfig);
+ dr.mDisplayLayout = new DisplayLayout(dr.mContext, display);
for (int i = 0; i < mDisplayChangedListeners.size(); ++i) {
mDisplayChangedListeners.get(i).onDisplayConfigurationChanged(
displayId, newConfig);
@@ -144,6 +147,9 @@ public class DisplayWindowController {
public void onDisplayRemoved(int displayId) {
mHandler.post(() -> {
synchronized (mDisplays) {
+ if (mDisplays.get(displayId) == null) {
+ return;
+ }
for (int i = mDisplayChangedListeners.size() - 1; i >= 0; --i) {
mDisplayChangedListeners.get(i).onDisplayRemoved(displayId);
}
@@ -154,7 +160,7 @@ public class DisplayWindowController {
};
@Inject
- public DisplayWindowController(Context context, @MainHandler Handler mainHandler,
+ public DisplayWindowController(Context context, @Main Handler mainHandler,
IWindowManager wmService) {
mHandler = mainHandler;
mContext = context;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index 819a7f6fde1a..c85d600e8447 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -117,7 +117,7 @@ public abstract class SysuiTestCase {
}
protected void waitForUiOffloadThread() {
- Future<?> future = Dependency.get(UiOffloadThread.class).submit(() -> {});
+ Future<?> future = Dependency.get(UiOffloadThread.class).execute(() -> { });
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
index 3561e3465898..a19d1df8a713 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java
@@ -34,7 +34,9 @@ import com.android.systemui.classifier.brightline.BrightLineFalsingManager;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.util.DeviceConfigProxy;
import com.android.systemui.util.DeviceConfigProxyFake;
+import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.sensors.ProximitySensor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.After;
import org.junit.Before;
@@ -55,6 +57,7 @@ public class FalsingManagerProxyTest extends SysuiTestCase {
private FalsingManagerProxy mProxy;
private DeviceConfigProxy mDeviceConfig;
private TestableLooper mTestableLooper;
+ private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@Before
public void setup() {
@@ -77,7 +80,7 @@ public class FalsingManagerProxyTest extends SysuiTestCase {
@Test
public void test_brightLineFalsingManagerDisabled() {
mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler, mProximitySensor,
- mDeviceConfig);
+ mDeviceConfig, mUiBgExecutor);
assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
}
@@ -87,14 +90,14 @@ public class FalsingManagerProxyTest extends SysuiTestCase {
BRIGHTLINE_FALSING_MANAGER_ENABLED, "true", false);
mTestableLooper.processAllMessages();
mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler, mProximitySensor,
- mDeviceConfig);
+ mDeviceConfig, mUiBgExecutor);
assertThat(mProxy.getInternalFalsingManager(), instanceOf(BrightLineFalsingManager.class));
}
@Test
public void test_brightLineFalsingManagerToggled() throws InterruptedException {
mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mHandler, mProximitySensor,
- mDeviceConfig);
+ mDeviceConfig, mUiBgExecutor);
assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class));
mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
index 7fa1dbeafced..a00cabc71a0c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.keyguard;
@@ -24,6 +24,8 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
@@ -41,10 +43,11 @@ public class DismissCallbackRegistryTest extends SysuiTestCase {
private DismissCallbackRegistry mDismissCallbackRegistry;
private @Mock IKeyguardDismissCallback mMockCallback;
private @Mock IKeyguardDismissCallback mMockCallback2;
+ private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@Before
public void setUp() throws Exception {
- mDismissCallbackRegistry = new DismissCallbackRegistry();
+ mDismissCallbackRegistry = new DismissCallbackRegistry(mUiBgExecutor);
MockitoAnnotations.initMocks(this);
}
@@ -52,7 +55,7 @@ public class DismissCallbackRegistryTest extends SysuiTestCase {
public void testCancelled() throws Exception {
mDismissCallbackRegistry.addCallback(mMockCallback);
mDismissCallbackRegistry.notifyDismissCancelled();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mMockCallback).onDismissCancelled();
}
@@ -61,7 +64,7 @@ public class DismissCallbackRegistryTest extends SysuiTestCase {
mDismissCallbackRegistry.addCallback(mMockCallback);
mDismissCallbackRegistry.addCallback(mMockCallback2);
mDismissCallbackRegistry.notifyDismissCancelled();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mMockCallback).onDismissCancelled();
verify(mMockCallback2).onDismissCancelled();
}
@@ -70,7 +73,7 @@ public class DismissCallbackRegistryTest extends SysuiTestCase {
public void testSucceeded() throws Exception {
mDismissCallbackRegistry.addCallback(mMockCallback);
mDismissCallbackRegistry.notifyDismissSucceeded();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mMockCallback).onDismissSucceeded();
}
@@ -79,7 +82,7 @@ public class DismissCallbackRegistryTest extends SysuiTestCase {
mDismissCallbackRegistry.addCallback(mMockCallback);
mDismissCallbackRegistry.addCallback(mMockCallback2);
mDismissCallbackRegistry.notifyDismissSucceeded();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mMockCallback).onDismissSucceeded();
verify(mMockCallback2).onDismissSucceeded();
}
@@ -89,7 +92,7 @@ public class DismissCallbackRegistryTest extends SysuiTestCase {
mDismissCallbackRegistry.addCallback(mMockCallback);
mDismissCallbackRegistry.notifyDismissSucceeded();
mDismissCallbackRegistry.notifyDismissSucceeded();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mMockCallback, times(1)).onDismissSucceeded();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index a8a2b33215e5..64fbc1bac658 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -38,6 +38,8 @@ import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarWindowController;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
@@ -58,6 +60,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
private @Mock StatusBarWindowController mStatusBarWindowController;
private @Mock BroadcastDispatcher mBroadcastDispatcher;
private @Mock DismissCallbackRegistry mDismissCallbackRegistry;
+ private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
private FalsingManagerFake mFalsingManager;
@@ -75,7 +78,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
mViewMediator = new KeyguardViewMediator(
mContext, mFalsingManager, mLockPatternUtils, mBroadcastDispatcher,
mStatusBarWindowController, () -> mStatusBarKeyguardViewManager,
- mDismissCallbackRegistry);
+ mDismissCallbackRegistry, mUiBgExecutor);
});
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
index 9f90396e08d5..6e9c2c8adb4a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifListBuilderImplTest.java
@@ -727,7 +727,7 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
mListBuilder.addPreGroupFilter(filter3);
// GIVEN the SystemClock is set to a particular time:
- mSystemClock.setUptimeMillis(47);
+ mSystemClock.setUptimeMillis(10047);
// WHEN the pipeline is kicked off on a list of notifs
addNotif(0, PACKAGE_1);
@@ -735,12 +735,12 @@ public class NotifListBuilderImplTest extends SysuiTestCase {
dispatchBuild();
// THEN the value of `now` is the same for all calls to shouldFilterOut
- verify(filter1).shouldFilterOut(mEntrySet.get(0), 47);
- verify(filter2).shouldFilterOut(mEntrySet.get(0), 47);
- verify(filter3).shouldFilterOut(mEntrySet.get(0), 47);
- verify(filter1).shouldFilterOut(mEntrySet.get(1), 47);
- verify(filter2).shouldFilterOut(mEntrySet.get(1), 47);
- verify(filter3).shouldFilterOut(mEntrySet.get(1), 47);
+ verify(filter1).shouldFilterOut(mEntrySet.get(0), 10047);
+ verify(filter2).shouldFilterOut(mEntrySet.get(0), 10047);
+ verify(filter3).shouldFilterOut(mEntrySet.get(0), 10047);
+ verify(filter1).shouldFilterOut(mEntrySet.get(1), 10047);
+ verify(filter2).shouldFilterOut(mEntrySet.get(1), 10047);
+ verify(filter3).shouldFilterOut(mEntrySet.get(1), 10047);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java
index 4f1ffbe50fc1..2662c80dce1d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/ExpansionStateLoggerTest.java
@@ -29,10 +29,10 @@ import androidx.test.filters.SmallTest;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
@@ -52,12 +52,12 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
private NotificationLogger.ExpansionStateLogger mLogger;
@Mock
private IStatusBarService mBarService;
+ private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mLogger = new NotificationLogger.ExpansionStateLogger(
- Dependency.get(UiOffloadThread.class));
+ mLogger = new NotificationLogger.ExpansionStateLogger(mUiBgExecutor);
mLogger.mBarService = mBarService;
}
@@ -66,7 +66,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
mLogger.onVisibilityChanged(
Collections.singletonList(createNotificationVisibility(NOTIFICATION_KEY, true)),
Collections.emptyList());
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, Mockito.never()).onNotificationExpansionChanged(
eq(NOTIFICATION_KEY), anyBoolean(), anyBoolean(), anyInt());
@@ -76,7 +76,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
public void testExpanded() throws RemoteException {
mLogger.onExpansionChanged(NOTIFICATION_KEY, false, true,
NotificationVisibility.NotificationLocation.LOCATION_UNKNOWN);
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, Mockito.never()).onNotificationExpansionChanged(
eq(NOTIFICATION_KEY), anyBoolean(), anyBoolean(), anyInt());
@@ -89,7 +89,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
mLogger.onVisibilityChanged(
Collections.singletonList(createNotificationVisibility(NOTIFICATION_KEY, true)),
Collections.emptyList());
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, Mockito.never()).onNotificationExpansionChanged(
eq(NOTIFICATION_KEY), anyBoolean(), anyBoolean(), anyInt());
@@ -102,7 +102,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
mLogger.onVisibilityChanged(
Collections.singletonList(createNotificationVisibility(NOTIFICATION_KEY, true)),
Collections.emptyList());
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService).onNotificationExpansionChanged(
NOTIFICATION_KEY, true, true,
@@ -117,7 +117,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
Collections.singletonList(createNotificationVisibility(NOTIFICATION_KEY, true,
NotificationVisibility.NotificationLocation.LOCATION_MAIN_AREA)),
Collections.emptyList());
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService).onNotificationExpansionChanged(
NOTIFICATION_KEY, false, true,
@@ -133,7 +133,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
Collections.emptyList());
mLogger.onExpansionChanged(NOTIFICATION_KEY, false, true,
NotificationVisibility.NotificationLocation.LOCATION_FIRST_HEADS_UP);
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService).onNotificationExpansionChanged(
NOTIFICATION_KEY, false, true,
@@ -150,7 +150,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
NotificationVisibility.NotificationLocation.LOCATION_UNKNOWN);
mLogger.onExpansionChanged(NOTIFICATION_KEY, false, true,
NotificationVisibility.NotificationLocation.LOCATION_UNKNOWN);
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService).onNotificationExpansionChanged(
NOTIFICATION_KEY, false, true,
@@ -164,7 +164,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
mLogger.onVisibilityChanged(
Collections.singletonList(createNotificationVisibility(NOTIFICATION_KEY, true)),
Collections.emptyList());
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService).onNotificationExpansionChanged(
NOTIFICATION_KEY, true, true, ExpandableViewState.LOCATION_UNKNOWN);
@@ -172,7 +172,7 @@ public class ExpansionStateLoggerTest extends SysuiTestCase {
mLogger.onVisibilityChanged(
Collections.singletonList(createNotificationVisibility(NOTIFICATION_KEY, true)),
Collections.emptyList());
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
// onNotificationExpansionChanged is called the second time.
verify(mBarService, times(2)).onNotificationExpansionChanged(
NOTIFICATION_KEY, true, true, ExpandableViewState.LOCATION_UNKNOWN);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index e23d0ae89a09..d826ce1bbdd8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -11,7 +11,7 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
package com.android.systemui.statusbar.notification.logging;
@@ -36,9 +36,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.Dependency;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.statusbar.NotificationListener;
import com.android.systemui.statusbar.StatusBarStateControllerImpl;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
@@ -47,6 +45,8 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import com.google.android.collect.Lists;
@@ -60,6 +60,7 @@ import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Executor;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -82,6 +83,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
private TestableNotificationLogger mLogger;
private NotificationEntryListener mNotificationEntryListener;
private ConcurrentLinkedQueue<AssertionError> mErrorQueue = new ConcurrentLinkedQueue<>();
+ private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@Before
public void setUp() {
@@ -98,7 +100,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
.build();
mEntry.setRow(mRow);
- mLogger = new TestableNotificationLogger(mListener, Dependency.get(UiOffloadThread.class),
+ mLogger = new TestableNotificationLogger(mListener, mUiBgExecutor,
mEntryManager, mock(StatusBarStateControllerImpl.class), mBarService,
mExpansionStateLogger);
mLogger.setUpWithContainer(mListContainer);
@@ -130,7 +132,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
when(mEntryManager.getVisibleNotifications()).thenReturn(Lists.newArrayList(mEntry));
mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
TestableLooper.get(this).processAllMessages();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
if(!mErrorQueue.isEmpty()) {
throw mErrorQueue.poll();
@@ -140,7 +142,7 @@ public class NotificationLoggerTest extends SysuiTestCase {
Mockito.reset(mBarService);
mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
TestableLooper.get(this).processAllMessages();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, never()).onNotificationVisibilityChanged(any(), any());
}
@@ -152,11 +154,11 @@ public class NotificationLoggerTest extends SysuiTestCase {
when(mEntryManager.getVisibleNotifications()).thenReturn(Lists.newArrayList(mEntry));
mLogger.getChildLocationsChangedListenerForTest().onChildLocationsChanged();
TestableLooper.get(this).processAllMessages();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
Mockito.reset(mBarService);
mLogger.stopNotificationLogging();
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
// The visibility objects are recycled by NotificationLogger, so we can't use specific
// matchers here.
verify(mBarService, times(1)).onNotificationVisibilityChanged(any(), any());
@@ -165,12 +167,12 @@ public class NotificationLoggerTest extends SysuiTestCase {
private class TestableNotificationLogger extends NotificationLogger {
TestableNotificationLogger(NotificationListener notificationListener,
- UiOffloadThread uiOffloadThread,
+ Executor uiBgExecutor,
NotificationEntryManager entryManager,
StatusBarStateControllerImpl statusBarStateController,
IStatusBarService barService,
ExpansionStateLogger expansionStateLogger) {
- super(notificationListener, uiOffloadThread, entryManager, statusBarStateController,
+ super(notificationListener, uiBgExecutor, entryManager, statusBarStateController,
expansionStateLogger);
mBarService = barService;
// Make this on the current thread so we can wait for it during tests.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
index 532192ba97ae..86b2a44a1acb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterTest.java
@@ -72,6 +72,8 @@ import com.android.systemui.statusbar.notification.NotificationInterruptionState
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before;
import org.junit.Test;
@@ -126,6 +128,7 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
private SuperStatusBarViewFactory mSuperStatusBarViewFactory;
@Mock
private NotificationPanelView mNotificationPanelView;
+ private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
private NotificationTestHelper mNotificationTestHelper;
private ExpandableNotificationRow mNotificationRow;
@@ -178,8 +181,9 @@ public class StatusBarNotificationActivityStarterTest extends SysuiTestCase {
mock(NotificationLockscreenUserManager.class),
mKeyguardStateController,
mock(NotificationInterruptionStateProvider.class), mock(MetricsLogger.class),
- mock(LockPatternUtils.class), mHandler, mHandler, mActivityIntentHelper,
- mBubbleController, mShadeController, mSuperStatusBarViewFactory))
+ mock(LockPatternUtils.class), mHandler, mHandler, mUiBgExecutor,
+ mActivityIntentHelper, mBubbleController, mShadeController,
+ mSuperStatusBarViewFactory))
.setStatusBar(mStatusBar)
.setNotificationPresenter(mock(NotificationPresenter.class))
.setActivityLaunchAnimator(mock(ActivityLaunchAnimator.class))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index d3ae7a783404..ca229c9a6a57 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -78,7 +78,6 @@ import com.android.systemui.Dependency;
import com.android.systemui.InitController;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.UiOffloadThread;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
@@ -133,6 +132,8 @@ import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.RemoteInputUriController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
import com.android.systemui.volume.VolumeComponent;
import org.junit.Before;
@@ -245,6 +246,7 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private StatusBarNotificationActivityStarter.Builder
mStatusBarNotificationActivityStarterBuilder;
private ShadeController mShadeController;
+ private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@Before
public void setup() throws Exception {
@@ -266,7 +268,7 @@ public class StatusBarTest extends SysuiTestCase {
mMetricsLogger = new FakeMetricsLogger();
NotificationLogger notificationLogger = new NotificationLogger(mNotificationListener,
- Dependency.get(UiOffloadThread.class), mEntryManager, mStatusBarStateController,
+ mUiBgExecutor, mEntryManager, mStatusBarStateController,
mExpansionStateLogger);
notificationLogger.setVisibilityReporter(mock(Runnable.class));
@@ -349,7 +351,7 @@ public class StatusBarTest extends SysuiTestCase {
mNotificationAlertingManager,
new DisplayMetrics(),
mMetricsLogger,
- Dependency.get(UiOffloadThread.class),
+ mUiBgExecutor,
mNotificationMediaManager,
mLockscreenUserManager,
mRemoteInputManager,
@@ -641,7 +643,7 @@ public class StatusBarTest extends SysuiTestCase {
public void testLogHidden() {
try {
mStatusBar.handleVisibleToUserChanged(false);
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, times(1)).onPanelHidden();
verify(mBarService, never()).onPanelRevealed(anyBoolean(), anyInt());
} catch (RemoteException e) {
@@ -659,7 +661,7 @@ public class StatusBarTest extends SysuiTestCase {
try {
mStatusBar.handleVisibleToUserChanged(true);
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, never()).onPanelHidden();
verify(mBarService, times(1)).onPanelRevealed(false, 1);
} catch (RemoteException e) {
@@ -678,7 +680,7 @@ public class StatusBarTest extends SysuiTestCase {
try {
mStatusBar.handleVisibleToUserChanged(true);
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, never()).onPanelHidden();
verify(mBarService, times(1)).onPanelRevealed(true, 5);
} catch (RemoteException e) {
@@ -696,7 +698,7 @@ public class StatusBarTest extends SysuiTestCase {
try {
mStatusBar.handleVisibleToUserChanged(true);
- waitForUiOffloadThread();
+ mUiBgExecutor.runAllReady();
verify(mBarService, never()).onPanelHidden();
verify(mBarService, times(1)).onPanelRevealed(false, 5);
} catch (RemoteException e) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java
index f3c053058468..7c7ad5322d48 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutor.java
@@ -17,7 +17,6 @@
package com.android.systemui.util.concurrency;
import com.android.systemui.util.time.FakeSystemClock;
-import com.android.systemui.util.time.FakeSystemClock.ClockTickListener;
import java.util.Collections;
import java.util.PriorityQueue;
@@ -29,15 +28,6 @@ public class FakeExecutor implements DelayableExecutor {
private PriorityQueue<QueuedRunnable> mQueuedRunnables = new PriorityQueue<>();
private boolean mIgnoreClockUpdates;
- private ClockTickListener mClockTickListener = new ClockTickListener() {
- @Override
- public void onUptimeMillis(long uptimeMillis) {
- if (!mIgnoreClockUpdates) {
- runAllReady();
- }
- }
- };
-
/**
* Initializes a fake executor.
*
@@ -47,7 +37,11 @@ public class FakeExecutor implements DelayableExecutor {
*/
public FakeExecutor(FakeSystemClock clock) {
mClock = clock;
- mClock.addListener(mClockTickListener);
+ mClock.addListener(() -> {
+ if (!mIgnoreClockUpdates) {
+ runAllReady();
+ }
+ });
}
/**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java
index bd641243be12..abc283f40b1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/concurrency/FakeExecutorTest.java
@@ -52,28 +52,28 @@ public class FakeExecutorTest extends SysuiTestCase {
FakeExecutor fakeExecutor = new FakeExecutor(clock);
RunnableImpl runnable = new RunnableImpl();
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(0, runnable.mRunCount);
// Execute two runnables. They should not run and should be left pending.
fakeExecutor.execute(runnable);
assertEquals(0, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(1, fakeExecutor.numPending());
fakeExecutor.execute(runnable);
assertEquals(0, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(2, fakeExecutor.numPending());
// Run one pending runnable.
assertTrue(fakeExecutor.runNextReady());
assertEquals(1, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(1, fakeExecutor.numPending());
// Run a second pending runnable.
assertTrue(fakeExecutor.runNextReady());
assertEquals(2, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(0, fakeExecutor.numPending());
// No more runnables to run.
@@ -83,12 +83,12 @@ public class FakeExecutorTest extends SysuiTestCase {
fakeExecutor.execute(runnable);
fakeExecutor.execute(runnable);
assertEquals(2, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(2, fakeExecutor.numPending());
// Execute all pending runnables in batch.
assertEquals(2, fakeExecutor.runAllReady());
assertEquals(4, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(0, fakeExecutor.runAllReady());
}
@@ -106,7 +106,7 @@ public class FakeExecutorTest extends SysuiTestCase {
fakeExecutor.executeDelayed(runnable, 50);
fakeExecutor.executeDelayed(runnable, 100);
assertEquals(0, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(3, fakeExecutor.numPending());
// Delayed runnables should not advance the clock and therefore should not run.
assertFalse(fakeExecutor.runNextReady());
@@ -140,7 +140,7 @@ public class FakeExecutorTest extends SysuiTestCase {
fakeExecutor.executeDelayed(runnable, 50);
fakeExecutor.executeDelayed(runnable, 100);
assertEquals(0, runnable.mRunCount);
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
assertEquals(3, fakeExecutor.numPending());
// Delayed runnables should not advance the clock and therefore should not run.
assertFalse(fakeExecutor.runNextReady());
@@ -150,24 +150,24 @@ public class FakeExecutorTest extends SysuiTestCase {
// Advance the clock to the next runnable. Check that it is run.
assertEquals(1, fakeExecutor.advanceClockToNext());
assertEquals(1, fakeExecutor.runAllReady());
- assertEquals(1, clock.uptimeMillis());
+ assertEquals(10001, clock.uptimeMillis());
assertEquals(2, fakeExecutor.numPending());
assertEquals(1, runnable.mRunCount);
assertEquals(49, fakeExecutor.advanceClockToNext());
assertEquals(1, fakeExecutor.runAllReady());
- assertEquals(50, clock.uptimeMillis());
+ assertEquals(10050, clock.uptimeMillis());
assertEquals(1, fakeExecutor.numPending());
assertEquals(2, runnable.mRunCount);
assertEquals(50, fakeExecutor.advanceClockToNext());
assertEquals(1, fakeExecutor.runAllReady());
- assertEquals(100, clock.uptimeMillis());
+ assertEquals(10100, clock.uptimeMillis());
assertEquals(0, fakeExecutor.numPending());
assertEquals(3, runnable.mRunCount);
// Nothing left to do
assertEquals(0, fakeExecutor.advanceClockToNext());
assertEquals(0, fakeExecutor.runAllReady());
- assertEquals(100, clock.uptimeMillis());
+ assertEquals(10100, clock.uptimeMillis());
assertEquals(0, fakeExecutor.numPending());
assertEquals(3, runnable.mRunCount);
}
@@ -193,7 +193,7 @@ public class FakeExecutorTest extends SysuiTestCase {
return null;
};
- assertEquals(0, clock.uptimeMillis());
+ assertEquals(10000, clock.uptimeMillis());
checkRunCounts.invoke(0, 0, 0, 0);
fakeExecutor.execute(runnableA);
@@ -227,8 +227,8 @@ public class FakeExecutorTest extends SysuiTestCase {
fakeExecutor.execute(runnableA);
fakeExecutor.executeAtTime(runnableB, 0); // this is in the past!
- fakeExecutor.executeAtTime(runnableC, 1000);
- fakeExecutor.executeAtTime(runnableD, 500);
+ fakeExecutor.executeAtTime(runnableC, 11000);
+ fakeExecutor.executeAtTime(runnableD, 10500);
fakeExecutor.advanceClockToNext();
fakeExecutor.runAllReady();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java b/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java
index e94eaafdb692..601f88e0a9c6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/time/FakeSystemClock.java
@@ -16,94 +16,70 @@
package com.android.systemui.util.time;
+import com.android.systemui.util.concurrency.FakeExecutor;
+
import java.util.ArrayList;
import java.util.List;
+/**
+ * A fake {@link SystemClock} for use with {@link FakeExecutor}.
+ *
+ * Attempts to simulate the behavior of a real system clock. Time can be moved forward but not
+ * backwards. uptimeMillis, elapsedRealtime, and currentThreadTimeMillis are all kept in sync.
+ *
+ * Unless otherwise specified, uptimeMillis and elapsedRealtime will advance the same amount with
+ * every call to {@link #advanceTime(long)}. Thread time always lags by 50% of the uptime
+ * advancement to simulate time loss due to scheduling.
+ */
public class FakeSystemClock implements SystemClock {
- private long mUptimeMillis;
- private long mElapsedRealtime;
- private long mElapsedRealtimeNanos;
- private long mCurrentThreadTimeMillis;
- private long mCurrentThreadTimeMicro;
- private long mCurrentTimeMicro;
+ private long mUptimeMillis = 10000;
+ private long mElapsedRealtime = 10000;
+ private long mCurrentThreadTimeMillis = 10000;
- List<ClockTickListener> mListeners = new ArrayList<>();
+ private final List<ClockTickListener> mListeners = new ArrayList<>();
@Override
public long uptimeMillis() {
- long value = mUptimeMillis;
- return value;
+ return mUptimeMillis;
}
@Override
public long elapsedRealtime() {
- long value = mElapsedRealtime;
- return value;
+ return mElapsedRealtime;
}
@Override
public long elapsedRealtimeNanos() {
- long value = mElapsedRealtimeNanos;
- return value;
+ return mElapsedRealtime * 1000000 + 447;
}
@Override
public long currentThreadTimeMillis() {
- long value = mCurrentThreadTimeMillis;
- return value;
- }
-
- @Override
- public long currentThreadTimeMicro() {
- long value = mCurrentThreadTimeMicro;
- return value;
+ return mCurrentThreadTimeMillis;
}
- @Override
- public long currentTimeMicro() {
- long value = mCurrentTimeMicro;
- return value;
+ public void setUptimeMillis(long uptime) {
+ advanceTime(uptime - mUptimeMillis);
}
- public void setUptimeMillis(long uptimeMillis) {
- mUptimeMillis = uptimeMillis;
- for (ClockTickListener listener : mListeners) {
- listener.onUptimeMillis(mUptimeMillis);
- }
+ public void advanceTime(long uptime) {
+ advanceTime(uptime, 0);
}
- public void setElapsedRealtime(long elapsedRealtime) {
- mElapsedRealtime = elapsedRealtime;
- for (ClockTickListener listener : mListeners) {
- listener.onElapsedRealtime(mElapsedRealtime);
+ public void advanceTime(long uptime, long sleepTime) {
+ if (uptime < 0 || sleepTime < 0) {
+ throw new IllegalArgumentException("Time cannot go backwards");
}
- }
- public void setElapsedRealtimeNanos(long elapsedRealtimeNanos) {
- mElapsedRealtimeNanos = elapsedRealtimeNanos;
- for (ClockTickListener listener : mListeners) {
- listener.onElapsedRealtimeNanos(mElapsedRealtimeNanos);
- }
- }
+ if (uptime > 0 || sleepTime > 0) {
+ mUptimeMillis += uptime;
+ mElapsedRealtime += uptime + sleepTime;
- public void setCurrentThreadTimeMillis(long currentThreadTimeMillis) {
- mCurrentThreadTimeMillis = currentThreadTimeMillis;
- for (ClockTickListener listener : mListeners) {
- listener.onCurrentThreadTimeMillis(mCurrentThreadTimeMillis);
- }
- }
+ mCurrentThreadTimeMillis += Math.ceil(uptime * 0.5);
- public void setCurrentThreadTimeMicro(long currentThreadTimeMicro) {
- mCurrentThreadTimeMicro = currentThreadTimeMicro;
- for (ClockTickListener listener : mListeners) {
- listener.onCurrentThreadTimeMicro(mCurrentThreadTimeMicro);
- }
- }
-
- public void setCurrentTimeMicro(long currentTimeMicro) {
- mCurrentTimeMicro = currentTimeMicro;
- for (ClockTickListener listener : mListeners) {
- listener.onCurrentTimeMicro(mCurrentTimeMicro);
+ for (ClockTickListener listener : mListeners) {
+ listener.onClockTick();
+ }
}
}
@@ -115,30 +91,9 @@ public class FakeSystemClock implements SystemClock {
mListeners.remove(listener);
}
- /** Alert all the listeners about the current time. */
- public void synchronizeListeners() {
- for (ClockTickListener listener : mListeners) {
- listener.onUptimeMillis(mUptimeMillis);
- listener.onElapsedRealtime(mElapsedRealtime);
- listener.onElapsedRealtimeNanos(mElapsedRealtimeNanos);
- listener.onCurrentThreadTimeMillis(mCurrentThreadTimeMillis);
- listener.onCurrentThreadTimeMicro(mCurrentThreadTimeMicro);
- listener.onCurrentTimeMicro(mCurrentTimeMicro);
- }
- }
-
-
public interface ClockTickListener {
- default void onUptimeMillis(long uptimeMillis) {}
-
- default void onElapsedRealtime(long elapsedRealtime) {}
-
- default void onElapsedRealtimeNanos(long elapsedRealtimeNanos) {}
-
- default void onCurrentThreadTimeMillis(long currentThreadTimeMillis) {}
-
- default void onCurrentThreadTimeMicro(long currentThreadTimeMicro) {}
-
- default void onCurrentTimeMicro(long currentTimeMicro) {}
+ void onClockTick();
}
+
+ private static final long START_TIME = 10000;
}
diff --git a/packages/WindowManager/OWNERS b/packages/WindowManager/OWNERS
new file mode 100644
index 000000000000..063d4594f2fa
--- /dev/null
+++ b/packages/WindowManager/OWNERS
@@ -0,0 +1,3 @@
+set noparent
+
+include ../../services/core/java/com/android/server/wm/OWNERS \ No newline at end of file
diff --git a/packages/WindowManager/Shell/Android.bp b/packages/WindowManager/Shell/Android.bp
new file mode 100644
index 000000000000..b8934dc8c583
--- /dev/null
+++ b/packages/WindowManager/Shell/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_library {
+ name: "WindowManager-Shell",
+ srcs: [
+ "src/**/*.java",
+ "src/**/I*.aidl",
+ ],
+ resource_dirs: [
+ "res",
+ ],
+ manifest: "AndroidManifest.xml",
+
+ platform_apis: true,
+ sdk_version: "current",
+ min_sdk_version: "system_current",
+}
diff --git a/packages/WindowManager/Shell/AndroidManifest.xml b/packages/WindowManager/Shell/AndroidManifest.xml
new file mode 100644
index 000000000000..ea8a5c305029
--- /dev/null
+++ b/packages/WindowManager/Shell/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.wm.shell">
+</manifest>
diff --git a/packages/WindowManager/Shell/OWNERS b/packages/WindowManager/Shell/OWNERS
new file mode 100644
index 000000000000..4390004f5f93
--- /dev/null
+++ b/packages/WindowManager/Shell/OWNERS
@@ -0,0 +1,4 @@
+# sysui owners
+hwwang@google.com
+mrenouf@google.com
+winsonc@google.com \ No newline at end of file
diff --git a/packages/WindowManager/Shell/res/values/config.xml b/packages/WindowManager/Shell/res/values/config.xml
new file mode 100644
index 000000000000..c894eb0133b5
--- /dev/null
+++ b/packages/WindowManager/Shell/res/values/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+</resources> \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgLooper.java b/packages/WindowManager/Shell/src/com/android/wm/shell/WindowManagerShell.java
index 2aadda1215d5..273bd27a221b 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/qualifiers/BgLooper.java
+++ b/packages/WindowManager/Shell/src/com/android/wm/shell/WindowManagerShell.java
@@ -14,17 +14,10 @@
* limitations under the License.
*/
-package com.android.systemui.dagger.qualifiers;
+package com.android.wm.shell;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-
-import javax.inject.Qualifier;
-
-@Qualifier
-@Documented
-@Retention(RUNTIME)
-public @interface BgLooper {
+/**
+ * Interface for the shell.
+ */
+public class WindowManagerShell {
}
diff --git a/packages/WindowManager/Shell/tests/Android.bp b/packages/WindowManager/Shell/tests/Android.bp
new file mode 100644
index 000000000000..78fa45ebdf94
--- /dev/null
+++ b/packages/WindowManager/Shell/tests/Android.bp
@@ -0,0 +1,45 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+ name: "WindowManagerShellTests",
+
+ srcs: ["**/*.java"],
+
+ static_libs: [
+ "WindowManager-Shell",
+ "junit",
+ "androidx.test.runner",
+ "androidx.test.rules",
+ "androidx.test.ext.junit",
+ "mockito-target-extended-minus-junit4",
+ "truth-prebuilt",
+ ],
+ libs: [
+ "android.test.mock",
+ "android.test.base",
+ "android.test.runner",
+ ],
+ jni_libs: [
+ "libdexmakerjvmtiagent",
+ "libstaticjvmtiagent",
+ ],
+
+ sdk_version: "current",
+ platform_apis: true,
+
+ optimize: {
+ enabled: false,
+ },
+}
diff --git a/packages/WindowManager/Shell/tests/AndroidManifest.xml b/packages/WindowManager/Shell/tests/AndroidManifest.xml
new file mode 100644
index 000000000000..a8f795ec8a8d
--- /dev/null
+++ b/packages/WindowManager/Shell/tests/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="com.android.wm.shell.tests">
+
+ <application android:debuggable="true" android:largeHeap="true">
+ <uses-library android:name="android.test.mock" />
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:label="Tests for WindowManager-Shell"
+ android:targetPackage="com.android.wm.shell.tests">
+ </instrumentation>
+</manifest>
diff --git a/packages/WindowManager/Shell/tests/AndroidTest.xml b/packages/WindowManager/Shell/tests/AndroidTest.xml
new file mode 100644
index 000000000000..4dce4db360e4
--- /dev/null
+++ b/packages/WindowManager/Shell/tests/AndroidTest.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs Tests for WindowManagerShellLib">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
+ <option name="test-file-name" value="WindowManagerShellTests.apk" />
+ </target_preparer>
+
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="framework-base-presubmit" />
+ <option name="test-tag" value="WindowManagerShellTests" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.wm.shell.tests" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/packages/WindowManager/Shell/tests/res/values/config.xml b/packages/WindowManager/Shell/tests/res/values/config.xml
new file mode 100644
index 000000000000..c894eb0133b5
--- /dev/null
+++ b/packages/WindowManager/Shell/tests/res/values/config.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<resources>
+</resources> \ No newline at end of file
diff --git a/packages/WindowManager/Shell/tests/src/com/android/wm/shell/tests/WindowManagerShellTest.java b/packages/WindowManager/Shell/tests/src/com/android/wm/shell/tests/WindowManagerShellTest.java
new file mode 100644
index 000000000000..376875b143a1
--- /dev/null
+++ b/packages/WindowManager/Shell/tests/src/com/android/wm/shell/tests/WindowManagerShellTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.tests;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.WindowManagerShell;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for the shell.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WindowManagerShellTest {
+
+ WindowManagerShell mShell;
+
+ @Test
+ public void testNothing() {
+ // Do nothing
+ }
+}
diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk
index 3eb90491f902..eecc10158e8a 100644
--- a/packages/overlays/Android.mk
+++ b/packages/overlays/Android.mk
@@ -42,7 +42,7 @@ LOCAL_REQUIRED_MODULES := \
IconPackRoundedLauncherOverlay \
IconPackRoundedSettingsOverlay \
IconPackRoundedSystemUIOverlay \
- IconPackRoundedThemePickerUIOverlay \
+ IconPackRoundedThemePickerOverlay \
IconShapeRoundedRectOverlay \
IconShapeSquircleOverlay \
IconShapeTeardropOverlay \
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
index 9b7adc883dee..50d21ba59996 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/GestureManifold.java
@@ -77,6 +77,8 @@ class GestureManifold implements GestureMatcher.StateChangeListener {
// Start with double tap.
mGestures.add(new MultiTap(context, 2, GESTURE_DOUBLE_TAP, this));
mGestures.add(new MultiTapAndHold(context, 2, GESTURE_DOUBLE_TAP_AND_HOLD, this));
+ // Second-finger double tap.
+ mGestures.add(new SecondFingerMultiTap(context, 2, GESTURE_DOUBLE_TAP, this));
// One-direction swipes.
mGestures.add(new Swipe(context, RIGHT, GESTURE_SWIPE_RIGHT, this));
mGestures.add(new Swipe(context, LEFT, GESTURE_SWIPE_LEFT, this));
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/SecondFingerMultiTap.java b/services/accessibility/java/com/android/server/accessibility/gestures/SecondFingerMultiTap.java
new file mode 100644
index 000000000000..eb38b53dc52a
--- /dev/null
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/SecondFingerMultiTap.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility.gestures;
+
+import static android.view.MotionEvent.INVALID_POINTER_ID;
+
+import android.content.Context;
+import android.os.Handler;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+
+/**
+ * This class matches second-finger multi-tap gestures. A second-finger multi-tap gesture is where
+ * one finger is held down and a second finger executes the taps. The number of taps for each
+ * instance is specified in the constructor.
+ */
+class SecondFingerMultiTap extends GestureMatcher {
+ final int mTargetTaps;
+ int mDoubleTapSlop;
+ int mTouchSlop;
+ int mTapTimeout;
+ int mDoubleTapTimeout;
+ int mCurrentTaps;
+ int mSecondFingerPointerId;
+ float mBaseX;
+ float mBaseY;
+
+ SecondFingerMultiTap(
+ Context context, int taps, int gesture, GestureMatcher.StateChangeListener listener) {
+ super(gesture, new Handler(context.getMainLooper()), listener);
+ mTargetTaps = taps;
+ mDoubleTapSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop();
+ mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+ mTapTimeout = ViewConfiguration.getTapTimeout();
+ mDoubleTapTimeout = ViewConfiguration.getDoubleTapTimeout();
+ clear();
+ }
+
+ @Override
+ protected void clear() {
+ mCurrentTaps = 0;
+ mBaseX = Float.NaN;
+ mBaseY = Float.NaN;
+ mSecondFingerPointerId = INVALID_POINTER_ID;
+ super.clear();
+ }
+
+ @Override
+ protected void onPointerDown(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ if (event.getPointerCount() > 2) {
+ cancelGesture(event, rawEvent, policyFlags);
+ return;
+ }
+ // Second finger has gone down.
+ int index = getActionIndex(event);
+ mSecondFingerPointerId = event.getPointerId(index);
+ cancelAfterTapTimeout(event, rawEvent, policyFlags);
+ if (Float.isNaN(mBaseX) && Float.isNaN(mBaseY)) {
+ mBaseX = event.getX();
+ mBaseY = event.getY();
+ }
+ if (!isSecondFingerInsideSlop(rawEvent, mDoubleTapSlop)) {
+ cancelGesture(event, rawEvent, policyFlags);
+ }
+ mBaseX = event.getX();
+ mBaseY = event.getY();
+ }
+
+ @Override
+ protected void onPointerUp(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ if (event.getPointerCount() > 2) {
+ cancelGesture(event, rawEvent, policyFlags);
+ return;
+ }
+ cancelAfterDoubleTapTimeout(event, rawEvent, policyFlags);
+ if (!isSecondFingerInsideSlop(rawEvent, mTouchSlop)) {
+ cancelGesture(event, rawEvent, policyFlags);
+ }
+ if (getState() == STATE_GESTURE_STARTED || getState() == STATE_CLEAR) {
+ mCurrentTaps++;
+ if (mCurrentTaps == mTargetTaps) {
+ // Done.
+ completeGesture(event, rawEvent, policyFlags);
+ return;
+ }
+ // Needs more taps.
+ cancelAfterDoubleTapTimeout(event, rawEvent, policyFlags);
+ } else {
+ // Nonsensical event stream.
+ cancelGesture(event, rawEvent, policyFlags);
+ }
+ }
+
+ @Override
+ protected void onMove(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+ switch (event.getPointerCount()) {
+ case 1:
+ // We don't need to track anything about one-finger movements.
+ break;
+ case 2:
+ if (!isSecondFingerInsideSlop(rawEvent, mTouchSlop)) {
+ cancelGesture(event, rawEvent, policyFlags);
+ }
+ break;
+ default:
+ // More than two fingers means we stop tracking.
+ cancelGesture(event, rawEvent, policyFlags);
+ break;
+ }
+ }
+
+ @Override
+ public String getGestureName() {
+ switch (mTargetTaps) {
+ case 2:
+ return "Second Finger Double Tap";
+ case 3:
+ return "Second Finger Triple Tap";
+ default:
+ return "Second Finger " + Integer.toString(mTargetTaps) + " Taps";
+ }
+ }
+
+ private boolean isSecondFingerInsideSlop(MotionEvent rawEvent, int slop) {
+ int pointerIndex = rawEvent.findPointerIndex(mSecondFingerPointerId);
+ if (pointerIndex == -1) {
+ return false;
+ }
+ final float deltaX = mBaseX - rawEvent.getX(pointerIndex);
+ final float deltaY = mBaseY - rawEvent.getY(pointerIndex);
+ if (deltaX == 0 && deltaY == 0) {
+ return true;
+ }
+ final double moveDelta = Math.hypot(deltaX, deltaY);
+ return moveDelta <= slop;
+ }
+
+ private int getActionIndex(MotionEvent event) {
+ return event.getAction()
+ & MotionEvent.ACTION_POINTER_INDEX_MASK << MotionEvent.ACTION_POINTER_INDEX_SHIFT;
+ }
+
+ @Override
+ public String toString() {
+ return super.toString()
+ + ", Taps:"
+ + mCurrentTaps
+ + ", mBaseX: "
+ + Float.toString(mBaseX)
+ + ", mBaseY: "
+ + Float.toString(mBaseY);
+ }
+}
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index 5f4163880366..f6eb31b93f06 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -286,11 +286,6 @@ public class TouchExplorer extends BaseEventStreamTransformation
@Override
public void onDoubleTapAndHold() {
- // Ignore the event if we aren't touch interacting.
- if (!mState.isTouchInteracting()) {
- return;
- }
-
// Pointers should not be zero when running this command.
if (mState.getLastReceivedEvent().getPointerCount() == 0) {
return;
@@ -304,10 +299,6 @@ public class TouchExplorer extends BaseEventStreamTransformation
@Override
public boolean onDoubleTap() {
- if (!mState.isTouchInteracting()) {
- return false;
- }
-
mAms.onTouchInteractionEnd();
// Remove pending event deliveries.
mSendHoverEnterAndMoveDelayed.cancel();
@@ -454,7 +445,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
handleActionDown(event, rawEvent, policyFlags);
break;
case MotionEvent.ACTION_POINTER_DOWN:
- handleActionPointerDown();
+ handleActionPointerDown(event, rawEvent, policyFlags);
break;
case MotionEvent.ACTION_MOVE:
handleActionMoveStateTouchInteracting(event, rawEvent, policyFlags);
@@ -479,7 +470,7 @@ public class TouchExplorer extends BaseEventStreamTransformation
// We should have already received ACTION_DOWN. Ignore.
break;
case MotionEvent.ACTION_POINTER_DOWN:
- handleActionPointerDown();
+ handleActionPointerDown(event, rawEvent, policyFlags);
break;
case MotionEvent.ACTION_MOVE:
handleActionMoveStateTouchExploring(event, rawEvent, policyFlags);
@@ -496,12 +487,19 @@ public class TouchExplorer extends BaseEventStreamTransformation
* Handles ACTION_POINTER_DOWN when in the touch exploring state. This event represents an
* additional finger touching the screen.
*/
- private void handleActionPointerDown() {
+ private void handleActionPointerDown(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
// Another finger down means that if we have not started to deliver
// hover events, we will not have to. The code for ACTION_MOVE will
// decide what we will actually do next.
- mSendHoverEnterAndMoveDelayed.cancel();
- mSendHoverExitDelayed.cancel();
+
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ } else {
+ // We have already delivered at least one hover event, so send hover exit to keep the
+ // stream consistent.
+ sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
+ }
}
/**
* Handles ACTION_MOVE while in the touch interacting state. This is where transitions to
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 81ce359cc078..26245b15f92b 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -635,7 +635,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
mPackageManagerInternal.getSuspendedDialogInfo(providerPackage,
suspendingPackage, providerUserId);
onClickIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent(
- providerPackage, suspendingPackage, dialogInfo, providerUserId);
+ providerPackage, suspendingPackage, dialogInfo, null, providerUserId);
}
} else if (provider.maskedByQuietProfile) {
showBadge = true;
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 8f1e1568ead6..e976811a3094 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -18,6 +18,7 @@
package com.android.server.companion;
import static com.android.internal.util.CollectionUtils.size;
+import static com.android.internal.util.FunctionalUtils.uncheckExceptions;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.internal.util.Preconditions.checkState;
@@ -26,16 +27,15 @@ import static com.android.internal.util.function.pooled.PooledLambda.obtainRunna
import android.annotation.CheckResult;
import android.annotation.Nullable;
import android.app.PendingIntent;
+import android.companion.Association;
import android.companion.AssociationRequest;
import android.companion.CompanionDeviceManager;
import android.companion.ICompanionDeviceDiscoveryService;
-import android.companion.ICompanionDeviceDiscoveryServiceCallback;
import android.companion.ICompanionDeviceManager;
import android.companion.IFindDeviceCallback;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.ServiceConnection;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageItemInfo;
@@ -67,6 +67,9 @@ import android.util.Xml;
import com.android.internal.app.IAppOpsService;
import com.android.internal.content.PackageMonitor;
+import com.android.internal.infra.AndroidFuture;
+import com.android.internal.infra.PerUser;
+import com.android.internal.infra.ServiceConnector;
import com.android.internal.notification.NotificationAccessConfirmationActivityContract;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
@@ -118,12 +121,13 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
private final CompanionDeviceManagerImpl mImpl;
private final ConcurrentMap<Integer, AtomicFile> mUidToStorage = new ConcurrentHashMap<>();
private IDeviceIdleController mIdleController;
- private ServiceConnection mServiceConnection;
+ private PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>> mServiceConnectors;
private IAppOpsService mAppOpsManager;
private IFindDeviceCallback mFindDeviceCallback;
private AssociationRequest mRequest;
private String mCallingPackage;
+ private AndroidFuture<Association> mOngoingDeviceDiscovery;
private final Object mLock = new Object();
@@ -134,6 +138,19 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER));
mAppOpsManager = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
+
+ Intent serviceIntent = new Intent().setComponent(SERVICE_TO_BIND_TO);
+ mServiceConnectors = new PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>>() {
+ @Override
+ protected ServiceConnector<ICompanionDeviceDiscoveryService> create(int userId) {
+ return new ServiceConnector.Impl<>(
+ getContext(),
+ serviceIntent, 0/* bindingFlags */, userId,
+ ICompanionDeviceDiscoveryService.Stub::asInterface);
+ }
+ };
+
+
registerPackageMonitor();
}
@@ -187,7 +204,10 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
private void cleanup() {
synchronized (mLock) {
- mServiceConnection = unbind(mServiceConnection);
+ AndroidFuture<Association> ongoingDeviceDiscovery = mOngoingDeviceDiscovery;
+ if (ongoingDeviceDiscovery != null && !ongoingDeviceDiscovery.isDone()) {
+ ongoingDeviceDiscovery.cancel(true);
+ }
mFindDeviceCallback = unlinkToDeath(mFindDeviceCallback, this, 0);
mRequest = null;
mCallingPackage = null;
@@ -207,15 +227,6 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
return null;
}
- @Nullable
- @CheckResult
- private ServiceConnection unbind(@Nullable ServiceConnection conn) {
- if (conn != null) {
- getContext().unbindService(conn);
- }
- return null;
- }
-
class CompanionDeviceManagerImpl extends ICompanionDeviceManager.Stub {
@Override
@@ -243,13 +254,27 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
checkCallerIsSystemOr(callingPackage);
int userId = getCallingUserId();
checkUsesFeature(callingPackage, userId);
+
+ mFindDeviceCallback = callback;
+ mRequest = request;
+ mCallingPackage = callingPackage;
+ callback.asBinder().linkToDeath(CompanionDeviceManagerService.this /* recipient */, 0);
+
final long callingIdentity = Binder.clearCallingIdentity();
try {
- getContext().bindServiceAsUser(
- new Intent().setComponent(SERVICE_TO_BIND_TO),
- createServiceConnection(request, callback, callingPackage),
- Context.BIND_AUTO_CREATE,
- UserHandle.of(userId));
+ mOngoingDeviceDiscovery = mServiceConnectors.forUser(userId).postAsync(service -> {
+ AndroidFuture<Association> future = new AndroidFuture<>();
+ service.startDiscovery(request, callingPackage, callback, future);
+ return future;
+ }).whenComplete(uncheckExceptions((association, err) -> {
+ if (err == null) {
+ addAssociation(association);
+ } else {
+ Log.e(LOG_TAG, "Failed to discover device(s)", err);
+ callback.onFailure("No devices found: " + err.getMessage());
+ }
+ cleanup();
+ }));
} finally {
Binder.restoreCallingIdentity(callingIdentity);
}
@@ -386,82 +411,14 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
return Binder.getCallingUid() == Process.SYSTEM_UID;
}
- private ServiceConnection createServiceConnection(
- final AssociationRequest request,
- final IFindDeviceCallback findDeviceCallback,
- final String callingPackage) {
- mServiceConnection = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- if (DEBUG) {
- Slog.i(LOG_TAG,
- "onServiceConnected(name = " + name + ", service = "
- + service + ")");
- }
-
- mFindDeviceCallback = findDeviceCallback;
- mRequest = request;
- mCallingPackage = callingPackage;
-
- try {
- mFindDeviceCallback.asBinder().linkToDeath(
- CompanionDeviceManagerService.this, 0);
- } catch (RemoteException e) {
- cleanup();
- return;
- }
-
- try {
- ICompanionDeviceDiscoveryService.Stub
- .asInterface(service)
- .startDiscovery(
- request,
- callingPackage,
- findDeviceCallback,
- getServiceCallback());
- } catch (RemoteException e) {
- Log.e(LOG_TAG, "Error while initiating device discovery", e);
- }
- }
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- if (DEBUG) Slog.i(LOG_TAG, "onServiceDisconnected(name = " + name + ")");
- }
- };
- return mServiceConnection;
- }
-
- private ICompanionDeviceDiscoveryServiceCallback.Stub getServiceCallback() {
- return new ICompanionDeviceDiscoveryServiceCallback.Stub() {
-
- @Override
- public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
- throws RemoteException {
- try {
- return super.onTransact(code, data, reply, flags);
- } catch (Throwable e) {
- Slog.e(LOG_TAG, "Error during IPC", e);
- throw ExceptionUtils.propagate(e, RemoteException.class);
- }
- }
-
- @Override
- public void onDeviceSelected(String packageName, int userId, String deviceAddress) {
- addAssociation(userId, packageName, deviceAddress);
- cleanup();
- }
-
- @Override
- public void onDeviceSelectionCancel() {
- cleanup();
- }
- };
+ void addAssociation(int userId, String packageName, String deviceAddress) {
+ addAssociation(new Association(userId, deviceAddress, packageName));
}
- void addAssociation(int userId, String packageName, String deviceAddress) {
- updateSpecialAccessPermissionForAssociatedPackage(packageName, userId);
- recordAssociation(packageName, deviceAddress);
+ void addAssociation(Association association) {
+ updateSpecialAccessPermissionForAssociatedPackage(
+ association.companionAppPackage, association.userId);
+ recordAssociation(association);
}
void removeAssociation(int userId, String pkg, String deviceMacAddress) {
@@ -525,14 +482,15 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
}, getContext(), packageName, userId).recycleOnUse());
}
- private void recordAssociation(String priviledgedPackage, String deviceAddress) {
+ private void recordAssociation(Association association) {
if (DEBUG) {
- Log.i(LOG_TAG, "recordAssociation(priviledgedPackage = " + priviledgedPackage
- + ", deviceAddress = " + deviceAddress + ")");
+ Log.i(LOG_TAG, "recordAssociation(" + association + ")");
}
- int userId = getCallingUserId();
- updateAssociations(associations -> CollectionUtils.add(associations,
- new Association(userId, deviceAddress, priviledgedPackage)));
+ updateAssociations(associations -> CollectionUtils.add(associations, association));
+ }
+
+ private void recordAssociation(String privilegedPackage, String deviceAddress) {
+ recordAssociation(new Association(getCallingUserId(), deviceAddress, privilegedPackage));
}
private void updateAssociations(Function<Set<Association>, Set<Association>> update) {
@@ -629,41 +587,6 @@ public class CompanionDeviceManagerService extends SystemService implements Bind
}
}
-
-
- private class Association {
- public final int uid;
- public final String deviceAddress;
- public final String companionAppPackage;
-
- private Association(int uid, String deviceAddress, String companionAppPackage) {
- this.uid = uid;
- this.deviceAddress = checkNotNull(deviceAddress);
- this.companionAppPackage = checkNotNull(companionAppPackage);
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- Association that = (Association) o;
-
- if (uid != that.uid) return false;
- if (!deviceAddress.equals(that.deviceAddress)) return false;
- return companionAppPackage.equals(that.companionAppPackage);
-
- }
-
- @Override
- public int hashCode() {
- int result = uid;
- result = 31 * result + deviceAddress.hashCode();
- result = 31 * result + companionAppPackage.hashCode();
- return result;
- }
- }
-
private class ShellCmd extends ShellCommand {
public static final String USAGE = "help\n"
+ "list USER_ID\n"
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index f363a73b05af..40a7dfcfc18d 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -67,6 +67,27 @@ public abstract class PackageManagerInternal {
public static final int PACKAGE_COMPANION = 14;
@IntDef(value = {
+ INTEGRITY_VERIFICATION_ALLOW,
+ INTEGRITY_VERIFICATION_REJECT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface IntegrityVerificationResult {}
+
+ /**
+ * Used as the {@code verificationCode} argument for
+ * {@link PackageManagerInternal#setIntegrityVerificationResult(int, int)} to indicate that the
+ * integrity component allows the install to proceed.
+ */
+ public static final int INTEGRITY_VERIFICATION_ALLOW = 1;
+
+ /**
+ * Used as the {@code verificationCode} argument for
+ * {@link PackageManagerInternal#setIntegrityVerificationResult(int, int)} to indicate that the
+ * integrity component does not allow install to proceed.
+ */
+ public static final int INTEGRITY_VERIFICATION_REJECT = 0;
+
+ @IntDef(value = {
PACKAGE_SYSTEM,
PACKAGE_SETUP_WIZARD,
PACKAGE_INSTALLER,
@@ -842,13 +863,13 @@ public abstract class PackageManagerInternal {
* {@link Intent#ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION package verification
* broadcast} to respond to the package manager. The response must include
* the {@code verificationCode} which is one of
- * {@link PackageManager#VERIFICATION_ALLOW} or
- * {@link PackageManager#VERIFICATION_REJECT}.
+ * {@link #INTEGRITY_VERIFICATION_ALLOW} and {@link #INTEGRITY_VERIFICATION_REJECT}.
*
* @param verificationId pending package identifier as passed via the
* {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra.
- * @param verificationResult either {@link PackageManager#VERIFICATION_ALLOW}
- * or {@link PackageManager#VERIFICATION_REJECT}.
+ * @param verificationResult either {@link #INTEGRITY_VERIFICATION_ALLOW}
+ * or {@link #INTEGRITY_VERIFICATION_REJECT}.
*/
- public abstract void setIntegrityVerificationResult(int verificationId, int verificationResult);
+ public abstract void setIntegrityVerificationResult(int verificationId,
+ @IntegrityVerificationResult int verificationResult);
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 13eb55665741..46ff71831905 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -46,6 +46,7 @@ import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SrvccState;
import android.telephony.CallAttributes;
import android.telephony.CallQuality;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.CellLocation;
import android.telephony.DataFailCause;
@@ -207,7 +208,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
// Connection state of default APN type data (i.e. internet) of phones
private int[] mDataConnectionState;
- private Bundle[] mCellLocation;
+ private CellIdentity[] mCellIdentity;
private int[] mDataConnectionNetworkType;
@@ -295,7 +296,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
int numPhones = getTelephonyManager().getPhoneCount();
for (int sub = 0; sub < numPhones; sub++) {
TelephonyRegistry.this.notifyCellLocationForSubscriber(sub,
- mCellLocation[sub]);
+ mCellIdentity[sub]);
}
break;
}
@@ -404,7 +405,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mSignalStrength = copyOf(mSignalStrength, mNumPhones);
mMessageWaiting = copyOf(mMessageWaiting, mNumPhones);
mCallForwarding = copyOf(mCallForwarding, mNumPhones);
- mCellLocation = copyOf(mCellLocation, mNumPhones);
+ mCellIdentity = copyOf(mCellIdentity, mNumPhones);
mSrvccState = copyOf(mSrvccState, mNumPhones);
mPreciseCallState = copyOf(mPreciseCallState, mNumPhones);
mForegroundCallState = copyOf(mForegroundCallState, mNumPhones);
@@ -439,31 +440,22 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mUserMobileDataState[i] = false;
mMessageWaiting[i] = false;
mCallForwarding[i] = false;
- mCellLocation[i] = new Bundle();
+ mCellIdentity[i] = null;
mCellInfo.add(i, null);
mImsReasonInfo.add(i, null);
mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
mCallQuality[i] = createCallQuality();
- mCallAttributes[i] = new CallAttributes(new PreciseCallState(),
+ mCallAttributes[i] = new CallAttributes(createPreciseCallState(),
TelephonyManager.NETWORK_TYPE_UNKNOWN, createCallQuality());
mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
- mPreciseCallState[i] = new PreciseCallState();
+ mPreciseCallState[i] = createPreciseCallState();
mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>());
}
-
- // Note that location can be null for non-phone builds like
- // like the generic one.
- CellLocation location = CellLocation.getEmpty();
- if (location != null) {
- for (int i = oldNumPhones; i < mNumPhones; i++) {
- location.fillInNotifierBundle(mCellLocation[i]);
- }
- }
}
private void cutListToSize(List list, int size) {
@@ -503,7 +495,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mSignalStrength = new SignalStrength[numPhones];
mMessageWaiting = new boolean[numPhones];
mCallForwarding = new boolean[numPhones];
- mCellLocation = new Bundle[numPhones];
+ mCellIdentity = new CellIdentity[numPhones];
mSrvccState = new int[numPhones];
mPreciseCallState = new PreciseCallState[numPhones];
mForegroundCallState = new int[numPhones];
@@ -532,31 +524,23 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mUserMobileDataState[i] = false;
mMessageWaiting[i] = false;
mCallForwarding[i] = false;
- mCellLocation[i] = new Bundle();
+ mCellIdentity[i] = null;
mCellInfo.add(i, null);
mImsReasonInfo.add(i, null);
mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
mCallQuality[i] = createCallQuality();
- mCallAttributes[i] = new CallAttributes(new PreciseCallState(),
+ mCallAttributes[i] = new CallAttributes(createPreciseCallState(),
TelephonyManager.NETWORK_TYPE_UNKNOWN, createCallQuality());
mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
- mPreciseCallState[i] = new PreciseCallState();
+ mPreciseCallState[i] = createPreciseCallState();
mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>());
}
- // Note that location can be null for non-phone builds like
- // like the generic one.
- if (location != null) {
- for (int i = 0; i < numPhones; i++) {
- location.fillInNotifierBundle(mCellLocation[i]);
- }
- }
-
mAppOps = mContext.getSystemService(AppOpsManager.class);
}
@@ -837,11 +821,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
try {
- if (DBG_LOC) log("listen: mCellLocation = "
- + mCellLocation[phoneId]);
+ if (DBG_LOC) log("listen: mCellIdentity = " + mCellIdentity[phoneId]);
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
- r.callback.onCellLocationChanged(
- new Bundle(mCellLocation[phoneId]));
+ // null will be translated to empty CellLocation object in client.
+ r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
}
} catch (RemoteException ex) {
remove(r.binder);
@@ -1629,11 +1612,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
broadcastDataConnectionFailed(apnType, subId);
}
- public void notifyCellLocation(Bundle cellLocation) {
- notifyCellLocationForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cellLocation);
+ @Override
+ public void notifyCellLocation(CellIdentity cellLocation) {
+ notifyCellLocationForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, cellLocation);
}
- public void notifyCellLocationForSubscriber(int subId, Bundle cellLocation) {
+ @Override
+ public void notifyCellLocationForSubscriber(int subId, CellIdentity cellLocation) {
log("notifyCellLocationForSubscriber: subId=" + subId
+ " cellLocation=" + cellLocation);
if (!checkNotifyPermission("notifyCellLocation()")) {
@@ -1646,7 +1631,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
int phoneId = getPhoneIdFromSubId(subId);
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
- mCellLocation[phoneId] = cellLocation;
+ mCellIdentity[phoneId] = cellLocation;
for (Record r : mRecords) {
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&
idMatch(r.subId, subId, phoneId) &&
@@ -1656,7 +1641,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
log("notifyCellLocation: cellLocation=" + cellLocation
+ " r=" + r);
}
- r.callback.onCellLocationChanged(new Bundle(cellLocation));
+ r.callback.onCellLocationChanged(cellLocation);
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -2093,7 +2078,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
pw.println("mCallForwarding=" + mCallForwarding[i]);
pw.println("mDataActivity=" + mDataActivity[i]);
pw.println("mDataConnectionState=" + mDataConnectionState[i]);
- pw.println("mCellLocation=" + mCellLocation[i]);
+ pw.println("mCellIdentity=" + mCellIdentity[i]);
pw.println("mCellInfo=" + mCellInfo.get(i));
pw.println("mImsCallDisconnectCause=" + mImsReasonInfo.get(i));
pw.println("mSrvccState=" + mSrvccState[i]);
@@ -2583,10 +2568,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
try {
- if (DBG_LOC) log("checkPossibleMissNotify: onCellLocationChanged mCellLocation = "
- + mCellLocation[phoneId]);
+ if (DBG_LOC) {
+ log("checkPossibleMissNotify: onCellLocationChanged mCellIdentity = "
+ + mCellIdentity[phoneId]);
+ }
if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
- r.callback.onCellLocationChanged(new Bundle(mCellLocation[phoneId]));
+ // null will be translated to empty CellLocation object in client.
+ r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
}
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
@@ -2678,6 +2666,15 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
+ /** Returns a new PreciseCallState object with default values. */
+ private static PreciseCallState createPreciseCallState() {
+ return new PreciseCallState(PreciseCallState.PRECISE_CALL_STATE_NOT_VALID,
+ PreciseCallState.PRECISE_CALL_STATE_NOT_VALID,
+ PreciseCallState.PRECISE_CALL_STATE_NOT_VALID,
+ DisconnectCause.NOT_VALID,
+ PreciseDisconnectCause.NOT_VALID);
+ }
+
/** Returns a new CallQuality object with default values. */
private static CallQuality createCallQuality() {
return new CallQuality(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6dc49b7ba375..d7a46fec7767 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7558,6 +7558,26 @@ public class ActivityManagerService extends IActivityManager.Stub
});
}
+ @Override
+ public void appNotResponding(final String reason) {
+ final int callingPid = Binder.getCallingPid();
+
+ synchronized (mPidsSelfLocked) {
+ final ProcessRecord app = mPidsSelfLocked.get(callingPid);
+ if (app == null) {
+ throw new SecurityException("Unknown process: " + callingPid);
+ }
+
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ app.appNotResponding(
+ null, app.info, null, null, false, "App requested: " + reason);
+ }
+ });
+ }
+ }
+
public final void installSystemProviders() {
List<ProviderInfo> providers;
synchronized (this) {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 0b74840d850b..9f23cdaf3b86 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -2335,7 +2335,7 @@ public class AppOpsService extends IAppOpsService.Stub {
} else {
final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
final int mode = switchOp.evalMode();
- if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
+ if (mode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Slog.d(TAG, "noteOperation: reject #" + mode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
+ packageName);
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 21c478417d87..00fc6d06245c 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -355,8 +355,15 @@ public class AudioDeviceInventory {
mConnectedDevices.replace(key, di);
}
}
- if (AudioSystem.handleDeviceConfigChange(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address,
- BtHelper.getName(btDevice), a2dpCodec) != AudioSystem.AUDIO_STATUS_OK) {
+ final int res = AudioSystem.handleDeviceConfigChange(
+ AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address,
+ BtHelper.getName(btDevice), a2dpCodec);
+
+ if (res != AudioSystem.AUDIO_STATUS_OK) {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "APM handleDeviceConfigChange failed for A2DP device addr="
+ + address + " codec=" + a2dpCodec).printLog(TAG));
+
int musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC);
// force A2DP device disconnection in case of error so that AudioService state is
// consistent with audio policy manager state
@@ -364,6 +371,10 @@ public class AudioDeviceInventory {
btDevice, BluetoothA2dp.STATE_DISCONNECTED, BluetoothProfile.A2DP,
false /* suppressNoisyIntent */, musicDevice,
-1 /* a2dpVolume */);
+ } else {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "APM handleDeviceConfigChange success for A2DP device addr="
+ + address + " codec=" + a2dpCodec).printLog(TAG));
}
}
}
@@ -702,8 +713,20 @@ public class AudioDeviceInventory {
mDeviceBroker.setBluetoothA2dpOnInt(true, eventSource);
// at this point there could be another A2DP device already connected in APM, but it
// doesn't matter as this new one will overwrite the previous one
- AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+ final int res = AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
AudioSystem.DEVICE_STATE_AVAILABLE, address, name, a2dpCodec);
+
+ if (res != AudioSystem.AUDIO_STATUS_OK) {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "APM failed to make available A2DP device addr=" + address
+ + " error=" + res).printLog(TAG));
+ // TODO: connection failed, stop here
+ // TODO: return;
+ } else {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "A2DP device addr=" + address + " now available").printLog(TAG));
+ }
+
// Reset A2DP suspend state each time a new sink is connected
AudioSystem.setParameters("A2dpSuspended=false");
@@ -738,8 +761,19 @@ public class AudioDeviceInventory {
// device to remove was visible by APM, update APM
mDeviceBroker.setAvrcpAbsoluteVolumeSupported(false);
- AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
+ final int res = AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
AudioSystem.DEVICE_STATE_UNAVAILABLE, address, "", a2dpCodec);
+
+ if (res != AudioSystem.AUDIO_STATUS_OK) {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(
+ "APM failed to make unavailable A2DP device addr=" + address
+ + " error=" + res).printLog(TAG));
+ // TODO: failed to disconnect, stop here
+ // TODO: return;
+ } else {
+ AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
+ "A2DP device addr=" + address + " made unavailable")).printLog(TAG));
+ }
mApmConnectedDevices.remove(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
// Remove A2DP routes as well
setCurrentAudioRouteNameIfPossible(null);
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 7ce63c5f89b2..d57ce5390a96 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -138,18 +138,13 @@ abstract class DisplayDevice {
}
/**
- * Sets the refresh ranges, and display modes that the system is allowed to switch between.
- * Display modes are roughly ordered by preference.
+ * Sets the display mode specs.
*
* Not all display devices will automatically switch between modes, so it's important that the
- * most-desired modes are at the beginning of the allowed array.
- *
- * @param defaultModeId is used, if the device does not support multiple refresh
- * rates, and to navigate other parameters.
+ * default modeId is set correctly.
*/
- public void setDesiredDisplayConfigSpecs(int defaultModeId, float minRefreshRate,
- float maxRefreshRate, int[] modes) {
- }
+ public void setDesiredDisplayModeSpecsLocked(
+ DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) {}
/**
* Sets the requested color mode.
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index d20191dd1f85..ea031318be89 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -431,7 +431,8 @@ public final class DisplayManagerService extends SystemService {
recordTopInsetLocked(mLogicalDisplays.get(Display.DEFAULT_DISPLAY));
}
- mDisplayModeDirector.setDisplayModeListener(new AllowedDisplayModeObserver());
+ mDisplayModeDirector.setDesiredDisplayModeSpecsListener(
+ new DesiredDisplayModeSpecsObserver());
mDisplayModeDirector.start(mSensorManager);
mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS);
@@ -1327,19 +1328,24 @@ public final class DisplayManagerService extends SystemService {
return SurfaceControl.getDisplayedContentSample(token, maxFrames, timestamp);
}
- private void onAllowedDisplayModesChangedInternal() {
+ private void onDesiredDisplayModeSpecsChangedInternal() {
boolean changed = false;
synchronized (mSyncRoot) {
final int count = mLogicalDisplays.size();
for (int i = 0; i < count; i++) {
LogicalDisplay display = mLogicalDisplays.valueAt(i);
int displayId = mLogicalDisplays.keyAt(i);
- int[] allowedModes = mDisplayModeDirector.getAllowedModes(displayId);
- // Note that order is important here since not all display devices are capable of
- // automatically switching, so we do actually want to check for equality and not
- // just equivalent contents (regardless of order).
- if (!Arrays.equals(allowedModes, display.getAllowedDisplayModesLocked())) {
- display.setAllowedDisplayModesLocked(allowedModes);
+ DisplayModeDirector.DesiredDisplayModeSpecs desiredDisplayModeSpecs =
+ mDisplayModeDirector.getDesiredDisplayModeSpecs(displayId);
+ DisplayModeDirector.DesiredDisplayModeSpecs existingDesiredDisplayModeSpecs =
+ display.getDesiredDisplayModeSpecsLocked();
+ if (DEBUG) {
+ Slog.i(TAG,
+ "Comparing display specs: " + desiredDisplayModeSpecs
+ + ", existing: " + existingDesiredDisplayModeSpecs);
+ }
+ if (!desiredDisplayModeSpecs.equals(existingDesiredDisplayModeSpecs)) {
+ display.setDesiredDisplayModeSpecsLocked(desiredDisplayModeSpecs);
changed = true;
}
}
@@ -2488,9 +2494,10 @@ public final class DisplayManagerService extends SystemService {
}
- class AllowedDisplayModeObserver implements DisplayModeDirector.DisplayModeListener {
- public void onAllowedDisplayModesChanged() {
- onAllowedDisplayModesChangedInternal();
+ class DesiredDisplayModeSpecsObserver
+ implements DisplayModeDirector.DesiredDisplayModeSpecsListener {
+ public void onDesiredDisplayModeSpecsChanged() {
+ onDesiredDisplayModeSpecsChangedInternal();
}
}
}
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 2df682fa708c..ad728c18dd59 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -63,7 +63,7 @@ public class DisplayModeDirector {
private static final String TAG = "DisplayModeDirector";
private static final boolean DEBUG = false;
- private static final int MSG_ALLOWED_MODES_CHANGED = 1;
+ private static final int MSG_REFRESH_RATE_RANGE_CHANGED = 1;
private static final int MSG_BRIGHTNESS_THRESHOLDS_CHANGED = 2;
private static final int MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED = 3;
private static final int MSG_REFRESH_RATE_IN_ZONE_CHANGED = 4;
@@ -95,7 +95,7 @@ public class DisplayModeDirector {
private final BrightnessObserver mBrightnessObserver;
private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
- private DisplayModeListener mDisplayModeListener;
+ private DesiredDisplayModeSpecsListener mDesiredDisplayModeSpecsListener;
public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler) {
mContext = context;
@@ -125,23 +125,11 @@ public class DisplayModeDirector {
synchronized (mLock) {
// We may have a listener already registered before the call to start, so go ahead and
// notify them to pick up our newly initialized state.
- notifyAllowedModesChangedLocked();
+ notifyDesiredDisplayModeSpecsChangedLocked();
}
}
- /**
- * Calculates the modes the system is allowed to freely switch between based on global and
- * display-specific constraints.
- *
- * @param displayId The display to query for.
- * @return The IDs of the modes the system is allowed to freely switch between.
- */
- @NonNull
- public int[] getAllowedModes(int displayId) {
- return getDesiredDisplayConfigSpecs(displayId).allowedConfigs;
- }
-
@NonNull
private SparseArray<Vote> getVotesLocked(int displayId) {
SparseArray<Vote> displayVotes = mVotesByDisplay.get(displayId);
@@ -173,16 +161,16 @@ public class DisplayModeDirector {
* system is allowed to switch between.
*/
@NonNull
- public DesiredDisplayConfigSpecs getDesiredDisplayConfigSpecs(int displayId) {
+ public DesiredDisplayModeSpecs getDesiredDisplayModeSpecs(int displayId) {
synchronized (mLock) {
SparseArray<Vote> votes = getVotesLocked(displayId);
Display.Mode[] modes = mSupportedModesByDisplay.get(displayId);
Display.Mode defaultMode = mDefaultModeByDisplay.get(displayId);
if (modes == null || defaultMode == null) {
- Slog.e(TAG, "Asked about unknown display, returning empty desired configs!"
- + "(id=" + displayId + ")");
- return new DesiredDisplayConfigSpecs(displayId, new RefreshRateRange(60, 60),
- new int[0]);
+ Slog.e(TAG,
+ "Asked about unknown display, returning empty display mode specs!"
+ + "(id=" + displayId + ")");
+ return new DesiredDisplayModeSpecs();
}
int[] availableModes = new int[]{defaultMode.getModeId()};
@@ -255,9 +243,9 @@ public class DisplayModeDirector {
}
// filterModes function is going to filter the modes based on the voting system. If
// the application requests a given mode with preferredModeId function, it will be
- // stored as the first and only element in available modes array.
- return new DesiredDisplayConfigSpecs(defaultModeId,
- new RefreshRateRange(minRefreshRate, maxRefreshRate), availableModes);
+ // stored as defaultModeId.
+ return new DesiredDisplayModeSpecs(
+ defaultModeId, new RefreshRateRange(minRefreshRate, maxRefreshRate));
}
}
@@ -311,11 +299,13 @@ public class DisplayModeDirector {
}
/**
- * Sets the modeListener for changes to allowed display modes.
+ * Sets the desiredDisplayModeSpecsListener for changes to display mode and refresh rate
+ * ranges.
*/
- public void setDisplayModeListener(@Nullable DisplayModeListener displayModeListener) {
+ public void setDesiredDisplayModeSpecsListener(
+ @Nullable DesiredDisplayModeSpecsListener desiredDisplayModeSpecsListener) {
synchronized (mLock) {
- mDisplayModeListener = displayModeListener;
+ mDesiredDisplayModeSpecsListener = desiredDisplayModeSpecsListener;
}
}
@@ -389,16 +379,18 @@ public class DisplayModeDirector {
mVotesByDisplay.remove(displayId);
}
- notifyAllowedModesChangedLocked();
+ notifyDesiredDisplayModeSpecsChangedLocked();
}
- private void notifyAllowedModesChangedLocked() {
- if (mDisplayModeListener != null && !mHandler.hasMessages(MSG_ALLOWED_MODES_CHANGED)) {
+ private void notifyDesiredDisplayModeSpecsChangedLocked() {
+ if (mDesiredDisplayModeSpecsListener != null
+ && !mHandler.hasMessages(MSG_REFRESH_RATE_RANGE_CHANGED)) {
// We need to post this to a handler to avoid calling out while holding the lock
// since we know there are things that both listen for changes as well as provide
- // information. If we did call out while holding the lock, then there's no guaranteed
- // lock order and we run the real of risk deadlock.
- Message msg = mHandler.obtainMessage(MSG_ALLOWED_MODES_CHANGED, mDisplayModeListener);
+ // information. If we did call out while holding the lock, then there's no
+ // guaranteed lock order and we run the real of risk deadlock.
+ Message msg = mHandler.obtainMessage(
+ MSG_REFRESH_RATE_RANGE_CHANGED, mDesiredDisplayModeSpecsListener);
msg.sendToTarget();
}
}
@@ -430,13 +422,13 @@ public class DisplayModeDirector {
}
/**
- * Listens for changes to display mode coordination.
+ * Listens for changes refresh rate coordination.
*/
- public interface DisplayModeListener {
+ public interface DesiredDisplayModeSpecsListener {
/**
- * Called when the allowed display modes may have changed.
+ * Called when the refresh rate range may have changed.
*/
- void onAllowedDisplayModesChanged();
+ void onDesiredDisplayModeSpecsChanged();
}
private final class DisplayModeDirectorHandler extends Handler {
@@ -447,11 +439,6 @@ public class DisplayModeDirector {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
- case MSG_ALLOWED_MODES_CHANGED:
- DisplayModeListener displayModeListener = (DisplayModeListener) msg.obj;
- displayModeListener.onAllowedDisplayModesChanged();
- break;
-
case MSG_BRIGHTNESS_THRESHOLDS_CHANGED:
Pair<int[], int[]> thresholds = (Pair<int[], int[]>) msg.obj;
@@ -474,6 +461,12 @@ public class DisplayModeDirector {
mBrightnessObserver.onDeviceConfigRefreshRateInZoneChanged(
refreshRateInZone);
break;
+
+ case MSG_REFRESH_RATE_RANGE_CHANGED:
+ DesiredDisplayModeSpecsListener desiredDisplayModeSpecsListener =
+ (DesiredDisplayModeSpecsListener) msg.obj;
+ desiredDisplayModeSpecsListener.onDesiredDisplayModeSpecsChanged();
+ break;
}
}
}
@@ -485,11 +478,13 @@ public class DisplayModeDirector {
/**
* The lowest desired refresh rate.
*/
- public final float min;
+ public float min;
/**
* The highest desired refresh rate.
*/
- public final float max;
+ public float max;
+
+ public RefreshRateRange() {}
public RefreshRateRange(float min, float max) {
if (min < 0 || max < 0 || min > max) {
@@ -531,32 +526,32 @@ public class DisplayModeDirector {
}
/**
- * Information about the desired configuration to be set by the system. Includes the default
- * configuration ID, refresh rate range, and the list of policy decisions that influenced the
- * choice.
+ * Information about the desired display mode to be set by the system. Includes the default
+ * mode ID and refresh rate range.
+ *
+ * We have this class in addition to SurfaceControl.DesiredDisplayConfigSpecs to make clear the
+ * distinction between the config ID / physical index that
+ * SurfaceControl.DesiredDisplayConfigSpecs uses, and the mode ID used here.
*/
- public static final class DesiredDisplayConfigSpecs {
+ public static final class DesiredDisplayModeSpecs {
/**
- * Default configuration ID. This is what system defaults to for all other settings, or
+ * Default mode ID. This is what system defaults to for all other settings, or
* if the refresh rate range is not available.
*/
- public final int defaultModeId;
+ public int defaultModeId;
/**
* The refresh rate range.
*/
public final RefreshRateRange refreshRateRange;
- /**
- * For legacy reasons, keep a list of allowed configs.
- * TODO(b/142507213): Re-assess whether the list of allowed configs is still necessary.
- */
- public final int[] allowedConfigs;
- public DesiredDisplayConfigSpecs(int defaultModeId,
- @NonNull RefreshRateRange refreshRateRange,
- @NonNull int[] allowedConfigs) {
+ public DesiredDisplayModeSpecs() {
+ refreshRateRange = new RefreshRateRange();
+ }
+
+ public DesiredDisplayModeSpecs(
+ int defaultModeId, @NonNull RefreshRateRange refreshRateRange) {
this.defaultModeId = defaultModeId;
this.refreshRateRange = refreshRateRange;
- this.allowedConfigs = allowedConfigs;
}
/**
@@ -564,9 +559,8 @@ public class DisplayModeDirector {
*/
@Override
public String toString() {
- return "DesiredDisplayConfigSpecs(defaultModeId=" + defaultModeId
- + ", refreshRateRange=" + refreshRateRange.toString()
- + ", allowedConfigs=" + Arrays.toString(allowedConfigs) + ")";
+ return String.format("defaultModeId=%d min=%.0f max=%.0f", defaultModeId,
+ refreshRateRange.min, refreshRateRange.max);
}
/**
* Checks whether the two objects have the same values.
@@ -577,17 +571,16 @@ public class DisplayModeDirector {
return true;
}
- if (!(other instanceof DesiredDisplayConfigSpecs)) {
+ if (!(other instanceof DesiredDisplayModeSpecs)) {
return false;
}
- DesiredDisplayConfigSpecs desiredDisplayConfigSpecs =
- (DesiredDisplayConfigSpecs) other;
+ DesiredDisplayModeSpecs desiredDisplayModeSpecs = (DesiredDisplayModeSpecs) other;
- if (defaultModeId != desiredDisplayConfigSpecs.defaultModeId) {
+ if (defaultModeId != desiredDisplayModeSpecs.defaultModeId) {
return false;
}
- if (!refreshRateRange.equals(desiredDisplayConfigSpecs.refreshRateRange)) {
+ if (!refreshRateRange.equals(desiredDisplayModeSpecs.refreshRateRange)) {
return false;
}
return true;
@@ -597,6 +590,15 @@ public class DisplayModeDirector {
public int hashCode() {
return Objects.hash(defaultModeId, refreshRateRange);
}
+
+ /**
+ * Copy values from the other object.
+ */
+ public void copyFrom(DesiredDisplayModeSpecs other) {
+ defaultModeId = other.defaultModeId;
+ refreshRateRange.min = other.refreshRateRange.min;
+ refreshRateRange.max = other.refreshRateRange.max;
+ }
}
@VisibleForTesting
@@ -932,7 +934,7 @@ public class DisplayModeDirector {
mDefaultModeByDisplay.put(displayId, info.getDefaultMode());
}
if (changed) {
- notifyAllowedModesChangedLocked();
+ notifyDesiredDisplayModeSpecsChangedLocked();
}
}
}
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 308c755a0868..bf58efeb2b02 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -112,18 +112,19 @@ final class LocalDisplayAdapter extends DisplayAdapter {
activeColorMode = Display.COLOR_MODE_INVALID;
}
int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
- int[] allowedConfigs = SurfaceControl.getAllowedDisplayConfigs(displayToken);
+ SurfaceControl.DesiredDisplayConfigSpecs desiredDisplayConfigSpecs =
+ SurfaceControl.getDesiredDisplayConfigSpecs(displayToken);
LocalDisplayDevice device = mDevices.get(physicalDisplayId);
if (device == null) {
// Display was added.
final boolean isInternal = mDevices.size() == 0;
- device = new LocalDisplayDevice(displayToken, physicalDisplayId,
- configs, activeConfig, allowedConfigs, colorModes, activeColorMode,
+ device = new LocalDisplayDevice(displayToken, physicalDisplayId, configs,
+ activeConfig, desiredDisplayConfigSpecs, colorModes, activeColorMode,
isInternal);
mDevices.put(physicalDisplayId, device);
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
} else if (device.updatePhysicalDisplayInfoLocked(configs, activeConfig,
- allowedConfigs, colorModes, activeColorMode)) {
+ desiredDisplayConfigSpecs, colorModes, activeColorMode)) {
// Display properties changed.
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
}
@@ -172,12 +173,10 @@ final class LocalDisplayAdapter extends DisplayAdapter {
private int mDefaultModeId;
private int mActiveModeId;
private boolean mActiveModeInvalid;
- private int[] mAllowedModeIds;
- private float mMinRefreshRate;
- private float mMaxRefreshRate;
- private boolean mAllowedModeIdsInvalid;
+ private DisplayModeDirector.DesiredDisplayModeSpecs mDisplayModeSpecs =
+ new DisplayModeDirector.DesiredDisplayModeSpecs();
+ private boolean mDisplayModeSpecsInvalid;
private int mActivePhysIndex;
- private int[] mAllowedPhysIndexes;
private int mActiveColorMode;
private boolean mActiveColorModeInvalid;
private Display.HdrCapabilities mHdrCapabilities;
@@ -188,13 +187,13 @@ final class LocalDisplayAdapter extends DisplayAdapter {
LocalDisplayDevice(IBinder displayToken, long physicalDisplayId,
SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
- int[] allowedDisplayInfos, int[] colorModes, int activeColorMode,
- boolean isInternal) {
+ SurfaceControl.DesiredDisplayConfigSpecs physicalDisplayConfigSpecs,
+ int[] colorModes, int activeColorMode, boolean isInternal) {
super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + physicalDisplayId);
mPhysicalDisplayId = physicalDisplayId;
mIsInternal = isInternal;
updatePhysicalDisplayInfoLocked(physicalDisplayInfos, activeDisplayInfo,
- allowedDisplayInfos, colorModes, activeColorMode);
+ physicalDisplayConfigSpecs, colorModes, activeColorMode);
updateColorModesLocked(colorModes, activeColorMode);
mSidekickInternal = LocalServices.getService(SidekickInternal.class);
if (mIsInternal) {
@@ -213,10 +212,10 @@ final class LocalDisplayAdapter extends DisplayAdapter {
public boolean updatePhysicalDisplayInfoLocked(
SurfaceControl.PhysicalDisplayInfo[] physicalDisplayInfos, int activeDisplayInfo,
- int[] allowedDisplayInfos, int[] colorModes, int activeColorMode) {
+ SurfaceControl.DesiredDisplayConfigSpecs physicalDisplayConfigSpecs,
+ int[] colorModes, int activeColorMode) {
mDisplayInfos = Arrays.copyOf(physicalDisplayInfos, physicalDisplayInfos.length);
mActivePhysIndex = activeDisplayInfo;
- mAllowedPhysIndexes = Arrays.copyOf(allowedDisplayInfos, allowedDisplayInfos.length);
// Build an updated list of all existing modes.
ArrayList<DisplayModeRecord> records = new ArrayList<DisplayModeRecord>();
boolean modesAdded = false;
@@ -264,6 +263,26 @@ final class LocalDisplayAdapter extends DisplayAdapter {
sendTraversalRequestLocked();
}
+ // Check whether surface flinger spontaneously changed display config specs out from
+ // under us. If so, schedule a traversal to reapply our display config specs.
+ if (mDisplayModeSpecs.defaultModeId != 0) {
+ int activeDefaultMode =
+ findMatchingModeIdLocked(physicalDisplayConfigSpecs.defaultConfig);
+ // If we can't map the defaultConfig index to a mode, then the physical display
+ // configs must have changed, and the code below for handling changes to the
+ // list of available modes will take care of updating display config specs.
+ if (activeDefaultMode != 0) {
+ if (mDisplayModeSpecs.defaultModeId != activeDefaultMode
+ || mDisplayModeSpecs.refreshRateRange.min
+ != physicalDisplayConfigSpecs.minRefreshRate
+ || mDisplayModeSpecs.refreshRateRange.max
+ != physicalDisplayConfigSpecs.maxRefreshRate) {
+ mDisplayModeSpecsInvalid = true;
+ sendTraversalRequestLocked();
+ }
+ }
+ }
+
boolean recordsChanged = records.size() != mSupportedModes.size() || modesAdded;
// If the records haven't changed then we're done here.
if (!recordsChanged) {
@@ -286,6 +305,17 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mDefaultModeId = activeRecord.mMode.getModeId();
}
+ // Determine whether the display mode specs' default mode is still there.
+ if (mSupportedModes.indexOfKey(mDisplayModeSpecs.defaultModeId) < 0) {
+ if (mDisplayModeSpecs.defaultModeId != 0) {
+ Slog.w(TAG,
+ "DisplayModeSpecs default mode no longer available, using currently"
+ + " active mode as default.");
+ }
+ mDisplayModeSpecs.defaultModeId = activeRecord.mMode.getModeId();
+ mDisplayModeSpecsInvalid = true;
+ }
+
// Determine whether the active mode is still there.
if (mSupportedModes.indexOfKey(mActiveModeId) < 0) {
if (mActiveModeId != 0) {
@@ -296,21 +326,6 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mActiveModeInvalid = true;
}
- // Determine what the currently allowed modes are
- mAllowedModeIds = new int[] { mActiveModeId };
- int[] allowedModeIds = new int[mAllowedPhysIndexes.length];
- int size = 0;
- for (int physIndex : mAllowedPhysIndexes) {
- int modeId = findMatchingModeIdLocked(physIndex);
- if (modeId > 0) {
- allowedModeIds[size++] = modeId;
- }
- }
-
- // If this is different from our desired allowed modes, then mark our current set as
- // invalid so we correct this on the next traversal.
- mAllowedModeIdsInvalid = !Arrays.equals(allowedModeIds, mAllowedModeIds);
-
// Schedule traversals so that we apply pending changes.
sendTraversalRequestLocked();
return true;
@@ -624,10 +639,40 @@ final class LocalDisplayAdapter extends DisplayAdapter {
}
@Override
- public void setDesiredDisplayConfigSpecs(int defaultModeId, float minRefreshRate,
- float maxRefreshRate, int[] modes) {
- updateDesiredDisplayConfigSpecs(defaultModeId, minRefreshRate, maxRefreshRate);
- updateAllowedModesLocked(modes);
+ public void setDesiredDisplayModeSpecsLocked(
+ DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) {
+ if (displayModeSpecs.defaultModeId == 0) {
+ // Bail if the caller is requesting a null mode. We'll get called again shortly with
+ // a valid mode.
+ return;
+ }
+ int defaultPhysIndex = findDisplayInfoIndexLocked(displayModeSpecs.defaultModeId);
+ if (defaultPhysIndex < 0) {
+ // When a display is hotplugged, it's possible for a mode to be removed that was
+ // previously valid. Because of the way display changes are propagated through the
+ // framework, and the caching of the display mode specs in LogicalDisplay, it's
+ // possible we'll get called with a stale mode id that no longer represents a valid
+ // mode. This should only happen in extremely rare cases. A followup call will
+ // contain a valid mode id.
+ Slog.w(TAG,
+ "Ignoring request for invalid default mode id "
+ + displayModeSpecs.defaultModeId);
+ updateDeviceInfoLocked();
+ return;
+ }
+ if (mDisplayModeSpecsInvalid || !displayModeSpecs.equals(mDisplayModeSpecs)) {
+ mDisplayModeSpecsInvalid = false;
+ mDisplayModeSpecs.copyFrom(displayModeSpecs);
+ final IBinder token = getDisplayTokenLocked();
+ SurfaceControl.setDesiredDisplayConfigSpecs(token,
+ new SurfaceControl.DesiredDisplayConfigSpecs(defaultPhysIndex,
+ mDisplayModeSpecs.refreshRateRange.min,
+ mDisplayModeSpecs.refreshRateRange.max));
+ int activePhysIndex = SurfaceControl.getActiveConfig(token);
+ if (updateActiveModeLocked(activePhysIndex)) {
+ updateDeviceInfoLocked();
+ }
+ }
}
@Override
@@ -650,107 +695,11 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mActiveModeInvalid = mActiveModeId == 0;
if (mActiveModeInvalid) {
Slog.w(TAG, "In unknown mode after setting allowed configs"
- + ": allowedPhysIndexes=" + mAllowedPhysIndexes
+ ", activePhysIndex=" + mActivePhysIndex);
}
return true;
}
- // TODO(b/142507213): Remove once refresh rates are plummed through to kernel.
- public void updateAllowedModesLocked(int[] allowedModes) {
- if (Arrays.equals(allowedModes, mAllowedModeIds) && !mAllowedModeIdsInvalid) {
- return;
- }
- if (updateAllowedModesInternalLocked(allowedModes)) {
- updateDeviceInfoLocked();
- }
- }
-
- public void updateDesiredDisplayConfigSpecs(int defaultModeId, float minRefreshRate,
- float maxRefreshRate) {
- if (minRefreshRate == mMinRefreshRate
- && maxRefreshRate == mMaxRefreshRate
- && defaultModeId == mDefaultModeId) {
- return;
- }
- if (updateDesiredDisplayConfigSpecsInternalLocked(defaultModeId, minRefreshRate,
- maxRefreshRate)) {
- updateDeviceInfoLocked();
- }
- }
-
- public boolean updateDesiredDisplayConfigSpecsInternalLocked(int defaultModeId,
- float minRefreshRate, float maxRefreshRate) {
- if (DEBUG) {
- Slog.w(TAG, "updateDesiredDisplayConfigSpecsInternalLocked("
- + "defaultModeId="
- + Integer.toString(defaultModeId)
- + ", minRefreshRate="
- + Float.toString(minRefreshRate)
- + ", maxRefreshRate="
- + Float.toString(minRefreshRate));
- }
-
- final IBinder token = getDisplayTokenLocked();
- SurfaceControl.setDesiredDisplayConfigSpecs(token,
- new SurfaceControl.DesiredDisplayConfigSpecs(
- defaultModeId, minRefreshRate, maxRefreshRate));
- int activePhysIndex = SurfaceControl.getActiveConfig(token);
- return updateActiveModeLocked(activePhysIndex);
- }
-
- public boolean updateAllowedModesInternalLocked(int[] allowedModes) {
- if (DEBUG) {
- Slog.w(TAG, "updateAllowedModesInternalLocked(allowedModes="
- + Arrays.toString(allowedModes) + ")");
- }
- int[] allowedPhysIndexes = new int[allowedModes.length];
- int size = 0;
- for (int modeId : allowedModes) {
- int physIndex = findDisplayInfoIndexLocked(modeId);
- if (physIndex < 0) {
- Slog.w(TAG, "Requested mode ID " + modeId + " not available,"
- + " dropping from allowed set.");
- } else {
- allowedPhysIndexes[size++] = physIndex;
- }
- }
-
- // If we couldn't find one or more of the suggested allowed modes then we need to
- // shrink the array to its actual size.
- if (size != allowedModes.length) {
- allowedPhysIndexes = Arrays.copyOf(allowedPhysIndexes, size);
- }
-
- // If we found no suitable modes, then we try again with the default mode which we
- // assume has a suitable physical config.
- if (size == 0) {
- if (DEBUG) {
- Slog.w(TAG, "No valid modes allowed, falling back to default mode (id="
- + mDefaultModeId + ")");
- }
- allowedModes = new int[] { mDefaultModeId };
- allowedPhysIndexes = new int[] { findDisplayInfoIndexLocked(mDefaultModeId) };
- }
-
- mAllowedModeIds = allowedModes;
- mAllowedModeIdsInvalid = false;
-
- if (Arrays.equals(mAllowedPhysIndexes, allowedPhysIndexes)) {
- return false;
- }
- mAllowedPhysIndexes = allowedPhysIndexes;
-
- if (DEBUG) {
- Slog.w(TAG, "Setting allowed physical configs: allowedPhysIndexes="
- + Arrays.toString(allowedPhysIndexes));
- }
-
- SurfaceControl.setAllowedDisplayConfigs(getDisplayTokenLocked(), allowedPhysIndexes);
- int activePhysIndex = SurfaceControl.getActiveConfig(getDisplayTokenLocked());
- return updateActiveModeLocked(activePhysIndex);
- }
-
public boolean requestColorModeLocked(int colorMode) {
if (mActiveColorMode == colorMode) {
return false;
@@ -770,11 +719,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
public void dumpLocked(PrintWriter pw) {
super.dumpLocked(pw);
pw.println("mPhysicalDisplayId=" + mPhysicalDisplayId);
- pw.println("mAllowedPhysIndexes=" + Arrays.toString(mAllowedPhysIndexes));
- pw.println("mAllowedModeIds=" + Arrays.toString(mAllowedModeIds));
- pw.println("mMinRefreshRate=" + mMinRefreshRate);
- pw.println("mMaxRefreshRate=" + mMaxRefreshRate);
- pw.println("mAllowedModeIdsInvalid=" + mAllowedModeIdsInvalid);
+ pw.println("mDisplayModeSpecs={" + mDisplayModeSpecs + "}");
+ pw.println("mDisplayModeSpecsInvalid=" + mDisplayModeSpecsInvalid);
pw.println("mActivePhysIndex=" + mActivePhysIndex);
pw.println("mActiveModeId=" + mActiveModeId);
pw.println("mActiveColorMode=" + mActiveColorMode);
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index f4b2dc8cfc98..b649a50f9443 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -87,9 +87,11 @@ final class LogicalDisplay {
// True if the logical display has unique content.
private boolean mHasContent;
- private int[] mAllowedDisplayModes = new int[0];
private int mRequestedColorMode;
+ private DisplayModeDirector.DesiredDisplayModeSpecs mDesiredDisplayModeSpecs =
+ new DisplayModeDirector.DesiredDisplayModeSpecs();
+
// The display offsets to apply to the display projection.
private int mDisplayOffsetX;
private int mDisplayOffsetY;
@@ -352,12 +354,12 @@ final class LogicalDisplay {
// Set the color mode and allowed display mode.
if (device == mPrimaryDisplayDevice) {
- // See ag/9588196 for correct values.
- device.setDesiredDisplayConfigSpecs(0, 60, 60, mAllowedDisplayModes);
+ device.setDesiredDisplayModeSpecsLocked(mDesiredDisplayModeSpecs);
device.setRequestedColorModeLocked(mRequestedColorMode);
} else {
// Reset to default for non primary displays
- device.setDesiredDisplayConfigSpecs(0, 60, 60, new int[] {0});
+ device.setDesiredDisplayModeSpecsLocked(
+ new DisplayModeDirector.DesiredDisplayModeSpecs());
device.setRequestedColorModeLocked(0);
}
@@ -462,17 +464,18 @@ final class LogicalDisplay {
}
/**
- * Sets the display modes the system is free to switch between.
+ * Sets the display configs the system can use.
*/
- public void setAllowedDisplayModesLocked(int[] modes) {
- mAllowedDisplayModes = modes;
+ public void setDesiredDisplayModeSpecsLocked(
+ DisplayModeDirector.DesiredDisplayModeSpecs specs) {
+ mDesiredDisplayModeSpecs = specs;
}
/**
- * Returns the display modes the system is free to switch between.
+ * Returns the display configs the system can choose.
*/
- public int[] getAllowedDisplayModesLocked() {
- return mAllowedDisplayModes;
+ public DisplayModeDirector.DesiredDisplayModeSpecs getDesiredDisplayModeSpecsLocked() {
+ return mDesiredDisplayModeSpecs;
}
/**
@@ -531,7 +534,7 @@ final class LogicalDisplay {
pw.println("mDisplayId=" + mDisplayId);
pw.println("mLayerStack=" + mLayerStack);
pw.println("mHasContent=" + mHasContent);
- pw.println("mAllowedDisplayModes=" + Arrays.toString(mAllowedDisplayModes));
+ pw.println("mDesiredDisplayModeSpecs={" + mDesiredDisplayModeSpecs + "}");
pw.println("mRequestedColorMode=" + mRequestedColorMode);
pw.println("mDisplayOffset=(" + mDisplayOffsetX + ", " + mDisplayOffsetY + ")");
pw.println("mDisplayScalingDisabled=" + mDisplayScalingDisabled);
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 739dd64451e4..b6255d15795e 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -315,9 +315,9 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
}
@Override
- public void setDesiredDisplayConfigSpecs(int defaultModeId, float minRefreshRate,
- float maxRefreshRate, int[] modes) {
- final int id = defaultModeId;
+ public void setDesiredDisplayModeSpecsLocked(
+ DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) {
+ final int id = displayModeSpecs.defaultModeId;
int index = -1;
if (id == 0) {
// Use the default.
diff --git a/services/core/java/com/android/server/incremental/IncrementalManagerService.java b/services/core/java/com/android/server/incremental/IncrementalManagerService.java
index 3049522c2231..d673ec84c47e 100644
--- a/services/core/java/com/android/server/incremental/IncrementalManagerService.java
+++ b/services/core/java/com/android/server/incremental/IncrementalManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.incremental;
import android.annotation.NonNull;
+import android.content.ComponentName;
import android.content.Context;
import android.content.pm.DataLoaderManager;
import android.content.pm.DataLoaderParamsParcel;
@@ -85,7 +86,8 @@ public class IncrementalManagerService extends IIncrementalManager.Stub {
DataLoaderParamsParcel params,
IDataLoaderStatusListener listener) {
Bundle dataLoaderParams = new Bundle();
- dataLoaderParams.putCharSequence("packageName", params.packageName);
+ dataLoaderParams.putParcelable("componentName",
+ new ComponentName(params.packageName, params.className));
dataLoaderParams.putParcelable("control", control);
dataLoaderParams.putParcelable("params", params);
DataLoaderManager dataLoaderManager = mContext.getSystemService(DataLoaderManager.class);
@@ -109,8 +111,7 @@ public class IncrementalManagerService extends IIncrementalManager.Stub {
return false;
}
try {
- // TODO: fix file list
- dataLoader.start(null);
+ dataLoader.start();
return true;
} catch (RemoteException ex) {
return false;
diff --git a/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java b/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java
index 6a8434aad88b..5c18f5880146 100644
--- a/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java
+++ b/services/core/java/com/android/server/incremental/IncrementalManagerShellCommand.java
@@ -19,6 +19,7 @@ package com.android.server.incremental;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.ComponentName;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
@@ -54,6 +55,8 @@ public final class IncrementalManagerShellCommand extends ShellCommand {
private static final String TAG = "IncrementalShellCommand";
// Assuming the adb data loader is always installed on the device
private static final String LOADER_PACKAGE_NAME = "com.android.incremental.nativeadb";
+ private static final String LOADER_CLASS_NAME =
+ LOADER_PACKAGE_NAME + ".NativeAdbDataLoaderService";
private final @NonNull Context mContext;
private static final int ERROR_INVALID_ARGUMENTS = -1;
@@ -111,14 +114,15 @@ public final class IncrementalManagerShellCommand extends ShellCommand {
pw.println("File names and sizes don't match.");
return ERROR_DATA_LOADER_INIT;
}
- final DataLoaderParams params = new DataLoaderParams(
- "", LOADER_PACKAGE_NAME, dataLoaderDynamicArgs);
+ final DataLoaderParams params = DataLoaderParams.forIncremental(
+ new ComponentName(LOADER_PACKAGE_NAME, LOADER_CLASS_NAME), "",
+ dataLoaderDynamicArgs);
PackageInstaller.SessionParams sessionParams = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
sessionParams.installFlags |= PackageManager.INSTALL_ALL_USERS;
// Replace existing if same package is already installed
sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
- sessionParams.setIncrementalParams(params);
+ sessionParams.setDataLoaderParams(params);
try {
int sessionId = packageInstaller.createSession(sessionParams);
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index b77c85929dd6..bf73aa39c581 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -317,6 +317,7 @@ public class InputManagerService extends IInputManager.Stub
this.mContext = context;
this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());
+ mStaticAssociations = loadStaticInputPortAssociations();
mUseDevInputEventForAudioJack =
context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);
Slog.i(TAG, "Initializing input manager, mUseDevInputEventForAudioJack="
@@ -328,7 +329,6 @@ public class InputManagerService extends IInputManager.Stub
mDoubleTouchGestureEnableFile = TextUtils.isEmpty(doubleTouchGestureEnablePath) ? null :
new File(doubleTouchGestureEnablePath);
- mStaticAssociations = loadStaticInputPortAssociations();
LocalServices.addService(InputManagerInternal.class, new LocalService());
}
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerService.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerService.java
index 005fb696b089..3762ebb0b902 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerService.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerService.java
@@ -37,7 +37,7 @@ public class AppIntegrityManagerService extends SystemService {
@Override
public void onStart() {
- mService = new AppIntegrityManagerServiceImpl(mContext);
- // TODO: define and publish a binder service.
+ mService = AppIntegrityManagerServiceImpl.create(mContext);
+ publishBinderService(Context.APP_INTEGRITY_SERVICE, mService);
}
}
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index 39c1b8535565..6c80a884edb6 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -17,40 +17,113 @@
package com.android.server.integrity;
import static android.content.Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION;
+import static android.content.Intent.EXTRA_ORIGINATING_UID;
+import static android.content.Intent.EXTRA_PACKAGE_NAME;
+import static android.content.Intent.EXTRA_VERSION_CODE;
+import static android.content.integrity.AppIntegrityManager.EXTRA_STATUS;
+import static android.content.integrity.AppIntegrityManager.STATUS_FAILURE;
+import static android.content.integrity.AppIntegrityManager.STATUS_SUCCESS;
import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.integrity.AppInstallMetadata;
+import android.content.integrity.IAppIntegrityManager;
+import android.content.integrity.Rule;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.Signature;
+import android.net.Uri;
+import android.os.Binder;
+import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.RemoteException;
import android.util.Slog;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.LocalServices;
+import com.android.server.integrity.engine.RuleEvaluationEngine;
+import com.android.server.integrity.model.IntegrityCheckResult;
+import com.android.server.integrity.model.RuleMetadata;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
/** Implementation of {@link AppIntegrityManagerService}. */
-class AppIntegrityManagerServiceImpl {
+public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
private static final String TAG = "AppIntegrityManagerServiceImpl";
+ private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
+ private static final char[] HEX_CHARS = "0123456789ABCDEF".toCharArray();
+ private static final String PACKAGE_INSTALLER = "com.google.android.packageinstaller";
+ private static final String BASE_APK_FILE = "base.apk";
+ private static final String ALLOWED_INSTALLERS_METADATA_NAME = "allowed-installers";
+ private static final String ALLOWED_INSTALLER_DELIMITER = ",";
+ private static final String INSTALLER_PACKAGE_CERT_DELIMITER = "\\|";
+
+ private static final String ADB_INSTALLER = "adb";
+ private static final String UNKNOWN_INSTALLER = "";
+ private static final String INSTALLER_CERT_NOT_APPLICABLE = "";
+
+ // Access to files inside mRulesDir is protected by mRulesLock;
private final Context mContext;
private final Handler mHandler;
private final PackageManagerInternal mPackageManagerInternal;
+ private final RuleEvaluationEngine mEvaluationEngine;
+ private final IntegrityFileManager mIntegrityFileManager;
- AppIntegrityManagerServiceImpl(Context context) {
- mContext = context;
-
+ /** Create an instance of {@link AppIntegrityManagerServiceImpl}. */
+ public static AppIntegrityManagerServiceImpl create(Context context) {
HandlerThread handlerThread = new HandlerThread("AppIntegrityManagerServiceHandler");
handlerThread.start();
- mHandler = handlerThread.getThreadHandler();
- mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
+ return new AppIntegrityManagerServiceImpl(
+ context,
+ LocalServices.getService(PackageManagerInternal.class),
+ RuleEvaluationEngine.getRuleEvaluationEngine(),
+ IntegrityFileManager.getInstance(),
+ handlerThread.getThreadHandler());
+ }
+
+ @VisibleForTesting
+ AppIntegrityManagerServiceImpl(
+ Context context,
+ PackageManagerInternal packageManagerInternal,
+ RuleEvaluationEngine evaluationEngine,
+ IntegrityFileManager integrityFileManager,
+ Handler handler) {
+ mContext = context;
+ mPackageManagerInternal = packageManagerInternal;
+ mEvaluationEngine = evaluationEngine;
+ mIntegrityFileManager = integrityFileManager;
+ mHandler = handler;
IntentFilter integrityVerificationFilter = new IntentFilter();
integrityVerificationFilter.addAction(ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
+ try {
+ integrityVerificationFilter.addDataType(PACKAGE_MIME_TYPE);
+ } catch (IntentFilter.MalformedMimeTypeException e) {
+ throw new RuntimeException("Mime type malformed: should never happen.", e);
+ }
mContext.registerReceiver(
new BroadcastReceiver() {
@@ -68,13 +141,418 @@ class AppIntegrityManagerServiceImpl {
mHandler);
}
- // protected broadcasts cannot be sent in the test.
- @VisibleForTesting
- void handleIntegrityVerification(Intent intent) {
+ @Override
+ public void updateRuleSet(
+ String version, ParceledListSlice<Rule> rules, IntentSender statusReceiver)
+ throws RemoteException {
+ String ruleProvider = getCallerPackageNameOrThrow();
+
+ mHandler.post(
+ () -> {
+ boolean success = true;
+ try {
+ mIntegrityFileManager.writeRules(version, ruleProvider, rules.getList());
+ } catch (Exception e) {
+ Slog.e(TAG, "Error writing rules.", e);
+ success = false;
+ }
+
+ Intent intent = new Intent();
+ intent.putExtra(EXTRA_STATUS, success ? STATUS_SUCCESS : STATUS_FAILURE);
+ try {
+ statusReceiver.sendIntent(
+ mContext,
+ /* code= */ 0,
+ intent,
+ /* onFinished= */ null,
+ /* handler= */ null);
+ } catch (IntentSender.SendIntentException e) {
+ Slog.e(TAG, "Error sending status feedback.", e);
+ }
+ });
+ }
+
+ @Override
+ public String getCurrentRuleSetVersion() throws RemoteException {
+ getCallerPackageNameOrThrow();
+
+ RuleMetadata ruleMetadata = mIntegrityFileManager.readMetadata();
+ return (ruleMetadata != null && ruleMetadata.getVersion() != null)
+ ? ruleMetadata.getVersion()
+ : "";
+ }
+
+ @Override
+ public String getCurrentRuleSetProvider() throws RemoteException {
+ getCallerPackageNameOrThrow();
+
+ RuleMetadata ruleMetadata = mIntegrityFileManager.readMetadata();
+ return (ruleMetadata != null && ruleMetadata.getRuleProvider() != null)
+ ? ruleMetadata.getRuleProvider()
+ : "";
+ }
+
+ private void handleIntegrityVerification(Intent intent) {
int verificationId = intent.getIntExtra(EXTRA_VERIFICATION_ID, -1);
- // TODO: implement this method.
- Slog.i(TAG, "Received integrity verification intent " + intent.toString());
- mPackageManagerInternal.setIntegrityVerificationResult(
- verificationId, PackageManager.VERIFICATION_ALLOW);
+ try {
+ Slog.i(TAG, "Received integrity verification intent " + intent.toString());
+ Slog.i(TAG, "Extras " + intent.getExtras());
+
+ String packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME);
+
+ PackageInfo packageInfo = getPackageArchiveInfo(intent.getData());
+ if (packageInfo == null) {
+ Slog.w(TAG, "Cannot parse package " + packageName);
+ // We can't parse the package.
+ mPackageManagerInternal.setIntegrityVerificationResult(
+ verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ return;
+ }
+
+ String installerPackageName = getInstallerPackageName(intent);
+ String appCert = getCertificateFingerprint(packageInfo);
+
+ AppInstallMetadata.Builder builder = new AppInstallMetadata.Builder();
+
+ builder.setPackageName(getPackageNameNormalized(packageName));
+ builder.setAppCertificate(appCert == null ? "" : appCert);
+ builder.setVersionCode(intent.getIntExtra(EXTRA_VERSION_CODE, -1));
+ builder.setInstallerName(getPackageNameNormalized(installerPackageName));
+ builder.setInstallerCertificate(
+ getInstallerCertificateFingerprint(installerPackageName));
+ builder.setIsPreInstalled(isSystemApp(packageName));
+
+ AppInstallMetadata appInstallMetadata = builder.build();
+
+ Slog.i(TAG, "To be verified: " + appInstallMetadata);
+ IntegrityCheckResult result =
+ mEvaluationEngine.evaluate(
+ appInstallMetadata, getAllowedInstallers(packageInfo));
+ Slog.i(
+ TAG,
+ "Integrity check result: "
+ + result.getEffect()
+ + " due to "
+ + result.getRule());
+ mPackageManagerInternal.setIntegrityVerificationResult(
+ verificationId,
+ result.getEffect() == IntegrityCheckResult.Effect.ALLOW
+ ? PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW
+ : PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
+ } catch (IllegalArgumentException e) {
+ // This exception indicates something is wrong with the input passed by package manager.
+ // e.g., someone trying to trick the system. We block installs in this case.
+ Slog.e(TAG, "Invalid input to integrity verification", e);
+ mPackageManagerInternal.setIntegrityVerificationResult(
+ verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
+ } catch (Exception e) {
+ // Other exceptions indicate an error within the integrity component implementation and
+ // we allow them.
+ Slog.e(TAG, "Error handling integrity verification", e);
+ mPackageManagerInternal.setIntegrityVerificationResult(
+ verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ }
+ }
+
+ /**
+ * Verify the UID and return the installer package name.
+ *
+ * @return the package name of the installer, or null if it cannot be determined or it is
+ * installed via adb.
+ */
+ @Nullable
+ private String getInstallerPackageName(Intent intent) {
+ String installer =
+ intent.getStringExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE);
+ if (installer == null) {
+ return ADB_INSTALLER;
+ }
+ int installerUid = intent.getIntExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID, -1);
+ if (installerUid < 0) {
+ Slog.e(
+ TAG,
+ "Installer cannot be determined: installer: "
+ + installer
+ + " installer UID: "
+ + installerUid);
+ return UNKNOWN_INSTALLER;
+ }
+
+ try {
+ int actualInstallerUid =
+ mContext.getPackageManager().getPackageUid(installer, /* flags= */ 0);
+ if (actualInstallerUid != installerUid) {
+ // Installer package name can be faked but the installerUid cannot.
+ Slog.e(
+ TAG,
+ "Installer "
+ + installer
+ + " has UID "
+ + actualInstallerUid
+ + " which doesn't match alleged installer UID "
+ + installerUid);
+ return UNKNOWN_INSTALLER;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.e(TAG, "Installer package " + installer + " not found.");
+ return UNKNOWN_INSTALLER;
+ }
+
+ // At this time we can trust "installer".
+
+ // A common way for apps to install packages is to send an intent to PackageInstaller. In
+ // that case, the installer will always show up as PackageInstaller which is not what we
+ // want.
+ if (installer.equals(PACKAGE_INSTALLER)) {
+ int originatingUid = intent.getIntExtra(EXTRA_ORIGINATING_UID, -1);
+ if (originatingUid < 0) {
+ Slog.e(TAG, "Installer is package installer but originating UID not found.");
+ return UNKNOWN_INSTALLER;
+ }
+ String[] installerPackages =
+ mContext.getPackageManager().getPackagesForUid(originatingUid);
+ if (installerPackages == null || installerPackages.length == 0) {
+ Slog.e(TAG, "No package found associated with originating UID " + originatingUid);
+ return UNKNOWN_INSTALLER;
+ }
+ // In the case of multiple package sharing a UID, we just return the first one.
+ return installerPackages[0];
+ }
+
+ return installer;
+ }
+
+ /** We will use the SHA256 digest of a package name if it is more than 32 bytes long. */
+ private String getPackageNameNormalized(String packageName) {
+ if (packageName.length() <= 32) {
+ return packageName;
+ }
+
+ try {
+ MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
+ byte[] hashBytes = messageDigest.digest(packageName.getBytes(StandardCharsets.UTF_8));
+ return toHexString(hashBytes);
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("SHA-256 algorithm not found", e);
+ }
+ }
+
+ private String getCertificateFingerprint(@NonNull PackageInfo packageInfo) {
+ return getFingerprint(getSignature(packageInfo));
+ }
+
+ private String getInstallerCertificateFingerprint(String installer) {
+ if (installer.equals(ADB_INSTALLER) || installer.equals(UNKNOWN_INSTALLER)) {
+ return INSTALLER_CERT_NOT_APPLICABLE;
+ }
+ try {
+ PackageInfo installerInfo =
+ mContext.getPackageManager()
+ .getPackageInfo(installer, PackageManager.GET_SIGNATURES);
+ return getCertificateFingerprint(installerInfo);
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.i(TAG, "Installer package " + installer + " not found.");
+ return "";
+ }
+ }
+
+ /** Get the allowed installers and their associated certificate hashes from <meta-data> tag. */
+ private Map<String, String> getAllowedInstallers(@NonNull PackageInfo packageInfo) {
+ Map<String, String> packageCertMap = new HashMap<>();
+ if (packageInfo.applicationInfo != null && packageInfo.applicationInfo.metaData != null) {
+ Bundle metaData = packageInfo.applicationInfo.metaData;
+ String allowedInstallers = metaData.getString(ALLOWED_INSTALLERS_METADATA_NAME);
+ if (allowedInstallers != null) {
+ // parse the metadata for certs.
+ String[] installerCertPairs = allowedInstallers.split(ALLOWED_INSTALLER_DELIMITER);
+ for (String packageCertPair : installerCertPairs) {
+ String[] packageAndCert =
+ packageCertPair.split(INSTALLER_PACKAGE_CERT_DELIMITER);
+ if (packageAndCert.length == 2) {
+ String packageName = packageAndCert[0];
+ String cert = packageAndCert[1];
+ packageCertMap.put(packageName, cert);
+ }
+ }
+ }
+ }
+
+ Slog.i("DEBUG", "allowed installers map " + packageCertMap);
+ return packageCertMap;
+ }
+
+ private boolean getPreInstalled(String packageName) {
+ try {
+ PackageInfo existingPackageInfo =
+ mContext.getPackageManager().getPackageInfo(packageName, 0);
+ return existingPackageInfo.applicationInfo != null
+ && existingPackageInfo.applicationInfo.isSystemApp();
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ private static Signature getSignature(@NonNull PackageInfo packageInfo) {
+ if (packageInfo.signatures == null || packageInfo.signatures.length < 1) {
+ throw new IllegalArgumentException("Package signature not found in " + packageInfo);
+ }
+ // Only the first element is guaranteed to be present.
+ return packageInfo.signatures[0];
+ }
+
+ private static String getFingerprint(Signature cert) {
+ InputStream input = new ByteArrayInputStream(cert.toByteArray());
+
+ CertificateFactory factory;
+ try {
+ factory = CertificateFactory.getInstance("X509");
+ } catch (CertificateException e) {
+ throw new RuntimeException("Error getting CertificateFactory", e);
+ }
+ X509Certificate certificate = null;
+ try {
+ if (factory != null) {
+ certificate = (X509Certificate) factory.generateCertificate(input);
+ }
+ } catch (CertificateException e) {
+ throw new RuntimeException("Error getting X509Certificate", e);
+ }
+
+ if (certificate == null) {
+ throw new RuntimeException("X509 Certificate not found");
+ }
+
+ try {
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ byte[] publicKey = digest.digest(certificate.getEncoded());
+ return toHexString(publicKey);
+ } catch (NoSuchAlgorithmException | CertificateEncodingException e) {
+ throw new IllegalArgumentException("Error error computing fingerprint", e);
+ }
+ }
+
+ private static String toHexString(byte[] bytes) {
+ // each byte is represented by two hex chars
+ StringBuffer hexString = new StringBuffer(bytes.length * 2);
+ for (int i = 0; i < bytes.length; i++) {
+ hexString.append(String.format("%02X", bytes[i]));
+ }
+ return new String(hexString);
+ }
+
+ private PackageInfo getPackageArchiveInfo(Uri dataUri) {
+ File installationPath = getInstallationPath(dataUri);
+ if (installationPath == null) {
+ throw new IllegalArgumentException("Installation path is null, package not found");
+ }
+ PackageInfo packageInfo;
+ try {
+ // The installation path will be a directory for a multi-apk install on L+
+ if (installationPath.isDirectory()) {
+ packageInfo = getMultiApkInfo(installationPath);
+ } else {
+ packageInfo =
+ mContext.getPackageManager()
+ .getPackageArchiveInfo(
+ installationPath.getPath(),
+ PackageManager.GET_SIGNATURES
+ | PackageManager.GET_META_DATA);
+ }
+ return packageInfo;
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Exception reading " + dataUri, e);
+ }
+ }
+
+ private PackageInfo getMultiApkInfo(File multiApkDirectory) {
+ // The base apk will normally be called base.apk
+ File baseFile = new File(multiApkDirectory, BASE_APK_FILE);
+ PackageInfo basePackageInfo =
+ mContext.getPackageManager()
+ .getPackageArchiveInfo(
+ baseFile.getAbsolutePath(), PackageManager.GET_SIGNATURES);
+
+ if (basePackageInfo == null) {
+ for (File apkFile : multiApkDirectory.listFiles()) {
+ if (apkFile.isDirectory()) {
+ continue;
+ }
+
+ // If we didn't find a base.apk, then try to parse each apk until we find the one
+ // that succeeds.
+ basePackageInfo =
+ mContext.getPackageManager()
+ .getPackageArchiveInfo(
+ apkFile.getAbsolutePath(),
+ PackageManager.GET_SIGNING_CERTIFICATES);
+ if (basePackageInfo != null) {
+ Slog.i(TAG, "Found package info from " + apkFile);
+ break;
+ }
+ }
+ }
+
+ if (basePackageInfo == null) {
+ throw new IllegalArgumentException(
+ "Base package info cannot be found from installation directory");
+ }
+
+ return basePackageInfo;
+ }
+
+ private File getInstallationPath(Uri dataUri) {
+ if (dataUri == null) {
+ throw new IllegalArgumentException("Null data uri");
+ }
+
+ String scheme = dataUri.getScheme();
+ if (!"file".equalsIgnoreCase(scheme)) {
+ throw new IllegalArgumentException("Unsupported scheme for " + dataUri);
+ }
+
+ File installationPath = new File(dataUri.getPath());
+ if (!installationPath.exists()) {
+ throw new IllegalArgumentException("Cannot find file for " + dataUri);
+ }
+ if (!installationPath.canRead()) {
+ throw new IllegalArgumentException("Cannot read file for " + dataUri);
+ }
+ return installationPath;
+ }
+
+ private String getCallerPackageNameOrThrow() {
+ final String[] allowedRuleProviders =
+ mContext.getResources()
+ .getStringArray(R.array.config_integrityRuleProviderPackages);
+ for (String packageName : allowedRuleProviders) {
+ try {
+ // At least in tests, getPackageUid gives "NameNotFound" but getPackagesFromUid
+ // give the correct package name.
+ int uid = mContext.getPackageManager().getPackageUid(packageName, 0);
+ if (uid == Binder.getCallingUid()) {
+ // Caller is allowed in the config.
+ if (isSystemApp(packageName)) {
+ return packageName;
+ }
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ // Ignore the exception. We don't expect the app to be necessarily installed.
+ Slog.i(TAG, "Rule provider package " + packageName + " not installed.");
+ }
+ }
+ throw new SecurityException(
+ "Only system packages specified in config_integrityRuleProviderPackages are"
+ + " allowed to call this method.");
+ }
+
+ private boolean isSystemApp(String packageName) {
+ try {
+ PackageInfo existingPackageInfo =
+ mContext.getPackageManager().getPackageInfo(packageName, /* flags= */ 0);
+ return existingPackageInfo.applicationInfo != null
+ && existingPackageInfo.applicationInfo.isSystemApp();
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
}
}
diff --git a/services/core/java/com/android/server/integrity/IntegrityFileManager.java b/services/core/java/com/android/server/integrity/IntegrityFileManager.java
new file mode 100644
index 000000000000..bdf027995fad
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/IntegrityFileManager.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity;
+
+import android.annotation.Nullable;
+import android.content.integrity.AppInstallMetadata;
+import android.content.integrity.Rule;
+import android.os.Environment;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.integrity.model.RuleMetadata;
+import com.android.server.integrity.parser.RuleBinaryParser;
+import com.android.server.integrity.parser.RuleMetadataParser;
+import com.android.server.integrity.parser.RuleParseException;
+import com.android.server.integrity.parser.RuleParser;
+import com.android.server.integrity.serializer.RuleBinarySerializer;
+import com.android.server.integrity.serializer.RuleMetadataSerializer;
+import com.android.server.integrity.serializer.RuleSerializeException;
+import com.android.server.integrity.serializer.RuleSerializer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.Optional;
+
+/** Abstraction over the underlying storage of rules and other metadata. */
+public class IntegrityFileManager {
+ private static final String TAG = "IntegrityFileManager";
+
+ // TODO: this is a prototype implementation of this class. Thus no tests are included.
+ // Implementing rule indexing will likely overhaul this class and more tests should be included
+ // then.
+
+ private static final String METADATA_FILE = "metadata";
+ private static final String RULES_FILE = "rules";
+ private static final Object RULES_LOCK = new Object();
+
+ private static IntegrityFileManager sInstance = null;
+
+ private final RuleParser mRuleParser;
+ private final RuleSerializer mRuleSerializer;
+
+ // mRulesDir contains data of the actual rules currently stored.
+ private final File mRulesDir;
+ // mStagingDir is used to store the temporary rules / metadata during updating, since we want to
+ // update rules atomically.
+ private final File mStagingDir;
+
+ @Nullable private RuleMetadata mRuleMetadataCache;
+
+ /** Get the singleton instance of this class. */
+ public static synchronized IntegrityFileManager getInstance() {
+ if (sInstance == null) {
+ sInstance = new IntegrityFileManager();
+ }
+ return sInstance;
+ }
+
+ private IntegrityFileManager() {
+ this(
+ new RuleBinaryParser(),
+ new RuleBinarySerializer(),
+ Environment.getDataSystemDirectory());
+ }
+
+ @VisibleForTesting
+ IntegrityFileManager(RuleParser ruleParser, RuleSerializer ruleSerializer, File dataDir) {
+ mRuleParser = ruleParser;
+ mRuleSerializer = ruleSerializer;
+
+ mRulesDir = new File(dataDir, "integrity_rules");
+ mStagingDir = new File(dataDir, "integrity_staging");
+
+ if (!mStagingDir.mkdirs() && mRulesDir.mkdirs()) {
+ Slog.e(TAG, "Error creating staging and rules directory");
+ // TODO: maybe throw an exception?
+ }
+
+ File metadataFile = new File(mRulesDir, METADATA_FILE);
+ if (metadataFile.exists()) {
+ try (FileInputStream inputStream = new FileInputStream(metadataFile)) {
+ mRuleMetadataCache = RuleMetadataParser.parse(inputStream);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error reading metadata file.", e);
+ }
+ }
+ }
+
+ /** Write rules to persistent storage. */
+ public void writeRules(String version, String ruleProvider, List<Rule> rules)
+ throws IOException, RuleSerializeException {
+ try {
+ writeMetadata(mStagingDir, ruleProvider, version);
+ } catch (IOException e) {
+ Slog.e(TAG, "Error writing metadata.", e);
+ // We don't consider this fatal so we continue execution.
+ }
+
+ try (FileOutputStream fileOutputStream =
+ new FileOutputStream(new File(mStagingDir, RULES_FILE))) {
+ mRuleSerializer.serialize(rules, Optional.empty(), fileOutputStream);
+ }
+
+ switchStagingRulesDir();
+ }
+
+ /**
+ * Read rules from persistent storage.
+ *
+ * @param appInstallMetadata information about the install used to select rules to read
+ */
+ public List<Rule> readRules(AppInstallMetadata appInstallMetadata)
+ throws IOException, RuleParseException {
+ // TODO: select rules by index
+ synchronized (RULES_LOCK) {
+ try (FileInputStream inputStream =
+ new FileInputStream(new File(mRulesDir, RULES_FILE))) {
+ List<Rule> rules = mRuleParser.parse(inputStream);
+ return rules;
+ }
+ }
+ }
+
+ /** Read the metadata of the current rules in storage. */
+ @Nullable
+ public RuleMetadata readMetadata() {
+ return mRuleMetadataCache;
+ }
+
+ private void switchStagingRulesDir() throws IOException {
+ synchronized (RULES_LOCK) {
+ File tmpDir = new File(Environment.getDataSystemDirectory(), "temp");
+
+ if (!(mRulesDir.renameTo(tmpDir)
+ && mStagingDir.renameTo(mRulesDir)
+ && tmpDir.renameTo(mStagingDir))) {
+ throw new IOException("Error switching staging/rules directory");
+ }
+ }
+ }
+
+ private void writeMetadata(File directory, String ruleProvider, String version)
+ throws IOException {
+ mRuleMetadataCache = new RuleMetadata(ruleProvider, version);
+
+ File metadataFile = new File(directory, METADATA_FILE);
+
+ try (FileOutputStream outputStream = new FileOutputStream(metadataFile)) {
+ RuleMetadataSerializer.serialize(mRuleMetadataCache, outputStream);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java b/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
index b8202b6c0dc6..0ea6efc41f42 100644
--- a/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
+++ b/services/core/java/com/android/server/integrity/engine/RuleEvaluationEngine.java
@@ -18,11 +18,14 @@ package com.android.server.integrity.engine;
import android.content.integrity.AppInstallMetadata;
import android.content.integrity.Rule;
+import android.util.Slog;
+import com.android.server.integrity.IntegrityFileManager;
import com.android.server.integrity.model.IntegrityCheckResult;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
/**
* The engine used to evaluate rules against app installs.
@@ -30,17 +33,23 @@ import java.util.List;
* <p>Every app install is evaluated against rules (pushed by the verifier) by the evaluation engine
* to allow/block that install.
*/
-public final class RuleEvaluationEngine {
+public class RuleEvaluationEngine {
private static final String TAG = "RuleEvaluation";
// The engine for loading rules, retrieving metadata for app installs, and evaluating app
// installs against rules.
private static RuleEvaluationEngine sRuleEvaluationEngine;
+ private final IntegrityFileManager mIntegrityFileManager;
+
+ private RuleEvaluationEngine(IntegrityFileManager integrityFileManager) {
+ mIntegrityFileManager = integrityFileManager;
+ }
+
/** Provide a singleton instance of the rule evaluation engine. */
public static synchronized RuleEvaluationEngine getRuleEvaluationEngine() {
if (sRuleEvaluationEngine == null) {
- return new RuleEvaluationEngine();
+ return new RuleEvaluationEngine(IntegrityFileManager.getInstance());
}
return sRuleEvaluationEngine;
}
@@ -52,13 +61,18 @@ public final class RuleEvaluationEngine {
* against.
* @return result of the integrity check
*/
- public IntegrityCheckResult evaluate(AppInstallMetadata appInstallMetadata) {
+ public IntegrityCheckResult evaluate(
+ AppInstallMetadata appInstallMetadata, Map<String, String> allowedInstallers) {
List<Rule> rules = loadRules(appInstallMetadata);
return RuleEvaluator.evaluateRules(rules, appInstallMetadata);
}
private List<Rule> loadRules(AppInstallMetadata appInstallMetadata) {
- // TODO: Load rules
- return new ArrayList<>();
+ try {
+ return mIntegrityFileManager.readRules(appInstallMetadata);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error loading rules.", e);
+ return new ArrayList<>();
+ }
}
}
diff --git a/services/core/java/com/android/server/integrity/model/RuleMetadata.java b/services/core/java/com/android/server/integrity/model/RuleMetadata.java
new file mode 100644
index 000000000000..6b582ae7b5f2
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/model/RuleMetadata.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.model;
+
+import android.annotation.Nullable;
+
+/** Data class containing relevant metadata associated with a rule set. */
+public class RuleMetadata {
+
+ private final String mRuleProvider;
+ private final String mVersion;
+
+ public RuleMetadata(String ruleProvider, String version) {
+ mRuleProvider = ruleProvider;
+ mVersion = version;
+ }
+
+ @Nullable
+ public String getRuleProvider() {
+ return mRuleProvider;
+ }
+
+ @Nullable
+ public String getVersion() {
+ return mVersion;
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/parser/RuleMetadataParser.java b/services/core/java/com/android/server/integrity/parser/RuleMetadataParser.java
new file mode 100644
index 000000000000..28d2e6914103
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/parser/RuleMetadataParser.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.parser;
+
+import android.annotation.Nullable;
+import android.util.Xml;
+
+import com.android.server.integrity.model.RuleMetadata;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+/** Helper class for parsing rule metadata. */
+public class RuleMetadataParser {
+
+ public static final String RULE_PROVIDER_TAG = "P";
+ public static final String VERSION_TAG = "V";
+
+ /** Parse the rule metadata from an input stream. */
+ @Nullable
+ public static RuleMetadata parse(InputStream inputStream)
+ throws XmlPullParserException, IOException {
+
+ String ruleProvider = "";
+ String version = "";
+
+ XmlPullParser xmlPullParser = Xml.newPullParser();
+ xmlPullParser.setInput(inputStream, StandardCharsets.UTF_8.name());
+
+ int eventType;
+ while ((eventType = xmlPullParser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.START_TAG) {
+ String tag = xmlPullParser.getName();
+ switch (tag) {
+ case RULE_PROVIDER_TAG:
+ ruleProvider = xmlPullParser.nextText();
+ break;
+ case VERSION_TAG:
+ version = xmlPullParser.nextText();
+ break;
+ default:
+ throw new IllegalStateException("Unknown tag in metadata: " + tag);
+ }
+ }
+ }
+
+ return new RuleMetadata(ruleProvider, version);
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleMetadataSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleMetadataSerializer.java
new file mode 100644
index 000000000000..5c51f31ba8cc
--- /dev/null
+++ b/services/core/java/com/android/server/integrity/serializer/RuleMetadataSerializer.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.integrity.serializer;
+
+import static com.android.server.integrity.parser.RuleMetadataParser.RULE_PROVIDER_TAG;
+import static com.android.server.integrity.parser.RuleMetadataParser.VERSION_TAG;
+
+import android.util.Xml;
+
+import com.android.server.integrity.model.RuleMetadata;
+
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+
+/** Helper class for writing rule metadata. */
+public class RuleMetadataSerializer {
+ /** Serialize the rule metadata to an output stream. */
+ public static void serialize(RuleMetadata ruleMetadata, OutputStream outputStream)
+ throws IOException {
+ XmlSerializer xmlSerializer = Xml.newSerializer();
+ xmlSerializer.setOutput(outputStream, StandardCharsets.UTF_8.name());
+
+ serializeTaggedValue(xmlSerializer, RULE_PROVIDER_TAG, ruleMetadata.getRuleProvider());
+ serializeTaggedValue(xmlSerializer, VERSION_TAG, ruleMetadata.getVersion());
+
+ xmlSerializer.endDocument();
+ }
+
+ private static void serializeTaggedValue(XmlSerializer xmlSerializer, String tag, String value)
+ throws IOException {
+ xmlSerializer.startTag(/* namespace= */ null, tag);
+ xmlSerializer.text(value);
+ xmlSerializer.endTag(/* namespace= */ null, tag);
+ }
+}
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
index cfe50c6c8ac9..ebf6a2e20238 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
@@ -16,6 +16,10 @@
package com.android.server.integrity.serializer;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.APP_CERTIFICATE_INDEXED;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.NOT_INDEXED;
+import static com.android.server.integrity.serializer.RuleIndexingDetails.PACKAGE_NAME_INDEXED;
+
import android.content.integrity.AtomicFormula;
import android.content.integrity.CompoundFormula;
import android.content.integrity.Formula;
@@ -29,6 +33,7 @@ import java.io.OutputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
/** A helper class to serialize rules from the {@link Rule} model to Xml representation. */
@@ -75,13 +80,32 @@ public class RuleXmlSerializer implements RuleSerializer {
}
}
- private void serializeRules(List<Rule> rules, XmlSerializer xmlSerializer) throws IOException {
- xmlSerializer.startTag(NAMESPACE, RULE_LIST_TAG);
+ private void serializeRules(List<Rule> rules, XmlSerializer xmlSerializer)
+ throws RuleSerializeException {
+ try {
+ // Determine the indexing groups and the order of the rules within each indexed group.
+ Map<Integer, List<Rule>> indexedRules =
+ RuleIndexingDetailsIdentifier.splitRulesIntoIndexBuckets(rules);
+
+ // Write the XML formatted rules in order.
+ xmlSerializer.startTag(NAMESPACE, RULE_LIST_TAG);
+
+ serializeRuleList(indexedRules.get(PACKAGE_NAME_INDEXED), xmlSerializer);
+ serializeRuleList(indexedRules.get(APP_CERTIFICATE_INDEXED), xmlSerializer);
+ serializeRuleList(indexedRules.get(NOT_INDEXED), xmlSerializer);
+
+ xmlSerializer.endTag(NAMESPACE, RULE_LIST_TAG);
+ xmlSerializer.endDocument();
+ } catch (Exception e) {
+ throw new RuleSerializeException(e.getMessage(), e);
+ }
+ }
+
+ private void serializeRuleList(List<Rule> rules, XmlSerializer xmlSerializer)
+ throws IOException {
for (Rule rule : rules) {
serializeRule(rule, xmlSerializer);
}
- xmlSerializer.endTag(NAMESPACE, RULE_LIST_TAG);
- xmlSerializer.endDocument();
}
private void serializeRule(Rule rule, XmlSerializer xmlSerializer) throws IOException {
diff --git a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
index eb706d7791d3..1d391775e550 100644
--- a/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
+++ b/services/core/java/com/android/server/media/AudioPlayerStateMonitor.java
@@ -240,8 +240,7 @@ class AudioPlayerStateMonitor {
if (!mPrevActiveAudioPlaybackConfigs.containsKey(
config.getPlayerInterfaceId())) {
if (DEBUG) {
- Log.d(TAG, "Found a new active media playback. "
- + AudioPlaybackConfiguration.toLogFriendlyString(config));
+ Log.d(TAG, "Found a new active media playback. " + config);
}
// New active audio playback.
int index = mSortedAudioPlaybackClientUids.indexOf(uid);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 83d0ecd33fbc..2ebca8870ec5 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1828,7 +1828,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
String[] mergedSubscriberId = ArrayUtils.defeatNullable(
- tm.createForSubscriptionId(subId).getMergedSubscriberIdsFromGroup());
+ tm.createForSubscriptionId(subId).getMergedImsisFromGroup());
mergedSubscriberIdsList.add(mergedSubscriberId);
}
diff --git a/services/core/java/com/android/server/pm/DataLoaderManagerService.java b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
index 0719797ed85a..0dfea7fd5f96 100644
--- a/services/core/java/com/android/server/pm/DataLoaderManagerService.java
+++ b/services/core/java/com/android/server/pm/DataLoaderManagerService.java
@@ -76,13 +76,12 @@ public class DataLoaderManagerService extends SystemService {
return false;
}
}
- CharSequence packageNameSeq = params.getCharSequence("packageName");
- if (packageNameSeq == null) {
- Slog.e(TAG, "Must specify package name.");
+ ComponentName componentName = params.getParcelable("componentName");
+ if (componentName == null) {
+ Slog.e(TAG, "Must specify component name.");
return false;
}
- String packageName = packageNameSeq.toString();
- ComponentName dataLoaderComponent = getDataLoaderServiceName(packageName);
+ ComponentName dataLoaderComponent = resolveDataLoaderComponentName(componentName);
if (dataLoaderComponent == null) {
return false;
}
@@ -103,22 +102,23 @@ public class DataLoaderManagerService extends SystemService {
/**
* Find the ComponentName of the data loader service provider, given its package name.
*
- * @param packageName the package name of the provider.
+ * @param componentName the name of the provider.
* @return ComponentName of the data loader service provider. Null if provider not found.
*/
- private @Nullable ComponentName getDataLoaderServiceName(String packageName) {
+ private @Nullable ComponentName resolveDataLoaderComponentName(
+ ComponentName componentName) {
final PackageManager pm = mContext.getPackageManager();
if (pm == null) {
Slog.e(TAG, "PackageManager is not available.");
return null;
}
Intent intent = new Intent(Intent.ACTION_LOAD_DATA);
- intent.setPackage(packageName);
+ intent.setComponent(componentName);
List<ResolveInfo> services =
pm.queryIntentServicesAsUser(intent, 0, UserHandle.getCallingUserId());
if (services == null || services.isEmpty()) {
Slog.e(TAG,
- "Failed to find data loader service provider in package " + packageName);
+ "Failed to find data loader service provider in " + componentName);
return null;
}
@@ -128,23 +128,21 @@ public class DataLoaderManagerService extends SystemService {
int numServices = services.size();
for (int i = 0; i < numServices; i++) {
ResolveInfo ri = services.get(i);
- ComponentName componentName = new ComponentName(
+ ComponentName resolved = new ComponentName(
ri.serviceInfo.packageName, ri.serviceInfo.name);
// There should only be one matching provider inside the given package.
// If there's more than one, return the first one found.
try {
- ApplicationInfo ai = pm.getApplicationInfo(componentName.getPackageName(), 0);
+ ApplicationInfo ai = pm.getApplicationInfo(resolved.getPackageName(), 0);
if (checkLoader && !ai.isPrivilegedApp()) {
Slog.w(TAG,
- "Data loader: " + componentName.getPackageName()
- + " is not a privileged app, skipping.");
+ "Data loader: " + resolved + " is not a privileged app, skipping.");
continue;
}
- return componentName;
+ return resolved;
} catch (PackageManager.NameNotFoundException ex) {
Slog.w(TAG,
- "Privileged data loader: " + componentName.getPackageName()
- + " not found, skipping.");
+ "Privileged data loader: " + resolved + " not found, skipping.");
}
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index a54534b461f1..e2dfa126225f 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -217,6 +217,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
public void systemReady() {
mAppOps = mContext.getSystemService(AppOpsManager.class);
+ mStagingManager.systemReady();
synchronized (mSessions) {
readSessionsLocked();
@@ -257,8 +258,9 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
}
// Don't hold mSessions lock when calling restoreSession, since it might trigger an APK
// atomic install which needs to query sessions, which requires lock on mSessions.
+ boolean isDeviceUpgrading = mPm.isDeviceUpgrading();
for (PackageInstallerSession session : stagedSessionsToRestore) {
- if (mPm.isDeviceUpgrading() && !session.isStagedAndInTerminalState()) {
+ if (isDeviceUpgrading && !session.isStagedAndInTerminalState()) {
session.setStagedSessionFailed(SessionInfo.STAGED_SESSION_ACTIVATION_FAILED,
"Build fingerprint has changed");
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index c12395e28e28..ac183dcf6b7a 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -16,6 +16,8 @@
package com.android.server.pm;
+import static android.content.pm.DataLoaderType.INCREMENTAL;
+import static android.content.pm.DataLoaderType.STREAMING;
import static android.content.pm.PackageManager.INSTALL_FAILED_ABORTED;
import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_SIGNATURE;
import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
@@ -49,12 +51,18 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.admin.DevicePolicyEventLogger;
import android.app.admin.DevicePolicyManagerInternal;
+import android.content.ComponentName;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
+import android.content.pm.DataLoaderManager;
+import android.content.pm.DataLoaderParams;
+import android.content.pm.FileSystemControlParcel;
+import android.content.pm.IDataLoader;
+import android.content.pm.IDataLoaderStatusListener;
import android.content.pm.IPackageInstallObserver2;
import android.content.pm.IPackageInstallerSession;
import android.content.pm.IPackageInstallerSessionFileSystemConnector;
@@ -84,6 +92,7 @@ import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.ParcelableException;
import android.os.Process;
+import android.os.RemoteException;
import android.os.RevocableFileDescriptor;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -127,12 +136,12 @@ import java.io.FileDescriptor;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static final String TAG = "PackageInstallerSession";
@@ -189,7 +198,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static final String ATTR_VOLUME_UUID = "volumeUuid";
private static final String ATTR_NAME = "name";
private static final String ATTR_INSTALL_REASON = "installRason";
- private static final String ATTR_DATA_LOADER_PACKAGE_NAME = "dataLoaderPackageName";
+ private static final String ATTR_IS_DATALOADER = "isDataLoader";
+ private static final String ATTR_DATALOADER_TYPE = "dataLoaderType";
+ private static final String ATTR_DATALOADER_PACKAGE_NAME = "dataLoaderPackageName";
+ private static final String ATTR_DATALOADER_CLASS_NAME = "dataLoaderClassName";
+ private static final String ATTR_DATALOADER_ARGUMENTS = "dataLoaderArguments";
private static final String ATTR_LENGTH_BYTES = "lengthBytes";
private static final String ATTR_METADATA = "metadata";
@@ -414,7 +427,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
};
private boolean isDataLoaderInstallation() {
- return !TextUtils.isEmpty(params.dataLoaderPackageName);
+ return params.dataLoaderParams != null;
+ }
+
+ private boolean isStreamingInstallation() {
+ return isDataLoaderInstallation() && params.dataLoaderParams.getType() == STREAMING;
+ }
+
+ private boolean isIncrementalInstallation() {
+ return isDataLoaderInstallation() && params.dataLoaderParams.getType() == INCREMENTAL;
}
/**
@@ -525,14 +546,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
stagedSessionErrorMessage != null ? stagedSessionErrorMessage : "";
// TODO(b/136132412): sanity check if session should not be incremental
- if (!params.isStaged && params.incrementalParams != null
- && !params.incrementalParams.getPackageName().isEmpty()) {
+ if (!params.isStaged && isIncrementalInstallation()) {
IncrementalManager incrementalManager = (IncrementalManager) mContext.getSystemService(
Context.INCREMENTAL_SERVICE);
if (incrementalManager != null) {
mIncrementalFileStorages =
new IncrementalFileStorages(mPackageName, stageDir, incrementalManager,
- params.incrementalParams);
+ params.dataLoaderParams);
}
}
}
@@ -714,7 +734,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
public void removeSplit(String splitName) {
if (isDataLoaderInstallation()) {
throw new IllegalStateException(
- "Cannot remove splits in a callback installation session.");
+ "Cannot remove splits in a data loader installation session.");
}
if (TextUtils.isEmpty(params.appPackageName)) {
throw new IllegalStateException("Must specify package name to remove a split");
@@ -753,7 +773,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private void assertCanWrite(boolean reverseMode) {
if (isDataLoaderInstallation()) {
throw new IllegalStateException(
- "Cannot write regular files in a callback installation session.");
+ "Cannot write regular files in a data loader installation session.");
}
synchronized (mLock) {
assertCallerIsOwnerOrRootLocked();
@@ -894,7 +914,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
public ParcelFileDescriptor openRead(String name) {
if (isDataLoaderInstallation()) {
throw new IllegalStateException(
- "Cannot read regular files in a callback installation session.");
+ "Cannot read regular files in a data loader installation session.");
}
synchronized (mLock) {
assertCallerIsOwnerOrRootLocked();
@@ -1663,7 +1683,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
computeProgressLocked(true);
// Unpack native libraries for non-incremental installation
- if (params.incrementalParams == null) {
+ if (isIncrementalInstallation()) {
extractNativeLibraries(stageDir, params.abiOverride, mayInheritNativeLibs());
}
}
@@ -2382,7 +2402,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
if (!isDataLoaderInstallation()) {
throw new IllegalStateException(
- "Cannot add files to non-callback installation session.");
+ "Cannot add files to non-data loader installation session.");
}
// Use installer provided name for now; we always rename later
if (!FileUtils.isValidExtFilename(name)) {
@@ -2401,7 +2421,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
public void removeFile(String name) {
if (!isDataLoaderInstallation()) {
throw new IllegalStateException(
- "Cannot add files to non-callback installation session.");
+ "Cannot add files to non-data loader installation session.");
}
if (TextUtils.isEmpty(params.appPackageName)) {
throw new IllegalStateException("Must specify package name to remove a split");
@@ -2415,76 +2435,121 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
+ static class Notificator {
+ private int mValue = 0;
+
+ void setValue(int value) {
+ synchronized (this) {
+ mValue = value;
+ this.notify();
+ }
+ }
+ int waitForValue() {
+ synchronized (this) {
+ while (mValue == 0) {
+ try {
+ this.wait();
+ } catch (InterruptedException e) {
+ // Happens if someone interrupts your thread.
+ }
+ }
+ return mValue;
+ }
+ }
+ }
+
/**
* Makes sure files are present in staging location.
*/
private void prepareDataLoader()
throws PackageManagerException, StreamingException {
- if (!isDataLoaderInstallation()) {
+ if (!isStreamingInstallation()) {
return;
}
FileSystemConnector connector = new FileSystemConnector();
- FileInfo[] addedFiles = mFiles.stream().filter(
- file -> sAddedFilter.accept(new File(file.name))).toArray(FileInfo[]::new);
- String[] removedFiles = mFiles.stream().filter(
+ List<InstallationFile> addedFiles = mFiles.stream().filter(
+ file -> sAddedFilter.accept(new File(file.name))).map(
+ file -> new InstallationFile(
+ file.name, file.lengthBytes, file.metadata)).collect(
+ Collectors.toList());
+ List<String> removedFiles = mFiles.stream().filter(
file -> sRemovedFilter.accept(new File(file.name))).map(
- file -> file.name.substring(0,
- file.name.length() - REMOVE_MARKER_EXTENSION.length())).toArray(
- String[]::new);
+ file -> file.name.substring(
+ 0, file.name.length() - REMOVE_MARKER_EXTENSION.length())).collect(
+ Collectors.toList());
- DataLoader dataLoader = new DataLoader();
- try {
- dataLoader.onCreate(connector);
+ DataLoaderManager dataLoaderManager = mContext.getSystemService(DataLoaderManager.class);
+ if (dataLoaderManager == null) {
+ throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
+ "Failed to find data loader manager service");
+ }
- if (!dataLoader.onPrepareImage(addedFiles, removedFiles)) {
- throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
- "Failed to prepare image.");
+ // TODO(b/146080380): make this code async.
+ final Notificator created = new Notificator();
+ final Notificator started = new Notificator();
+ final Notificator imageReady = new Notificator();
+
+ IDataLoaderStatusListener listener = new IDataLoaderStatusListener.Stub() {
+ @Override
+ public void onStatusChanged(int dataLoaderId, int status) {
+ switch (status) {
+ case IDataLoaderStatusListener.DATA_LOADER_CREATED: {
+ created.setValue(1);
+ break;
+ }
+ case IDataLoaderStatusListener.DATA_LOADER_STARTED: {
+ started.setValue(1);
+ break;
+ }
+ case IDataLoaderStatusListener.DATA_LOADER_IMAGE_READY: {
+ imageReady.setValue(1);
+ break;
+ }
+ case IDataLoaderStatusListener.DATA_LOADER_IMAGE_NOT_READY: {
+ imageReady.setValue(2);
+ break;
+ }
+ }
}
- } catch (IOException e) {
- throw new StreamingException(e);
- } finally {
- dataLoader.onDestroy();
- }
- }
+ };
+
+ final DataLoaderParams params = this.params.dataLoaderParams;
- static class DataLoader {
- private ParcelFileDescriptor mInFd = null;
- private FileSystemConnector mConnector = null;
+ final FileSystemControlParcel control = new FileSystemControlParcel();
+ control.callback = connector;
- void onCreate(FileSystemConnector connector) throws IOException {
- mConnector = connector;
+ Bundle dataLoaderParams = new Bundle();
+ dataLoaderParams.putParcelable("componentName", params.getComponentName());
+ dataLoaderParams.putParcelable("control", control);
+ dataLoaderParams.putParcelable("params", params.getData());
+
+ if (!dataLoaderManager.initializeDataLoader(sessionId, dataLoaderParams, listener)) {
+ throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
+ "Failed to initialize data loader");
}
+ created.waitForValue();
- void onDestroy() {
- IoUtils.closeQuietly(mInFd);
+ IDataLoader dataLoader = dataLoaderManager.getDataLoader(sessionId);
+ if (dataLoader == null) {
+ throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
+ "Failure to obtain data loader");
}
- private static final String STDIN_PATH = "-";
- boolean onPrepareImage(FileInfo[] addedFiles, String[] removedFiles) throws IOException {
- for (FileInfo fileInfo : addedFiles) {
- String filePath = new String(fileInfo.metadata, StandardCharsets.UTF_8);
- if (STDIN_PATH.equals(filePath) || TextUtils.isEmpty(filePath)) {
- if (mInFd == null) {
- Slog.e(TAG, "Invalid stdin file descriptor.");
- return false;
- }
- ParcelFileDescriptor inFd = ParcelFileDescriptor.dup(mInFd.getFileDescriptor());
- mConnector.writeData(fileInfo.name, 0, fileInfo.lengthBytes, inFd);
- } else {
- File localFile = new File(filePath);
- ParcelFileDescriptor incomingFd = null;
- try {
- incomingFd = ParcelFileDescriptor.open(localFile,
- ParcelFileDescriptor.MODE_READ_ONLY);
- mConnector.writeData(fileInfo.name, 0, localFile.length(), incomingFd);
- } finally {
- IoUtils.closeQuietly(incomingFd);
- }
- }
+ try {
+ dataLoader.start();
+ started.waitForValue();
+
+ dataLoader.prepareImage(addedFiles, removedFiles);
+ if (imageReady.waitForValue() == 2) {
+ throw new PackageManagerException(INSTALL_FAILED_MEDIA_UNAVAILABLE,
+ "Failed to prepare image.");
}
- return true;
+
+ dataLoader.destroy();
+ } catch (RemoteException e) {
+ throw new StreamingException(e);
}
}
@@ -2846,7 +2911,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
writeStringAttribute(out, ATTR_VOLUME_UUID, params.volumeUuid);
writeIntAttribute(out, ATTR_INSTALL_REASON, params.installReason);
- writeStringAttribute(out, ATTR_DATA_LOADER_PACKAGE_NAME, params.dataLoaderPackageName);
+ final boolean isDataLoader = params.dataLoaderParams != null;
+ writeBooleanAttribute(out, ATTR_IS_DATALOADER, isDataLoader);
+ if (isDataLoader) {
+ writeIntAttribute(out, ATTR_DATALOADER_TYPE, params.dataLoaderParams.getType());
+ writeStringAttribute(out, ATTR_DATALOADER_PACKAGE_NAME,
+ params.dataLoaderParams.getComponentName().getPackageName());
+ writeStringAttribute(out, ATTR_DATALOADER_CLASS_NAME,
+ params.dataLoaderParams.getComponentName().getClassName());
+ writeStringAttribute(out, ATTR_DATALOADER_ARGUMENTS,
+ params.dataLoaderParams.getArguments());
+ }
writeGrantedRuntimePermissionsLocked(out, params.grantedRuntimePermissions);
writeWhitelistedRestrictedPermissionsLocked(out,
@@ -2957,7 +3032,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
params.volumeUuid = readStringAttribute(in, ATTR_VOLUME_UUID);
params.installReason = readIntAttribute(in, ATTR_INSTALL_REASON);
- params.dataLoaderPackageName = readStringAttribute(in, ATTR_DATA_LOADER_PACKAGE_NAME);
+ if (readBooleanAttribute(in, ATTR_IS_DATALOADER)) {
+ params.dataLoaderParams = new DataLoaderParams(
+ readIntAttribute(in, ATTR_DATALOADER_TYPE),
+ new ComponentName(
+ readStringAttribute(in, ATTR_DATALOADER_PACKAGE_NAME),
+ readStringAttribute(in, ATTR_DATALOADER_CLASS_NAME)),
+ readStringAttribute(in, ATTR_DATALOADER_ARGUMENTS),
+ null);
+ }
final File appIconFile = buildAppIconFile(sessionId, sessionsDir);
if (appIconFile.exists()) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index da104eea8e5c..785ca7dd1fe8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -27,6 +27,8 @@ import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.content.Intent.ACTION_MAIN;
import static android.content.Intent.CATEGORY_DEFAULT;
import static android.content.Intent.CATEGORY_HOME;
+import static android.content.Intent.EXTRA_PACKAGE_NAME;
+import static android.content.Intent.EXTRA_VERSION_CODE;
import static android.content.pm.PackageManager.CERT_INPUT_RAW_X509;
import static android.content.pm.PackageManager.CERT_INPUT_SHA256;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
@@ -34,6 +36,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID;
import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
@@ -558,6 +561,11 @@ public class PackageManagerService extends IPackageManager.Stub
private static final boolean DEFAULT_VERIFY_ENABLE = true;
/**
+ * Whether integrity verification is enabled by default.
+ */
+ private static final boolean DEFAULT_INTEGRITY_VERIFY_ENABLE = true;
+
+ /**
* The default maximum time to wait for the verification agent to return in
* milliseconds.
*/
@@ -1444,6 +1452,7 @@ public class PackageManagerService extends IPackageManager.Stub
static final int DEFERRED_NO_KILL_POST_DELETE = 23;
static final int DEFERRED_NO_KILL_INSTALL_OBSERVER = 24;
static final int INTEGRITY_VERIFICATION_COMPLETE = 25;
+ static final int CHECK_PENDING_INTEGRITY_VERIFICATION = 26;
static final int DEFERRED_NO_KILL_POST_DELETE_DELAY_MS = 3 * 1000;
static final int DEFERRED_NO_KILL_INSTALL_OBSERVER_DELAY_MS = 500;
@@ -1707,13 +1716,13 @@ public class PackageManagerService extends IPackageManager.Stub
final int verificationId = msg.arg1;
final PackageVerificationState state = mPendingVerification.get(verificationId);
- if ((state != null) && !state.timeoutExtended()) {
+ if ((state != null) && !state.isVerificationComplete()
+ && !state.timeoutExtended()) {
final InstallParams params = state.getInstallParams();
final InstallArgs args = params.mArgs;
final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
Slog.i(TAG, "Verification timed out for " + originUri);
- mPendingVerification.remove(verificationId);
final UserHandle user = args.getUser();
if (getDefaultVerificationResponse(user)
@@ -1728,11 +1737,54 @@ public class PackageManagerService extends IPackageManager.Stub
PackageManager.VERIFICATION_REJECT, user);
params.setReturnCode(
PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE);
+ state.setVerifierResponse(Binder.getCallingUid(),
+ PackageManager.VERIFICATION_REJECT);
+ }
+
+ if (state.areAllVerificationsComplete()) {
+ mPendingVerification.remove(verificationId);
}
Trace.asyncTraceEnd(
TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
+
params.handleVerificationFinished();
+
+ }
+ break;
+ }
+ case CHECK_PENDING_INTEGRITY_VERIFICATION: {
+ final int verificationId = msg.arg1;
+ final PackageVerificationState state = mPendingVerification.get(verificationId);
+
+ if (state != null && !state.isIntegrityVerificationComplete()) {
+ final InstallParams params = state.getInstallParams();
+ final InstallArgs args = params.mArgs;
+ final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
+
+ Slog.i(TAG, "Integrity verification timed out for " + originUri);
+
+ state.setIntegrityVerificationResult(
+ getDefaultIntegrityVerificationResponse());
+
+ if (getDefaultIntegrityVerificationResponse()
+ == PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW) {
+ Slog.i(TAG, "Integrity check times out, continuing with " + originUri);
+ } else {
+ params.setReturnCode(
+ PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE);
+ }
+
+ if (state.areAllVerificationsComplete()) {
+ mPendingVerification.remove(verificationId);
+ }
+
+ Trace.asyncTraceEnd(
+ TRACE_TAG_PACKAGE_MANAGER,
+ "integrity_verification",
+ verificationId);
+
+ params.handleIntegrityVerificationFinished();
}
break;
}
@@ -1741,7 +1793,9 @@ public class PackageManagerService extends IPackageManager.Stub
final PackageVerificationState state = mPendingVerification.get(verificationId);
if (state == null) {
- Slog.w(TAG, "Invalid verification token " + verificationId + " received");
+ Slog.w(TAG, "Verification with id " + verificationId
+ + " not found."
+ + " It may be invalid or overridden by integrity verification");
break;
}
@@ -1750,8 +1804,6 @@ public class PackageManagerService extends IPackageManager.Stub
state.setVerifierResponse(response.callerUid, response.code);
if (state.isVerificationComplete()) {
- mPendingVerification.remove(verificationId);
-
final InstallParams params = state.getInstallParams();
final InstallArgs args = params.mArgs;
final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
@@ -1764,6 +1816,10 @@ public class PackageManagerService extends IPackageManager.Stub
PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE);
}
+ if (state.areAllVerificationsComplete()) {
+ mPendingVerification.remove(verificationId);
+ }
+
Trace.asyncTraceEnd(
TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
@@ -1773,7 +1829,40 @@ public class PackageManagerService extends IPackageManager.Stub
break;
}
case INTEGRITY_VERIFICATION_COMPLETE: {
- // TODO: implement this case.
+ final int verificationId = msg.arg1;
+
+ final PackageVerificationState state = mPendingVerification.get(verificationId);
+ if (state == null) {
+ Slog.w(TAG, "Integrity verification with id " + verificationId
+ + " not found. It may be invalid or overridden by verifier");
+ break;
+ }
+
+ final int response = (Integer) msg.obj;
+
+ final InstallParams params = state.getInstallParams();
+ final InstallArgs args = params.mArgs;
+ final Uri originUri = Uri.fromFile(args.origin.resolvedFile);
+
+ state.setIntegrityVerificationResult(response);
+
+ if (response == PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW) {
+ Slog.i(TAG, "Integrity check passed for " + originUri);
+ } else {
+ params.setReturnCode(
+ PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE);
+ }
+
+ if (state.areAllVerificationsComplete()) {
+ mPendingVerification.remove(verificationId);
+ }
+
+ Trace.asyncTraceEnd(
+ TRACE_TAG_PACKAGE_MANAGER,
+ "integrity_verification",
+ verificationId);
+
+ params.handleIntegrityVerificationFinished();
break;
}
case START_INTENT_FILTER_VERIFICATIONS: {
@@ -13099,6 +13188,15 @@ public class PackageManagerService extends IPackageManager.Stub
}
/**
+ * Get the default integrity verification response code.
+ */
+ private int getDefaultIntegrityVerificationResponse() {
+ // We are not exposing this as a user-configurable setting because we don't want to provide
+ // an easy way to get around the integrity check.
+ return PackageManager.VERIFICATION_REJECT;
+ }
+
+ /**
* Check whether or not package verification has been enabled.
*
* @return true if verification should be performed
@@ -13141,6 +13239,15 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
+ /**
+ * Check whether or not integrity verification has been enabled.
+ */
+ private boolean isIntegrityVerificationEnabled() {
+ // We are not exposing this as a user-configurable setting because we don't want to provide
+ // an easy way to get around the integrity check.
+ return DEFAULT_INTEGRITY_VERIFY_ENABLE;
+ }
+
@Override
public void verifyIntentFilter(int id, int verificationCode, List<String> failedDomains)
throws RemoteException {
@@ -13851,6 +13958,7 @@ public class PackageManagerService extends IPackageManager.Stub
@NonNull final InstallSource installSource;
final String volumeUuid;
private boolean mVerificationCompleted;
+ private boolean mIntegrityVerificationCompleted;
private boolean mEnableRollbackCompleted;
private InstallArgs mArgs;
int mRet;
@@ -14112,155 +14220,30 @@ public class PackageManagerService extends IPackageManager.Stub
final InstallArgs args = createInstallArgs(this);
mVerificationCompleted = true;
+ mIntegrityVerificationCompleted = true;
mEnableRollbackCompleted = true;
mArgs = args;
if (ret == PackageManager.INSTALL_SUCCEEDED) {
- // TODO: http://b/22976637
- // Apps installed for "all" users use the device owner to verify the app
- UserHandle verifierUser = getUser();
- if (verifierUser == UserHandle.ALL) {
- verifierUser = UserHandle.SYSTEM;
- }
-
- /*
- * Determine if we have any installed package verifiers. If we
- * do, then we'll defer to them to verify the packages.
- */
- final int requiredUid = mRequiredVerifierPackage == null ? -1
- : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
- verifierUser.getIdentifier());
- final int installerUid =
- verificationInfo == null ? -1 : verificationInfo.installerUid;
- if (!origin.existing && requiredUid != -1
- && isVerificationEnabled(
- verifierUser.getIdentifier(), installFlags, installerUid)) {
- final Intent verification = new Intent(
- Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
- verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
- PACKAGE_MIME_TYPE);
- verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- // Query all live verifiers based on current user state
- final List<ResolveInfo> receivers = queryIntentReceiversInternal(verification,
- PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier(),
- false /*allowDynamicSplits*/);
-
- if (DEBUG_VERIFY) {
- Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
- + verification.toString() + " with " + pkgLite.verifiers.length
- + " optional verifiers");
- }
-
- final int verificationId = mPendingVerificationToken++;
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
- installSource.initiatingPackageName);
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS,
- installFlags);
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME,
- pkgLite.packageName);
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_VERSION_CODE,
- pkgLite.versionCode);
-
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_LONG_VERSION_CODE,
- pkgLite.getLongVersionCode());
-
- if (verificationInfo != null) {
- if (verificationInfo.originatingUri != null) {
- verification.putExtra(Intent.EXTRA_ORIGINATING_URI,
- verificationInfo.originatingUri);
- }
- if (verificationInfo.referrer != null) {
- verification.putExtra(Intent.EXTRA_REFERRER,
- verificationInfo.referrer);
- }
- if (verificationInfo.originatingUid >= 0) {
- verification.putExtra(Intent.EXTRA_ORIGINATING_UID,
- verificationInfo.originatingUid);
- }
- if (verificationInfo.installerUid >= 0) {
- verification.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
- verificationInfo.installerUid);
- }
- }
-
- final PackageVerificationState verificationState = new PackageVerificationState(
- requiredUid, this);
+ final int verificationId = mPendingVerificationToken++;
+ // Perform package verification (unless we are simply moving the package).
+ if (!origin.existing) {
+ PackageVerificationState verificationState =
+ new PackageVerificationState(this);
mPendingVerification.append(verificationId, verificationState);
- final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
- receivers, verificationState);
-
- DeviceIdleInternal idleController =
- mInjector.getLocalDeviceIdleController();
- final long idleDuration = getVerificationTimeout();
+ sendIntegrityVerificationRequest(verificationId, pkgLite, verificationState);
+ ret = sendPackageVerificationRequest(
+ verificationId, pkgLite, verificationState);
- /*
- * If any sufficient verifiers were listed in the package
- * manifest, attempt to ask them.
- */
- if (sufficientVerifiers != null) {
- final int N = sufficientVerifiers.size();
- if (N == 0) {
- Slog.i(TAG, "Additional verifiers required, but none installed.");
- ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
- } else {
- for (int i = 0; i < N; i++) {
- final ComponentName verifierComponent = sufficientVerifiers.get(i);
- idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
- verifierComponent.getPackageName(), idleDuration,
- verifierUser.getIdentifier(), false, "package verifier");
-
- final Intent sufficientIntent = new Intent(verification);
- sufficientIntent.setComponent(verifierComponent);
- mContext.sendBroadcastAsUser(sufficientIntent, verifierUser);
- }
- }
- }
-
- final ComponentName requiredVerifierComponent = matchComponentForVerifier(
- mRequiredVerifierPackage, receivers);
- if (ret == PackageManager.INSTALL_SUCCEEDED
- && mRequiredVerifierPackage != null) {
- Trace.asyncTraceBegin(
- TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
- /*
- * Send the intent to the required verification agent,
- * but only start the verification timeout after the
- * target BroadcastReceivers have run.
- */
- verification.setComponent(requiredVerifierComponent);
- idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
- mRequiredVerifierPackage, idleDuration,
- verifierUser.getIdentifier(), false, "package verifier");
- mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
- android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
- new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- final Message msg = mHandler
- .obtainMessage(CHECK_PENDING_VERIFICATION);
- msg.arg1 = verificationId;
- mHandler.sendMessageDelayed(msg, getVerificationTimeout());
- }
- }, null, 0, null, null);
-
- /*
- * We don't want the copy to proceed until verification
- * succeeds.
- */
- mVerificationCompleted = false;
+ // If both verifications are skipped, we should remove the state.
+ if (verificationState.areAllVerificationsComplete()) {
+ mPendingVerification.remove(verificationId);
}
}
+
if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0) {
// TODO(ruhler) b/112431924: Don't do this in case of 'move'?
final int enableRollbackToken = mPendingEnableRollbackToken++;
@@ -14316,6 +14299,228 @@ public class PackageManagerService extends IPackageManager.Stub
mRet = ret;
}
+ /**
+ * Send a request to check the integrity of the package.
+ */
+ void sendIntegrityVerificationRequest(
+ int verificationId,
+ PackageInfoLite pkgLite,
+ PackageVerificationState verificationState) {
+ if (!isIntegrityVerificationEnabled()) {
+ // Consider the integrity check as passed.
+ verificationState.setIntegrityVerificationResult(
+ PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ return;
+ }
+
+ final Intent integrityVerification =
+ new Intent(Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
+
+ integrityVerification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
+ PACKAGE_MIME_TYPE);
+
+ final int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
+ | Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND;
+ integrityVerification.addFlags(flags);
+
+ integrityVerification.putExtra(EXTRA_VERIFICATION_ID, verificationId);
+ integrityVerification.putExtra(EXTRA_PACKAGE_NAME, pkgLite.packageName);
+ integrityVerification.putExtra(EXTRA_VERSION_CODE, pkgLite.versionCode);
+ populateInstallerExtras(integrityVerification);
+
+ // send to integrity component only.
+ integrityVerification.setPackage("android");
+
+ DeviceIdleInternal idleController =
+ mInjector.getLocalDeviceIdleController();
+ final long idleDuration = getVerificationTimeout();
+
+ idleController.addPowerSaveTempWhitelistAppDirect(Process.myUid(),
+ idleDuration,
+ false, "integrity component");
+ mContext.sendOrderedBroadcastAsUser(integrityVerification, UserHandle.SYSTEM,
+ /* receiverPermission= */ null,
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final Message msg =
+ mHandler.obtainMessage(CHECK_PENDING_INTEGRITY_VERIFICATION);
+ msg.arg1 = verificationId;
+ // TODO: do we want to use the same timeout?
+ mHandler.sendMessageDelayed(msg, getVerificationTimeout());
+ }
+ }, /* scheduler= */ null,
+ /* initialCode= */ 0,
+ /* initialData= */ null,
+ /* initialExtras= */ null);
+
+ Trace.asyncTraceBegin(
+ TRACE_TAG_PACKAGE_MANAGER, "integrity_verification", verificationId);
+
+ // stop the copy until verification succeeds.
+ mIntegrityVerificationCompleted = false;
+ }
+
+ /**
+ * Send a request to verifier(s) to verify the package if necessary, and return
+ * {@link PackageManager#INSTALL_SUCCEEDED} if succeeded.
+ */
+ int sendPackageVerificationRequest(
+ int verificationId,
+ PackageInfoLite pkgLite,
+ PackageVerificationState verificationState) {
+ int ret = INSTALL_SUCCEEDED;
+
+ // TODO: http://b/22976637
+ // Apps installed for "all" users use the device owner to verify the app
+ UserHandle verifierUser = getUser();
+ if (verifierUser == UserHandle.ALL) {
+ verifierUser = UserHandle.SYSTEM;
+ }
+
+ /*
+ * Determine if we have any installed package verifiers. If we
+ * do, then we'll defer to them to verify the packages.
+ */
+ final int requiredUid = mRequiredVerifierPackage == null ? -1
+ : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
+ verifierUser.getIdentifier());
+ verificationState.setRequiredVerifierUid(requiredUid);
+ final int installerUid =
+ verificationInfo == null ? -1 : verificationInfo.installerUid;
+ if (!origin.existing && requiredUid != -1
+ && isVerificationEnabled(
+ verifierUser.getIdentifier(), installFlags, installerUid)) {
+ final Intent verification = new Intent(
+ Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
+ verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+ verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
+ PACKAGE_MIME_TYPE);
+ verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ // Query all live verifiers based on current user state
+ final List<ResolveInfo> receivers = queryIntentReceiversInternal(verification,
+ PACKAGE_MIME_TYPE, 0, verifierUser.getIdentifier(),
+ false /*allowDynamicSplits*/);
+
+ if (DEBUG_VERIFY) {
+ Slog.d(TAG, "Found " + receivers.size() + " verifiers for intent "
+ + verification.toString() + " with " + pkgLite.verifiers.length
+ + " optional verifiers");
+ }
+
+ verification.putExtra(PackageManager.EXTRA_VERIFICATION_ID, verificationId);
+
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_INSTALL_FLAGS, installFlags);
+
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_PACKAGE_NAME, pkgLite.packageName);
+
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_VERSION_CODE, pkgLite.versionCode);
+
+ verification.putExtra(
+ PackageManager.EXTRA_VERIFICATION_LONG_VERSION_CODE,
+ pkgLite.getLongVersionCode());
+
+ populateInstallerExtras(verification);
+
+ final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
+ receivers, verificationState);
+
+ DeviceIdleInternal idleController =
+ mInjector.getLocalDeviceIdleController();
+ final long idleDuration = getVerificationTimeout();
+
+ /*
+ * If any sufficient verifiers were listed in the package
+ * manifest, attempt to ask them.
+ */
+ if (sufficientVerifiers != null) {
+ final int n = sufficientVerifiers.size();
+ if (n == 0) {
+ Slog.i(TAG, "Additional verifiers required, but none installed.");
+ ret = PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE;
+ } else {
+ for (int i = 0; i < n; i++) {
+ final ComponentName verifierComponent = sufficientVerifiers.get(i);
+ idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
+ verifierComponent.getPackageName(), idleDuration,
+ verifierUser.getIdentifier(), false, "package verifier");
+
+ final Intent sufficientIntent = new Intent(verification);
+ sufficientIntent.setComponent(verifierComponent);
+ mContext.sendBroadcastAsUser(sufficientIntent, verifierUser);
+ }
+ }
+ }
+
+ final ComponentName requiredVerifierComponent = matchComponentForVerifier(
+ mRequiredVerifierPackage, receivers);
+ if (mRequiredVerifierPackage != null) {
+ /*
+ * Send the intent to the required verification agent,
+ * but only start the verification timeout after the
+ * target BroadcastReceivers have run.
+ */
+ verification.setComponent(requiredVerifierComponent);
+ idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
+ mRequiredVerifierPackage, idleDuration,
+ verifierUser.getIdentifier(), false, "package verifier");
+ mContext.sendOrderedBroadcastAsUser(verification, verifierUser,
+ android.Manifest.permission.PACKAGE_VERIFICATION_AGENT,
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final Message msg = mHandler
+ .obtainMessage(CHECK_PENDING_VERIFICATION);
+ msg.arg1 = verificationId;
+ mHandler.sendMessageDelayed(msg, getVerificationTimeout());
+ }
+ }, null, 0, null, null);
+
+ Trace.asyncTraceBegin(
+ TRACE_TAG_PACKAGE_MANAGER, "verification", verificationId);
+
+ /*
+ * We don't want the copy to proceed until verification
+ * succeeds.
+ */
+ mVerificationCompleted = false;
+ }
+ } else {
+ verificationState.setVerifierResponse(
+ requiredUid, PackageManager.VERIFICATION_ALLOW);
+ }
+ return ret;
+ }
+
+ void populateInstallerExtras(Intent intent) {
+ intent.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
+ installSource.initiatingPackageName);
+
+ if (verificationInfo != null) {
+ if (verificationInfo.originatingUri != null) {
+ intent.putExtra(Intent.EXTRA_ORIGINATING_URI,
+ verificationInfo.originatingUri);
+ }
+ if (verificationInfo.referrer != null) {
+ intent.putExtra(Intent.EXTRA_REFERRER,
+ verificationInfo.referrer);
+ }
+ if (verificationInfo.originatingUid >= 0) {
+ intent.putExtra(Intent.EXTRA_ORIGINATING_UID,
+ verificationInfo.originatingUid);
+ }
+ if (verificationInfo.installerUid >= 0) {
+ intent.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_UID,
+ verificationInfo.installerUid);
+ }
+ }
+ }
+
void setReturnCode(int ret) {
if (mRet == PackageManager.INSTALL_SUCCEEDED) {
// Only update mRet if it was previously INSTALL_SUCCEEDED to
@@ -14325,10 +14530,28 @@ public class PackageManagerService extends IPackageManager.Stub
}
void handleVerificationFinished() {
- mVerificationCompleted = true;
- handleReturnCode();
+ if (!mVerificationCompleted) {
+ mVerificationCompleted = true;
+ if (mIntegrityVerificationCompleted || mRet != INSTALL_SUCCEEDED) {
+ mIntegrityVerificationCompleted = true;
+ handleReturnCode();
+ }
+ // integrity verification still pending.
+ }
}
+ void handleIntegrityVerificationFinished() {
+ if (!mIntegrityVerificationCompleted) {
+ mIntegrityVerificationCompleted = true;
+ if (mVerificationCompleted || mRet != INSTALL_SUCCEEDED) {
+ mVerificationCompleted = true;
+ handleReturnCode();
+ }
+ // verifier still pending
+ }
+ }
+
+
void handleRollbackEnabled() {
// TODO(ruhler) b/112431924: Consider halting the install if we
// couldn't enable rollback.
@@ -14338,7 +14561,8 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
void handleReturnCode() {
- if (mVerificationCompleted && mEnableRollbackCompleted) {
+ if (mVerificationCompleted
+ && mIntegrityVerificationCompleted && mEnableRollbackCompleted) {
if ((installFlags & PackageManager.INSTALL_DRY_RUN) != 0) {
String packageName = "";
try {
@@ -22673,7 +22897,6 @@ public class PackageManagerService extends IPackageManager.Stub
if (ps != null) {
return ps.getCeDataInode(userId);
}
- Slog.e(TAG, "failed to find package " + packageName);
return 0;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index dfffbd6cabef..10e2780863d8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -34,6 +34,7 @@ import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
+import android.content.pm.DataLoaderParams;
import android.content.pm.FeatureInfo;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageInstaller;
@@ -136,7 +137,9 @@ class PackageManagerShellCommand extends ShellCommand {
private final static String ART_PROFILE_SNAPSHOT_DEBUG_LOCATION = "/data/misc/profman/";
private static final int DEFAULT_WAIT_MS = 60 * 1000;
- private static final String PM_SHELL_DATALOADER = "com.android.pm.dataloader";
+ private static final String DATA_LOADER_PACKAGE = "android";
+ private static final String DATA_LOADER_CLASS =
+ "com.android.server.pm.PackageManagerShellCommandDataLoader";
final IPackageManager mInterface;
final IPermissionManager mPermissionManager;
@@ -1159,8 +1162,10 @@ class PackageManagerShellCommand extends ShellCommand {
private int runStreamingInstall() throws RemoteException {
final InstallParams params = makeInstallParams();
- if (TextUtils.isEmpty(params.sessionParams.dataLoaderPackageName)) {
- params.sessionParams.setDataLoaderPackageName(PM_SHELL_DATALOADER);
+ if (params.sessionParams.dataLoaderParams == null) {
+ final DataLoaderParams dataLoaderParams = DataLoaderParams.forStreaming(
+ new ComponentName(DATA_LOADER_PACKAGE, DATA_LOADER_CLASS), "");
+ params.sessionParams.setDataLoaderParams(dataLoaderParams);
}
return doRunInstall(params);
}
@@ -1171,7 +1176,7 @@ class PackageManagerShellCommand extends ShellCommand {
private int doRunInstall(final InstallParams params) throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
- final boolean streaming = !TextUtils.isEmpty(params.sessionParams.dataLoaderPackageName);
+ final boolean streaming = params.sessionParams.dataLoaderParams != null;
ArrayList<String> inPaths = getRemainingArgs();
if (inPaths.isEmpty()) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
new file mode 100644
index 000000000000..1ee9ab8927bb
--- /dev/null
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommandDataLoader.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.annotation.NonNull;
+import android.content.pm.DataLoaderParams;
+import android.content.pm.InstallationFile;
+import android.os.ParcelFileDescriptor;
+import android.service.dataloader.DataLoaderService;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import libcore.io.IoUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+
+/**
+ * Callback data loader for PackageManagerShellCommand installations.
+ */
+public class PackageManagerShellCommandDataLoader extends DataLoaderService {
+ public static final String TAG = "PackageManagerShellCommandDataLoader";
+
+ static class DataLoader implements DataLoaderService.DataLoader {
+ private ParcelFileDescriptor mInFd = null;
+ private FileSystemConnector mConnector = null;
+
+ private static final String STDIN_PATH = "-";
+
+ @Override
+ public boolean onCreate(@NonNull DataLoaderParams dataLoaderParams,
+ @NonNull FileSystemConnector connector) {
+ mConnector = connector;
+ return true;
+ }
+ @Override
+ public boolean onPrepareImage(Collection<InstallationFile> addedFiles,
+ Collection<String> removedFiles) {
+ try {
+ for (InstallationFile fileInfo : addedFiles) {
+ String filePath = new String(fileInfo.getMetadata(), StandardCharsets.UTF_8);
+ if (STDIN_PATH.equals(filePath) || TextUtils.isEmpty(filePath)) {
+ // TODO(b/146080380): add support for STDIN installations.
+ if (mInFd == null) {
+ Slog.e(TAG, "Invalid stdin file descriptor.");
+ return false;
+ }
+ ParcelFileDescriptor inFd = ParcelFileDescriptor.dup(
+ mInFd.getFileDescriptor());
+ mConnector.writeData(fileInfo.getName(), 0, fileInfo.getSize(), inFd);
+ } else {
+ File localFile = new File(filePath);
+ ParcelFileDescriptor incomingFd = null;
+ try {
+ // TODO(b/146080380): open files via callback into shell command.
+ incomingFd = ParcelFileDescriptor.open(localFile,
+ ParcelFileDescriptor.MODE_READ_ONLY);
+ mConnector.writeData(fileInfo.getName(), 0, localFile.length(),
+ incomingFd);
+ } finally {
+ IoUtils.closeQuietly(incomingFd);
+ }
+ }
+ }
+ return true;
+ } catch (IOException e) {
+ return false;
+ }
+ }
+ }
+
+ @Override
+ public DataLoaderService.DataLoader onCreateDataLoader() {
+ return new DataLoader();
+ }
+}
diff --git a/services/core/java/com/android/server/pm/PackageVerificationState.java b/services/core/java/com/android/server/pm/PackageVerificationState.java
index c50bf59f0206..ea7af9031bd0 100644
--- a/services/core/java/com/android/server/pm/PackageVerificationState.java
+++ b/services/core/java/com/android/server/pm/PackageVerificationState.java
@@ -22,18 +22,17 @@ import android.util.SparseBooleanArray;
import com.android.server.pm.PackageManagerService.InstallParams;
/**
- * Tracks the package verification state for a particular package. Each package
- * verification has a required verifier and zero or more sufficient verifiers.
- * Only one of the sufficient verifier list must return affirmative to allow the
- * package to be considered verified. If there are zero sufficient verifiers,
- * then package verification is considered complete.
+ * Tracks the package verification state for a particular package. Each package verification has a
+ * required verifier and zero or more sufficient verifiers. Only one of the sufficient verifier list
+ * must return affirmative to allow the package to be considered verified. If there are zero
+ * sufficient verifiers, then package verification is considered complete.
*/
class PackageVerificationState {
private final InstallParams mParams;
private final SparseBooleanArray mSufficientVerifierUids;
- private final int mRequiredVerifierUid;
+ private int mRequiredVerifierUid;
private boolean mSufficientVerificationComplete;
@@ -45,16 +44,13 @@ class PackageVerificationState {
private boolean mExtendedTimeout;
+ private boolean mIntegrityVerificationComplete;
+
/**
- * Create a new package verification state where {@code requiredVerifierUid}
- * is the user ID for the package that must reply affirmative before things
- * can continue.
- *
- * @param requiredVerifierUid user ID of required package verifier
- * @param args
+ * Create a new package verification state where {@code requiredVerifierUid} is the user ID for
+ * the package that must reply affirmative before things can continue.
*/
- PackageVerificationState(int requiredVerifierUid, InstallParams params) {
- mRequiredVerifierUid = requiredVerifierUid;
+ PackageVerificationState(InstallParams params) {
mParams = params;
mSufficientVerifierUids = new SparseBooleanArray();
mExtendedTimeout = false;
@@ -64,6 +60,11 @@ class PackageVerificationState {
return mParams;
}
+ /** Sets the user ID of the required package verifier. */
+ void setRequiredVerifierUid(int uid) {
+ mRequiredVerifierUid = uid;
+ }
+
/**
* Add a verifier which is added to our sufficient list.
*
@@ -74,8 +75,8 @@ class PackageVerificationState {
}
/**
- * Should be called when a verification is received from an agent so the
- * state of the package verification can be tracked.
+ * Should be called when a verification is received from an agent so the state of the package
+ * verification can be tracked.
*
* @param uid user ID of the verifying agent
* @return {@code true} if the verifying agent actually exists in our list
@@ -114,9 +115,8 @@ class PackageVerificationState {
}
/**
- * Returns whether verification is considered complete. This means that the
- * required verifier and at least one of the sufficient verifiers has
- * returned a positive verification.
+ * Returns whether verification is considered complete. This means that the required verifier
+ * and at least one of the sufficient verifiers has returned a positive verification.
*
* @return {@code true} when verification is considered complete
*/
@@ -133,8 +133,8 @@ class PackageVerificationState {
}
/**
- * Returns whether installation should be allowed. This should only be
- * called after {@link #isVerificationComplete()} returns {@code true}.
+ * Returns whether installation should be allowed. This should only be called after {@link
+ * #isVerificationComplete()} returns {@code true}.
*
* @return {@code true} if installation should be allowed
*/
@@ -150,9 +150,7 @@ class PackageVerificationState {
return true;
}
- /**
- * Extend the timeout for this Package to be verified.
- */
+ /** Extend the timeout for this Package to be verified. */
void extendTimeout() {
if (!mExtendedTimeout) {
mExtendedTimeout = true;
@@ -167,4 +165,16 @@ class PackageVerificationState {
boolean timeoutExtended() {
return mExtendedTimeout;
}
+
+ void setIntegrityVerificationResult(int code) {
+ mIntegrityVerificationComplete = true;
+ }
+
+ boolean isIntegrityVerificationComplete() {
+ return mIntegrityVerificationComplete;
+ }
+
+ boolean areAllVerificationsComplete() {
+ return mIntegrityVerificationComplete && isVerificationComplete();
+ }
}
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 688c34fed44f..6c3eb31d22af 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -22,10 +22,12 @@ import android.apex.ApexInfo;
import android.apex.ApexInfoList;
import android.apex.ApexSessionInfo;
import android.apex.ApexSessionParams;
+import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
@@ -774,6 +776,17 @@ public class StagingManager {
}
}
+ void systemReady() {
+ // Register the receiver of boot completed intent for staging manager.
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context ctx, Intent intent) {
+ mPreRebootVerificationHandler.readyToStart();
+ ctx.unregisterReceiver(this);
+ }
+ }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+ }
+
private static class LocalIntentReceiverAsync {
final Consumer<Intent> mConsumer;
@@ -824,6 +837,9 @@ public class StagingManager {
}
private final class PreRebootVerificationHandler extends Handler {
+ // Hold session ids before handler gets ready to do the verification.
+ private IntArray mPendingSessionIds;
+ private boolean mIsReady;
PreRebootVerificationHandler(Looper looper) {
super(looper);
@@ -876,8 +892,26 @@ public class StagingManager {
}
}
+ // Notify the handler that system is ready, and reschedule the pre-reboot verifications.
+ private synchronized void readyToStart() {
+ mIsReady = true;
+ if (mPendingSessionIds != null) {
+ for (int i = 0; i < mPendingSessionIds.size(); i++) {
+ startPreRebootVerification(mPendingSessionIds.get(i));
+ }
+ mPendingSessionIds = null;
+ }
+ }
+
// Method for starting the pre-reboot verification
- private void startPreRebootVerification(int sessionId) {
+ private synchronized void startPreRebootVerification(int sessionId) {
+ if (!mIsReady) {
+ if (mPendingSessionIds == null) {
+ mPendingSessionIds = new IntArray();
+ }
+ mPendingSessionIds.add(sessionId);
+ return;
+ }
obtainMessage(MSG_PRE_REBOOT_VERIFICATION_START, sessionId, 0).sendToTarget();
}
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 603b01a17e14..6d6ec250e4cc 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -726,10 +726,12 @@ public final class DefaultPermissionGrantPolicy {
userId, STORAGE_PERMISSIONS);
// TextClassifier Service
- String textClassifierPackageName =
- mContext.getPackageManager().getSystemTextClassifierPackageName();
- if (!TextUtils.isEmpty(textClassifierPackageName)) {
- grantPermissionsToSystemPackage(textClassifierPackageName, userId,
+ final String[] packages = mContext.getPackageManager().getSystemTextClassifierPackages();
+ if (packages.length > 0) {
+ // We have a list of supported system TextClassifier package names, the first one
+ // package is the default system TextClassifier service. Grant permissions to default
+ // TextClassifier Service.
+ grantPermissionsToSystemPackage(packages[0], userId,
COARSE_BACKGROUND_LOCATION_PERMISSIONS, CONTACTS_PERMISSIONS);
}
@@ -998,7 +1000,7 @@ public final class DefaultPermissionGrantPolicy {
private void revokeRuntimePermissions(String packageName, Set<String> permissions,
boolean systemFixed, int userId) {
PackageInfo pkg = getSystemPackageInfo(packageName);
- if (ArrayUtils.isEmpty(pkg.requestedPermissions)) {
+ if (pkg == null || ArrayUtils.isEmpty(pkg.requestedPermissions)) {
return;
}
Set<String> revokablePermissions = new ArraySet<>(Arrays.asList(pkg.requestedPermissions));
diff --git a/services/core/java/com/android/server/security/FileIntegrityService.java b/services/core/java/com/android/server/security/FileIntegrityService.java
new file mode 100644
index 000000000000..0bbb17950856
--- /dev/null
+++ b/services/core/java/com/android/server/security/FileIntegrityService.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.security;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.SystemProperties;
+import android.security.Credentials;
+import android.security.IFileIntegrityService;
+import android.security.KeyStore;
+import android.util.Slog;
+
+import com.android.server.SystemService;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * A {@link SystemService} that provides file integrity related operations.
+ * @hide
+ */
+public class FileIntegrityService extends SystemService {
+ private static final String TAG = "FileIntegrityService";
+
+ private static CertificateFactory sCertFactory;
+
+ private Collection<X509Certificate> mTrustedCertificates = new ArrayList<X509Certificate>();
+
+ private final IBinder mService = new IFileIntegrityService.Stub() {
+ @Override
+ public boolean isApkVeritySupported() {
+ return SystemProperties.getInt("ro.apk_verity.mode", 0) == 2;
+ }
+
+ @Override
+ public boolean isAppSourceCertificateTrusted(byte[] certificateBytes) {
+ enforceAnyCallingPermissions(
+ android.Manifest.permission.REQUEST_INSTALL_PACKAGES,
+ android.Manifest.permission.INSTALL_PACKAGES);
+ try {
+ if (!isApkVeritySupported()) {
+ return false;
+ }
+
+ return mTrustedCertificates.contains(toCertificate(certificateBytes));
+ } catch (CertificateException e) {
+ Slog.e(TAG, "Failed to convert the certificate: " + e);
+ return false;
+ }
+ }
+
+ private void enforceAnyCallingPermissions(String ...permissions) {
+ for (String permission : permissions) {
+ if (getContext().checkCallingPermission(permission)
+ == PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ }
+ throw new SecurityException("Insufficient permission");
+ }
+ };
+
+ public FileIntegrityService(final Context context) {
+ super(context);
+ try {
+ sCertFactory = CertificateFactory.getInstance("X.509");
+ } catch (CertificateException e) {
+ Slog.wtf(TAG, "Cannot get an instance of X.509 certificate factory");
+ }
+ }
+
+ @Override
+ public void onStart() {
+ loadAllCertificates();
+ publishBinderService(Context.FILE_INTEGRITY_SERVICE, mService);
+ }
+
+ private void loadAllCertificates() {
+ // A better alternative to load certificates would be to read from .fs-verity kernel
+ // keyring, which fsverity_init loads to during earlier boot time from the same sources
+ // below. But since the read operation from keyring is not provided in kernel, we need to
+ // duplicate the same loading logic here.
+
+ // Load certificates trusted by the device manufacturer.
+ loadCertificatesFromDirectory("/product/etc/security/fsverity");
+
+ // Load certificates trusted by the device owner.
+ loadCertificatesFromKeystore(KeyStore.getInstance());
+ }
+
+ private void loadCertificatesFromDirectory(String path) {
+ try {
+ File[] files = new File(path).listFiles();
+ if (files == null) {
+ return;
+ }
+
+ for (File cert : files) {
+ collectCertificate(Files.readAllBytes(cert.toPath()));
+ }
+ } catch (IOException e) {
+ Slog.wtf(TAG, "Failed to load fs-verity certificate from " + path, e);
+ }
+ }
+
+ private void loadCertificatesFromKeystore(KeyStore keystore) {
+ for (final String alias : keystore.list(Credentials.APP_SOURCE_CERTIFICATE,
+ Process.FSVERITY_CERT_UID)) {
+ byte[] certificateBytes = keystore.get(Credentials.APP_SOURCE_CERTIFICATE + alias,
+ Process.FSVERITY_CERT_UID, false /* suppressKeyNotFoundWarning */);
+ if (certificateBytes == null) {
+ Slog.w(TAG, "The retrieved fs-verity certificate is null, ignored " + alias);
+ continue;
+ }
+ collectCertificate(certificateBytes);
+ }
+ }
+
+ /**
+ * Tries to convert {@code bytes} into an X.509 certificate and store in memory.
+ * Errors need to be surpressed in order fo the next certificates to still be collected.
+ */
+ private void collectCertificate(@Nullable byte[] bytes) {
+ try {
+ mTrustedCertificates.add(toCertificate(bytes));
+ } catch (CertificateException | AssertionError e) {
+ Slog.e(TAG, "Invalid certificate, ignored: " + e);
+ }
+ }
+
+ /**
+ * Converts byte array into one X.509 certificate. If multiple certificate is defined, ignore
+ * the rest. The rational is to make it harder to smuggle.
+ */
+ @NonNull
+ private static X509Certificate toCertificate(@Nullable byte[] bytes)
+ throws CertificateException {
+ Certificate certificate = sCertFactory.generateCertificate(new ByteArrayInputStream(bytes));
+ if (!(certificate instanceof X509Certificate)) {
+ throw new CertificateException("Expected to contain an X.509 certificate");
+ }
+ return (X509Certificate) certificate;
+ }
+}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index fb33f3ad977a..834e924bca59 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -6060,6 +6060,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
void registerRemoteAnimations(RemoteAnimationDefinition definition) {
mRemoteAnimationDefinition = definition;
+ if (definition != null) {
+ definition.linkToDeath(this::unregisterRemoteAnimations);
+ }
+ }
+
+ void unregisterRemoteAnimations() {
+ mRemoteAnimationDefinition = null;
}
RemoteAnimationDefinition getRemoteAnimationDefinition() {
@@ -6301,6 +6308,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
resolveSizeCompatModeConfiguration(newParentConfiguration);
} else {
super.resolveOverrideConfiguration(newParentConfiguration);
+ // We ignore activities' requested orientation in multi-window modes. Task level may
+ // take them into consideration when calculating bounds.
+ if (getParent() != null && getParent().inMultiWindowMode()) {
+ resolvedConfig.orientation = Configuration.ORIENTATION_UNDEFINED;
+ }
applyAspectRatio(resolvedConfig.windowConfiguration.getBounds(),
newParentConfiguration.windowConfiguration.getAppBounds(),
newParentConfiguration.windowConfiguration.getBounds());
diff --git a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
index be3a61383de1..13554244fec2 100644
--- a/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/wm/ActivityStartInterceptor.java
@@ -252,7 +252,8 @@ class ActivityStartInterceptor {
final SuspendDialogInfo dialogInfo = pmi.getSuspendedDialogInfo(suspendedPackage,
suspendingPackage, mUserId);
mIntent = SuspendedAppActivity.createSuspendedAppInterceptIntent(suspendedPackage,
- suspendingPackage, dialogInfo, mUserId);
+ suspendingPackage, dialogInfo, deferCrossProfileAppsAnimationIfNecessary(),
+ mUserId);
mCallingPid = mRealCallingPid;
mCallingUid = mRealCallingUid;
mResolvedType = null;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 45b4818add11..60f051c37377 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4700,6 +4700,24 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
@Override
+ public void unregisterRemoteAnimations(IBinder token) {
+ mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
+ "unregisterRemoteAnimations");
+ synchronized (mGlobalLock) {
+ final ActivityRecord r = ActivityRecord.isInStackLocked(token);
+ if (r == null) {
+ return;
+ }
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ r.unregisterRemoteAnimations();
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+
+ @Override
public void registerRemoteAnimationForNextActivityStart(String packageName,
RemoteAnimationAdapter adapter) {
mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 7dd9790403fc..f778e4d7be0b 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -381,8 +381,8 @@ class RootActivityContainer extends ConfigurationContainer
* @return the {@link DisplayContent} or {@code null} if nothing is found.
*/
DisplayContent getDisplayContent(String uniqueId) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final DisplayContent display = mDisplayContents.get(i);
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayContent display = getChildAt(i);
final boolean isValid = display.mDisplay.isValid();
if (isValid && display.mDisplay.getUniqueId().equals(uniqueId)) {
return display;
@@ -394,8 +394,8 @@ class RootActivityContainer extends ConfigurationContainer
// TODO: Look into consolidating with getDisplayContentOrCreate()
DisplayContent getDisplayContent(int displayId) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final DisplayContent displayContent = mDisplayContents.get(i);
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayContent displayContent = getChildAt(i);
if (displayContent.mDisplayId == displayId) {
return displayContent;
}
@@ -438,16 +438,16 @@ class RootActivityContainer extends ConfigurationContainer
boolean startHomeOnAllDisplays(int userId, String reason) {
boolean homeStarted = false;
- for (int i = mDisplayContents.size() - 1; i >= 0; i--) {
- final int displayId = mDisplayContents.get(i).mDisplayId;
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ final int displayId = getChildAt(i).mDisplayId;
homeStarted |= startHomeOnDisplay(userId, reason, displayId);
}
return homeStarted;
}
void startHomeOnEmptyDisplays(String reason) {
- for (int i = mDisplayContents.size() - 1; i >= 0; i--) {
- final DisplayContent display = mDisplayContents.get(i);
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ final DisplayContent display = getChildAt(i);
if (display.topRunningActivity() == null) {
startHomeOnDisplay(mCurrentUser, reason, display.mDisplayId);
}
@@ -786,8 +786,8 @@ class RootActivityContainer extends ConfigurationContainer
final ArrayList<IBinder> topActivityTokens = new ArrayList<>();
final ActivityStack topFocusedStack = getTopDisplayFocusedStack();
// Traverse all displays.
- for (int i = mDisplayContents.size() - 1; i >= 0; i--) {
- final DisplayContent display = mDisplayContents.get(i);
+ for (int i = getChildCount() - 1; i >= 0; i--) {
+ final DisplayContent display = getChildAt(i);
// Traverse all stacks on a display.
for (int j = display.getStackCount() - 1; j >= 0; --j) {
final ActivityStack stack = display.getStackAt(j);
@@ -808,8 +808,8 @@ class RootActivityContainer extends ConfigurationContainer
}
ActivityStack getTopDisplayFocusedStack() {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final ActivityStack focusedStack = mDisplayContents.get(i).getFocusedStack();
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final ActivityStack focusedStack = getChildAt(i).getFocusedStack();
if (focusedStack != null) {
return focusedStack;
}
@@ -828,8 +828,8 @@ class RootActivityContainer extends ConfigurationContainer
}
// The top focused stack might not have a resumed activity yet - look on all displays in
// focus order.
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final DisplayContent display = mDisplayContents.get(i);
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayContent display = getChildAt(i);
final ActivityRecord resumedActivityOnDisplay = display.getResumedActivity();
if (resumedActivityOnDisplay != null) {
return resumedActivityOnDisplay;
@@ -858,8 +858,8 @@ class RootActivityContainer extends ConfigurationContainer
// previous app if this activity is being hosted by the process that is actually still the
// foreground.
WindowProcessController fgApp = null;
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getStackAt(stackNdx);
if (isTopDisplayFocusedStack(stack)) {
@@ -886,8 +886,8 @@ class RootActivityContainer extends ConfigurationContainer
boolean attachApplication(WindowProcessController app) throws RemoteException {
final String processName = app.mName;
boolean didSomething = false;
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
final ActivityStack stack = display.getFocusedStack();
if (stack == null) {
continue;
@@ -955,8 +955,8 @@ class RootActivityContainer extends ConfigurationContainer
try {
mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate();
// First the front stacks. In case any are not fullscreen and are in front of home.
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
display.ensureActivitiesVisible(starting, configChanges, preserveWindows,
notifyClients);
}
@@ -985,8 +985,8 @@ class RootActivityContainer extends ConfigurationContainer
mCurrentUser = userId;
mStackSupervisor.mStartingUsers.add(uss);
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getStackAt(stackNdx);
stack.switchUser(userId);
@@ -1165,8 +1165,8 @@ class RootActivityContainer extends ConfigurationContainer
}
void executeAppTransitionForAllDisplay() {
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
display.mDisplayContent.executeAppTransition();
}
}
@@ -1199,8 +1199,8 @@ class RootActivityContainer extends ConfigurationContainer
}
}
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
if (display.mDisplayId == preferredDisplayId) {
continue;
}
@@ -1224,8 +1224,8 @@ class RootActivityContainer extends ConfigurationContainer
int finishTopCrashedActivities(WindowProcessController app, String reason) {
Task finishedTask = null;
ActivityStack focusedStack = getTopDisplayFocusedStack();
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
// It is possible that request to finish activity might also remove its task and stack,
// so we need to be careful with indexes in the loop and check child count every time.
for (int stackNdx = 0; stackNdx < display.getStackCount(); ++stackNdx) {
@@ -1256,9 +1256,9 @@ class RootActivityContainer extends ConfigurationContainer
result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
boolean resumedOnDisplay = false;
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ final DisplayContent display = getChildAt(displayNdx);
for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getStackAt(stackNdx);
final ActivityRecord topRunningActivity = stack.topRunningActivity();
@@ -1299,9 +1299,9 @@ class RootActivityContainer extends ConfigurationContainer
}
void applySleepTokens(boolean applyToStacks) {
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
// Set the sleeping state of the display.
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ final DisplayContent display = getChildAt(displayNdx);
final boolean displayShouldSleep = display.shouldSleep();
if (displayShouldSleep == display.isSleeping()) {
continue;
@@ -1355,8 +1355,8 @@ class RootActivityContainer extends ConfigurationContainer
}
protected ActivityStack getStack(int stackId) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final ActivityStack stack = mDisplayContents.get(i).getStack(stackId);
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = getChildAt(i).getStack(stackId);
if (stack != null) {
return stack;
}
@@ -1366,9 +1366,8 @@ class RootActivityContainer extends ConfigurationContainer
/** @see DisplayContent#getStack(int, int) */
ActivityStack getStack(int windowingMode, int activityType) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final ActivityStack stack =
- mDisplayContents.get(i).getStack(windowingMode, activityType);
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = getChildAt(i).getStack(windowingMode, activityType);
if (stack != null) {
return stack;
}
@@ -1452,8 +1451,8 @@ class RootActivityContainer extends ConfigurationContainer
ArrayList<ActivityManager.StackInfo> getAllStackInfos(int displayId) {
ArrayList<ActivityManager.StackInfo> list = new ArrayList<>();
if (displayId == INVALID_DISPLAY) {
- for (int displayNdx = 0; displayNdx < mDisplayContents.size(); ++displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = 0; displayNdx < getChildCount(); ++displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getStackAt(stackNdx);
list.add(getStackInfo(stack));
@@ -1539,8 +1538,8 @@ class RootActivityContainer extends ConfigurationContainer
/** Update lists of UIDs that are present on displays and have access to them. */
void updateUIDsPresentOnDisplay() {
mDisplayAccessUIDs.clear();
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent displayContent = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent displayContent = getChildAt(displayNdx);
// Only bother calculating the whitelist for private displays
if (displayContent.isPrivate()) {
mDisplayAccessUIDs.append(
@@ -1635,8 +1634,8 @@ class RootActivityContainer extends ConfigurationContainer
}
void prepareForShutdown() {
- for (int i = 0; i < mDisplayContents.size(); i++) {
- createSleepToken("shutdown", mDisplayContents.get(i).mDisplayId);
+ for (int i = 0; i < getChildCount(); i++) {
+ createSleepToken("shutdown", getChildAt(i).mDisplayId);
}
}
@@ -1712,8 +1711,8 @@ class RootActivityContainer extends ConfigurationContainer
}
void scheduleDestroyAllActivities(WindowProcessController app, String reason) {
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getStackAt(stackNdx);
stack.scheduleDestroyActivities(app, reason);
@@ -1725,8 +1724,8 @@ class RootActivityContainer extends ConfigurationContainer
// successfully put to sleep.
boolean putStacksToSleep(boolean allowDelay, boolean shuttingDown) {
boolean allSleep = true;
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
// Stacks and activities could be removed while putting activities to sleep if
// the app process was gone. This prevents us getting exception by accessing an
@@ -1796,8 +1795,8 @@ class RootActivityContainer extends ConfigurationContainer
}
boolean hasAwakeDisplay() {
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
if (!display.shouldSleep()) {
return true;
}
@@ -2070,8 +2069,8 @@ class RootActivityContainer extends ConfigurationContainer
}
// Now look through all displays
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final DisplayContent display = mDisplayContents.get(i);
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayContent display = getChildAt(i);
if (display == preferredDisplay) {
// We've already checked this one
continue;
@@ -2097,8 +2096,8 @@ class RootActivityContainer extends ConfigurationContainer
* @return Next valid {@link ActivityStack}, null if not found.
*/
ActivityStack getNextValidLaunchStack(@NonNull ActivityRecord r, int currentFocus) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final DisplayContent display = mDisplayContents.get(i);
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayContent display = getChildAt(i);
if (display.mDisplayId == currentFocus) {
continue;
}
@@ -2113,8 +2112,8 @@ class RootActivityContainer extends ConfigurationContainer
boolean handleAppDied(WindowProcessController app) {
boolean hasVisibleActivities = false;
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getStackAt(stackNdx);
hasVisibleActivities |= stack.handleAppDiedLocked(app);
@@ -2226,8 +2225,8 @@ class RootActivityContainer extends ConfigurationContainer
}
void finishVoiceTask(IVoiceInteractionSession session) {
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
final int numStacks = display.getStackCount();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
final ActivityStack stack = display.getStackAt(stackNdx);
@@ -2241,20 +2240,20 @@ class RootActivityContainer extends ConfigurationContainer
* ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
*/
void removeStacksInWindowingModes(int... windowingModes) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- mDisplayContents.get(i).removeStacksInWindowingModes(windowingModes);
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ getChildAt(i).removeStacksInWindowingModes(windowingModes);
}
}
void removeStacksWithActivityTypes(int... activityTypes) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- mDisplayContents.get(i).removeStacksWithActivityTypes(activityTypes);
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ getChildAt(i).removeStacksWithActivityTypes(activityTypes);
}
}
ActivityRecord topRunningActivity() {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final ActivityRecord topActivity = mDisplayContents.get(i).topRunningActivity();
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final ActivityRecord topActivity = getChildAt(i).topRunningActivity();
if (topActivity != null) {
return topActivity;
}
@@ -2263,9 +2262,9 @@ class RootActivityContainer extends ConfigurationContainer
}
boolean allResumedActivitiesIdle() {
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
// TODO(b/117135575): Check resumed activities on all visible stacks.
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ final DisplayContent display = getChildAt(displayNdx);
if (display.isSleeping()) {
// No resumed activities while display is sleeping.
continue;
@@ -2293,8 +2292,8 @@ class RootActivityContainer extends ConfigurationContainer
boolean allResumedActivitiesVisible() {
boolean foundResumed = false;
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getStackAt(stackNdx);
final ActivityRecord r = stack.getResumedActivity();
@@ -2311,8 +2310,8 @@ class RootActivityContainer extends ConfigurationContainer
boolean allPausedActivitiesComplete() {
boolean pausing = true;
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getStackAt(stackNdx);
final ActivityRecord r = stack.mPausingActivity;
@@ -2376,8 +2375,8 @@ class RootActivityContainer extends ConfigurationContainer
}
void cancelInitializingActivities() {
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ final DisplayContent display = getChildAt(displayNdx);
for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getStackAt(stackNdx);
stack.cancelInitializingActivities();
@@ -2462,9 +2461,9 @@ class RootActivityContainer extends ConfigurationContainer
}
ActivityRecord isInAnyStack(IBinder token) {
- int numDisplays = mDisplayContents.size();
+ int numDisplays = getChildCount();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ final DisplayContent display = getChildAt(displayNdx);
for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getStackAt(stackNdx);
final ActivityRecord r = stack.isInStackLocked(token);
@@ -2498,8 +2497,8 @@ class RootActivityContainer extends ConfigurationContainer
// activity on all displays, or if there are no resumed activities in the system.
boolean noResumedActivities = true;
boolean allFocusedProcessesDiffer = true;
- for (int displayNdx = 0; displayNdx < mDisplayContents.size(); ++displayNdx) {
- final DisplayContent displayContent = mDisplayContents.get(displayNdx);
+ for (int displayNdx = 0; displayNdx < getChildCount(); ++displayNdx) {
+ final DisplayContent displayContent = getChildAt(displayNdx);
final ActivityRecord resumedActivity = displayContent.getResumedActivity();
final WindowProcessController resumedActivityProcess =
resumedActivity == null ? null : resumedActivity.app;
@@ -2545,9 +2544,9 @@ class RootActivityContainer extends ConfigurationContainer
return getTopDisplayFocusedStack().getDumpActivitiesLocked(name);
} else {
ArrayList<ActivityRecord> activities = new ArrayList<>();
- int numDisplays = mDisplayContents.size();
+ int numDisplays = getChildCount();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final DisplayContent display = mDisplayContents.get(displayNdx);
+ final DisplayContent display = getChildAt(displayNdx);
for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getStackAt(stackNdx);
if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
@@ -2562,8 +2561,8 @@ class RootActivityContainer extends ConfigurationContainer
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix);
pw.println("topDisplayFocusedStack=" + getTopDisplayFocusedStack());
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final DisplayContent display = mDisplayContents.get(i);
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayContent display = getChildAt(i);
display.dump(pw, prefix, true /* dumpAll */);
}
}
@@ -2574,17 +2573,17 @@ class RootActivityContainer extends ConfigurationContainer
*/
void dumpDisplayConfigs(PrintWriter pw, String prefix) {
pw.print(prefix); pw.println("Display override configurations:");
- final int displayCount = mDisplayContents.size();
+ final int displayCount = getChildCount();
for (int i = 0; i < displayCount; i++) {
- final DisplayContent displayContent = mDisplayContents.get(i);
+ final DisplayContent displayContent = getChildAt(i);
pw.print(prefix); pw.print(" "); pw.print(displayContent.mDisplayId); pw.print(": ");
pw.println(displayContent.getRequestedOverrideConfiguration());
}
}
public void dumpDisplays(PrintWriter pw) {
- for (int i = mDisplayContents.size() - 1; i >= 0; --i) {
- final DisplayContent display = mDisplayContents.get(i);
+ for (int i = getChildCount() - 1; i >= 0; --i) {
+ final DisplayContent display = getChildAt(i);
pw.print("[id:" + display.mDisplayId + " stacks:");
display.dumpStacks(pw);
pw.print("]");
@@ -2595,13 +2594,12 @@ class RootActivityContainer extends ConfigurationContainer
String dumpPackage) {
boolean printed = false;
boolean needSep = false;
- for (int displayNdx = mDisplayContents.size() - 1; displayNdx >= 0; --displayNdx) {
- DisplayContent displayContent = mDisplayContents.get(displayNdx);
+ for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
+ DisplayContent displayContent = getChildAt(displayNdx);
pw.print("Display #"); pw.print(displayContent.mDisplayId);
pw.println(" (activities from top to bottom):");
- final DisplayContent display = mDisplayContents.get(displayNdx);
- for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = display.getStackAt(stackNdx);
+ for (int stackNdx = displayContent.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = displayContent.getStackAt(stackNdx);
pw.println();
printed = stack.dump(fd, pw, dumpAll, dumpClient, dumpPackage, needSep);
needSep = printed;
@@ -2627,8 +2625,8 @@ class RootActivityContainer extends ConfigurationContainer
@WindowTraceLogLevel int logLevel) {
final long token = proto.start(fieldId);
super.dumpDebug(proto, CONFIGURATION_CONTAINER, logLevel);
- for (int displayNdx = 0; displayNdx < mDisplayContents.size(); ++displayNdx) {
- final DisplayContent displayContent = mDisplayContents.get(displayNdx);
+ for (int displayNdx = 0; displayNdx < getChildCount(); ++displayNdx) {
+ final DisplayContent displayContent = getChildAt(displayNdx);
displayContent.dumpDebug(proto, DISPLAYS, logLevel);
}
mStackSupervisor.getKeyguardController().dumpDebug(proto, KEYGUARD_CONTROLLER);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index fd95ac500370..45c012e6cd86 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1881,7 +1881,10 @@ class Task extends WindowContainer<WindowContainer> {
if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED
|| inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
- if (insideParentBounds && mStack != null) {
+ if (insideParentBounds && WindowConfiguration.isFloating(windowingMode)) {
+ mTmpNonDecorBounds.set(mTmpFullBounds);
+ mTmpStableBounds.set(mTmpFullBounds);
+ } else if (insideParentBounds && mStack != null) {
final DisplayInfo di = new DisplayInfo();
mStack.getDisplay().mDisplay.getDisplayInfo(di);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 3182a7243e7f..e4744dba85d3 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -179,7 +179,7 @@ class TaskSnapshotController {
}
void snapshotTasks(ArraySet<Task> tasks) {
- snapshotTasks(mTmpTasks, false /* allowSnapshotHome */);
+ snapshotTasks(tasks, false /* allowSnapshotHome */);
}
private void snapshotTasks(ArraySet<Task> tasks, boolean allowSnapshotHome) {
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 1313eebb446b..3039d69212f8 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -2368,43 +2368,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
final Region region = inputWindowHandle.touchableRegion;
setTouchableRegionCropIfNeeded(inputWindowHandle);
- if (modal && mActivityRecord != null) {
- // Limit the outer touch to the activity stack region.
+ if (modal) {
flags |= FLAG_NOT_TOUCH_MODAL;
- // If the inner bounds of letterbox is available, then it will be used as the touchable
- // region so it won't cover the touchable letterbox and the touch events can slip to
- // activity from letterbox.
- mActivityRecord.getLetterboxInnerBounds(mTmpRect);
- if (mTmpRect.isEmpty()) {
- // If this is a modal window we need to dismiss it if it's not full screen and the
- // touch happens outside of the frame that displays the content. This means we need
- // to intercept touches outside of that window. The dim layer user associated with
- // the window (task or stack) will give us the good bounds, as they would be used to
- // display the dim layer.
- final Task task = getTask();
- if (task != null) {
- task.getDimBounds(mTmpRect);
- } else {
- getStack().getDimBounds(mTmpRect);
- }
- }
- if (inFreeformWindowingMode()) {
- // For freeform windows we the touch region to include the whole surface for the
- // shadows.
- final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
- final int delta = WindowManagerService.dipToPixel(
- RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics);
- mTmpRect.inset(-delta, -delta);
- }
- region.set(mTmpRect);
- cropRegionToStackBoundsIfNeeded(region);
- subtractTouchExcludeRegionIfNeeded(region);
- } else if (modal && mTapExcludeRegionHolder != null) {
- final Region touchExcludeRegion = Region.obtain();
- amendTapExcludeRegion(touchExcludeRegion);
- if (!touchExcludeRegion.isEmpty()) {
- // Remove touch modal because there are some areas that cannot be touched.
- flags |= FLAG_NOT_TOUCH_MODAL;
+ if (mActivityRecord != null) {
+ // Limit the outer touch to the activity stack region.
+ updateRegionForModalActivityWindow(region);
+ } else {
// Give it a large touchable region at first because it was touch modal. The window
// might be moved on the display, so the touchable region should be large enough to
// ensure it covers the whole display, no matter where it is moved.
@@ -2412,15 +2381,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
final int dw = mTmpRect.width();
final int dh = mTmpRect.height();
region.set(-dw, -dh, dw + dw, dh + dh);
- // Subtract the area that cannot be touched.
- region.op(touchExcludeRegion, Region.Op.DIFFERENCE);
- inputWindowHandle.setTouchableRegionCrop(null);
}
- touchExcludeRegion.recycle();
+ subtractTouchExcludeRegionIfNeeded(region);
} else {
- // Not modal or full screen modal
+ // Not modal
getTouchableRegion(region);
}
+
// Translate to surface based coordinates.
region.translate(-mWindowFrames.mFrame.left, -mWindowFrames.mFrame.top);
@@ -2436,6 +2403,41 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return flags;
}
+ /**
+ * Updates the region for a window in an Activity that was a touch modal. This will limit
+ * the outer touch to the activity stack region.
+ * @param outRegion The region to update.
+ */
+ private void updateRegionForModalActivityWindow(Region outRegion) {
+ // If the inner bounds of letterbox is available, then it will be used as the
+ // touchable region so it won't cover the touchable letterbox and the touch
+ // events can slip to activity from letterbox.
+ mActivityRecord.getLetterboxInnerBounds(mTmpRect);
+ if (mTmpRect.isEmpty()) {
+ // If this is a modal window we need to dismiss it if it's not full screen
+ // and the touch happens outside of the frame that displays the content. This
+ // means we need to intercept touches outside of that window. The dim layer
+ // user associated with the window (task or stack) will give us the good
+ // bounds, as they would be used to display the dim layer.
+ final Task task = getTask();
+ if (task != null) {
+ task.getDimBounds(mTmpRect);
+ } else {
+ getStack().getDimBounds(mTmpRect);
+ }
+ }
+ if (inFreeformWindowingMode()) {
+ // For freeform windows, we need the touch region to include the whole
+ // surface for the shadows.
+ final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
+ final int delta = WindowManagerService.dipToPixel(
+ RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics);
+ mTmpRect.inset(-delta, -delta);
+ }
+ outRegion.set(mTmpRect);
+ cropRegionToStackBoundsIfNeeded(outRegion);
+ }
+
void checkPolicyVisibilityChange() {
if (isLegacyPolicyVisibility() != mLegacyPolicyVisibilityAfterAnim) {
if (DEBUG_VISIBILITY) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index eda69a99a3a3..153681677d78 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -84,6 +84,7 @@ import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
import static android.provider.Telephony.Carriers.DPC_URI;
import static android.provider.Telephony.Carriers.ENFORCE_KEY;
import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
+import static android.security.keystore.AttestationUtils.USE_INDIVIDUAL_ATTESTATION;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.PROVISIONING_ENTRY_POINT_ADB;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
@@ -5825,7 +5826,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
idTypeToAttestationFlag.put(ID_TYPE_IMEI, AttestationUtils.ID_TYPE_IMEI);
idTypeToAttestationFlag.put(ID_TYPE_MEID, AttestationUtils.ID_TYPE_MEID);
idTypeToAttestationFlag.put(
- ID_TYPE_INDIVIDUAL_ATTESTATION, AttestationUtils.USE_INDIVIDUAL_ATTESTATION);
+ ID_TYPE_INDIVIDUAL_ATTESTATION, USE_INDIVIDUAL_ATTESTATION);
int numFlagsSet = Integer.bitCount(idAttestationFlags);
// No flags are set - return null to indicate no device ID attestation information should
@@ -5865,6 +5866,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (deviceIdAttestationRequired && attestationUtilsFlags.length > 0) {
enforceCallerCanRequestDeviceIdAttestation(who, callerPackage, callingUid);
+ enforceIndividualAttestationSupportedIfRequested(attestationUtilsFlags);
} else {
enforceCanManageScope(who, callerPackage, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER,
DELEGATION_CERT_INSTALL);
@@ -5959,6 +5961,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
+ private void enforceIndividualAttestationSupportedIfRequested(int[] attestationUtilsFlags) {
+ for (int attestationFlag : attestationUtilsFlags) {
+ if (attestationFlag == USE_INDIVIDUAL_ATTESTATION
+ && !mInjector.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_DEVICE_UNIQUE_ATTESTATION)) {
+ throw new UnsupportedOperationException("Device Individual attestation is not "
+ + "supported on this device.");
+ }
+ }
+ }
+
@Override
public boolean setKeyPairCertificate(ComponentName who, String callerPackage, String alias,
byte[] cert, byte[] chain, boolean isUserSelectable) {
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index c43328fcdf9d..afce260ed41e 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -351,10 +351,13 @@ StorageId IncrementalService::createStorage(std::string_view mountPoint,
{
metadata::Mount m;
m.mutable_storage()->set_id(ifs->mountId);
+ m.mutable_loader()->set_type((int)dataLoaderParams.type);
m.mutable_loader()->set_package_name(dataLoaderParams.packageName);
- m.mutable_loader()->set_arguments(dataLoaderParams.staticArgs);
+ m.mutable_loader()->set_class_name(dataLoaderParams.className);
+ m.mutable_loader()->set_arguments(dataLoaderParams.arguments);
const auto metadata = m.SerializeAsString();
m.mutable_loader()->release_arguments();
+ m.mutable_loader()->release_class_name();
m.mutable_loader()->release_package_name();
if (auto err = mIncFs->makeFile(ifs->control, constants().infoMdName, INCFS_ROOT_INODE, 0,
metadata);
@@ -794,7 +797,7 @@ bool IncrementalService::startLoading(StorageId storage) const {
}
bool started = false;
std::unique_lock l(ifs->lock);
- if (ifs->dataLoaderStatus != IDataLoaderStatusListener::DATA_LOADER_READY) {
+ if (ifs->dataLoaderStatus != IDataLoaderStatusListener::DATA_LOADER_CREATED) {
if (ifs->dataLoaderReady.wait_for(l, Seconds(5)) == std::cv_status::timeout) {
LOG(ERROR) << "Timeout waiting for data loader to be ready";
return false;
@@ -917,8 +920,10 @@ bool IncrementalService::mountExistingImage(std::string_view root, std::string_v
}
DataLoaderParamsParcel dlParams;
+ dlParams.type = (DataLoaderType)m.loader().type();
dlParams.packageName = std::move(*m.mutable_loader()->mutable_package_name());
- dlParams.staticArgs = std::move(*m.mutable_loader()->mutable_arguments());
+ dlParams.className = std::move(*m.mutable_loader()->mutable_class_name());
+ dlParams.arguments = std::move(*m.mutable_loader()->mutable_arguments());
if (!prepareDataLoader(*ifs, &dlParams)) {
deleteStorage(*ifs);
return false;
@@ -955,7 +960,7 @@ bool IncrementalService::prepareDataLoader(IncrementalService::IncFsMount& ifs,
}
std::unique_lock l(ifs.lock);
- if (ifs.dataLoaderStatus == IDataLoaderStatusListener::DATA_LOADER_READY) {
+ if (ifs.dataLoaderStatus == IDataLoaderStatusListener::DATA_LOADER_CREATED) {
LOG(INFO) << "Skipped data loader preparation because it already exists";
return true;
}
@@ -1008,20 +1013,20 @@ binder::Status IncrementalService::IncrementalDataLoaderListener::onStatusChange
}
break;
}
- case IDataLoaderStatusListener::DATA_LOADER_READY: {
+ case IDataLoaderStatusListener::DATA_LOADER_CONNECTION_OK: {
+ ifs->dataLoaderStatus = IDataLoaderStatusListener::DATA_LOADER_STARTED;
+ break;
+ }
+ case IDataLoaderStatusListener::DATA_LOADER_CREATED: {
ifs->dataLoaderReady.notify_one();
break;
}
- case IDataLoaderStatusListener::DATA_LOADER_NOT_READY: {
+ case IDataLoaderStatusListener::DATA_LOADER_DESTROYED: {
ifs->dataLoaderStatus = IDataLoaderStatusListener::DATA_LOADER_STOPPED;
incrementalService.deleteStorageLocked(*ifs, std::move(l));
break;
}
- case IDataLoaderStatusListener::DATA_LOADER_RUNNING: {
- break;
- }
- case IDataLoaderStatusListener::DATA_LOADER_CONNECTION_OK: {
- ifs->dataLoaderStatus = IDataLoaderStatusListener::DATA_LOADER_RUNNING;
+ case IDataLoaderStatusListener::DATA_LOADER_STARTED: {
break;
}
case IDataLoaderStatusListener::DATA_LOADER_STOPPED: {
diff --git a/services/incremental/Metadata.proto b/services/incremental/Metadata.proto
index 0ff3c3234ffa..79f1bf8d29a9 100644
--- a/services/incremental/Metadata.proto
+++ b/services/incremental/Metadata.proto
@@ -10,7 +10,9 @@ message BindPoint {
message DataLoader {
string package_name = 1;
+ string class_name = 3;
string arguments = 2;
+ int32 type = 4;
}
message Storage {
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index f6b123d68212..ca1e1a972047 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -138,10 +138,10 @@ public:
.WillByDefault(Invoke(this, &MockIncrementalManager::startDataLoaderOk));
}
void setDataLoaderStatusNotReady() {
- mListener->onStatusChanged(mId, IDataLoaderStatusListener::DATA_LOADER_NOT_READY);
+ mListener->onStatusChanged(mId, IDataLoaderStatusListener::DATA_LOADER_DESTROYED);
}
void setDataLoaderStatusReady() {
- mListener->onStatusChanged(mId, IDataLoaderStatusListener::DATA_LOADER_READY);
+ mListener->onStatusChanged(mId, IDataLoaderStatusListener::DATA_LOADER_CREATED);
}
private:
@@ -235,7 +235,7 @@ public:
MockServiceManager serviceManager = MockServiceManager(mVold, mIncrementalManager, mIncFs);
mIncrementalService = std::make_unique<IncrementalService>(serviceManager, mRootDir.path);
mDataLoaderParcel.packageName = "com.test";
- mDataLoaderParcel.staticArgs = "uri";
+ mDataLoaderParcel.arguments = "uri";
mIncrementalService->onSystemReady();
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 50ae3761b255..cfe131899987 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -146,6 +146,7 @@ import com.android.server.recoverysystem.RecoverySystemService;
import com.android.server.restrictions.RestrictionsManagerService;
import com.android.server.role.RoleManagerService;
import com.android.server.rollback.RollbackManagerService;
+import com.android.server.security.FileIntegrityService;
import com.android.server.security.KeyAttestationApplicationIdProviderService;
import com.android.server.security.KeyChainSystemService;
import com.android.server.signedconfig.SignedConfigService;
@@ -673,6 +674,13 @@ public final class SystemServer {
AppCompatCallbacks.install(new long[0]);
t.traceEnd();
+ // FileIntegrityService responds to requests from apps and the system. It needs to run after
+ // the source (i.e. keystore) is ready, and before the apps (or the first customer in the
+ // system) run.
+ t.traceBegin("StartFileIntegrityService");
+ mSystemServiceManager.startService(FileIntegrityService.class);
+ t.traceEnd();
+
// Wait for installd to finish starting up so that it has a chance to
// create critical directories such as /data/user with the appropriate
// permissions. We need this to complete before we initialize other services.
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 05b655af65ed..9e1ddb1f8a80 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -217,9 +217,8 @@ public class LocalDisplayAdapterTest {
doReturn(new int[]{
0
}).when(() -> SurfaceControl.getDisplayColorModes(config.displayToken));
- doReturn(new int[]{
- 0
- }).when(() -> SurfaceControl.getAllowedDisplayConfigs(config.displayToken));
+ doReturn(new SurfaceControl.DesiredDisplayConfigSpecs(0, 60.f, 60.f))
+ .when(() -> SurfaceControl.getDesiredDisplayConfigSpecs(config.displayToken));
}
private void updateAvailableDisplays() {
diff --git a/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/test.apk b/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/test.apk
new file mode 100644
index 000000000000..6345c986efc2
--- /dev/null
+++ b/services/tests/servicestests/assets/AppIntegrityManagerServiceImplTest/test.apk
Binary files differ
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index 269f9180d8a6..ebca240819e8 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -78,10 +78,9 @@ public class DisplayModeDirectorTest {
int displayId = 0;
// With no votes present, DisplayModeDirector should allow any refresh rate.
- assertEquals(new DisplayModeDirector.DesiredDisplayConfigSpecs(/*defaultModeId=*/60,
- new DisplayModeDirector.RefreshRateRange(0f, Float.POSITIVE_INFINITY),
- intRange(60, 90)),
- createDisplayModeDirectorWithDisplayFpsRange(60, 90).getDesiredDisplayConfigSpecs(
+ assertEquals(new DisplayModeDirector.DesiredDisplayModeSpecs(/*defaultModeId=*/60,
+ new DisplayModeDirector.RefreshRateRange(0f, Float.POSITIVE_INFINITY)),
+ createDisplayModeDirectorWithDisplayFpsRange(60, 90).getDesiredDisplayModeSpecs(
displayId));
int numPriorities =
@@ -105,11 +104,10 @@ public class DisplayModeDirectorTest {
priority, DisplayModeDirector.Vote.forRefreshRates(minFps + i, maxFps - i));
director.injectVotesByDisplay(votesByDisplay);
assertEquals(
- new DisplayModeDirector.DesiredDisplayConfigSpecs(
+ new DisplayModeDirector.DesiredDisplayModeSpecs(
/*defaultModeId=*/minFps + i,
- new DisplayModeDirector.RefreshRateRange(minFps + i, maxFps - i),
- intRange(minFps + i, maxFps - i)),
- director.getDesiredDisplayConfigSpecs(displayId));
+ new DisplayModeDirector.RefreshRateRange(minFps + i, maxFps - i)),
+ director.getDesiredDisplayModeSpecs(displayId));
}
}
@@ -128,10 +126,9 @@ public class DisplayModeDirectorTest {
votes.put(DisplayModeDirector.Vote.MIN_PRIORITY,
DisplayModeDirector.Vote.forRefreshRates(70, 80));
director.injectVotesByDisplay(votesByDisplay);
- assertEquals(
- new DisplayModeDirector.DesiredDisplayConfigSpecs(/*defaultModeId=*/70,
- new DisplayModeDirector.RefreshRateRange(70, 80), intRange(70, 80)),
- director.getDesiredDisplayConfigSpecs(displayId));
+ assertEquals(new DisplayModeDirector.DesiredDisplayModeSpecs(/*defaultModeId=*/70,
+ new DisplayModeDirector.RefreshRateRange(70, 80)),
+ director.getDesiredDisplayModeSpecs(displayId));
}
}
}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
index 37ff06a18492..a2376a6bef1c 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
@@ -16,57 +16,380 @@
package com.android.server.integrity;
+import static android.content.integrity.AppIntegrityManager.EXTRA_STATUS;
+import static android.content.integrity.AppIntegrityManager.STATUS_FAILURE;
+import static android.content.integrity.AppIntegrityManager.STATUS_SUCCESS;
import static android.content.pm.PackageManager.EXTRA_VERIFICATION_ID;
+import static android.content.pm.PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE;
+import static android.content.pm.PackageManager.EXTRA_VERIFICATION_INSTALLER_UID;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.mockito.internal.verification.VerificationModeFactory.times;
+import android.content.BroadcastReceiver;
+import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.IntentSender;
+import android.content.integrity.AppInstallMetadata;
+import android.content.integrity.AtomicFormula;
+import android.content.integrity.Rule;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
+import android.content.pm.ParceledListSlice;
+import android.content.res.Resources;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Message;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.R;
import com.android.server.LocalServices;
+import com.android.server.integrity.engine.RuleEvaluationEngine;
+import com.android.server.integrity.model.IntegrityCheckResult;
+import com.android.server.testutils.TestUtils;
+import org.junit.After;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/** Unit test for {@link com.android.server.integrity.AppIntegrityManagerServiceImpl} */
@RunWith(AndroidJUnit4.class)
public class AppIntegrityManagerServiceImplTest {
+ private static final String TEST_DIR = "AppIntegrityManagerServiceImplTest";
+
+ private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
+ private static final String VERSION = "version";
+ private static final String TEST_FRAMEWORK_PACKAGE = "com.android.frameworks.servicestests";
- @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+ private static final String PACKAGE_NAME = "com.test.app";
+ private static final int VERSION_CODE = 100;
+ private static final String INSTALLER = TEST_FRAMEWORK_PACKAGE;
+ // These are obtained by running the test and checking logcat.
+ private static final String APP_CERT =
+ "949ADC6CB92FF09E3784D6E9504F26F9BEAC06E60D881D55A6A81160F9CD6FD1";
+ private static final String INSTALLER_CERT =
+ "301AA3CB081134501C45F1422ABC66C24224FD5DED5FDC8F17E697176FD866AA";
+ // We use SHA256 for package names longer than 32 characters.
+ private static final String INSTALLER_SHA256 =
+ "786933C28839603EB48C50B2A688DC6BE52C833627CB2731FF8466A2AE9F94CD";
+
+ @org.junit.Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
@Mock PackageManagerInternal mPackageManagerInternal;
+ @Mock Context mMockContext;
+ @Mock Resources mMockResources;
+ @Mock RuleEvaluationEngine mRuleEvaluationEngine;
+ @Mock IntegrityFileManager mIntegrityFileManager;
+ @Mock Handler mHandler;
+
+ private PackageManager mSpyPackageManager;
+ private File mTestApk;
+ private final Context mRealContext = InstrumentationRegistry.getTargetContext();
// under test
private AppIntegrityManagerServiceImpl mService;
@Before
- public void setup() {
+ public void setup() throws Exception {
+ mTestApk = File.createTempFile("TestApk", /* suffix= */ null);
+ mTestApk.deleteOnExit();
+ try (InputStream inputStream = mRealContext.getAssets().open(TEST_DIR + "/test.apk")) {
+ Files.copy(inputStream, mTestApk.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ }
+
+ mService =
+ new AppIntegrityManagerServiceImpl(
+ mMockContext,
+ mPackageManagerInternal,
+ mRuleEvaluationEngine,
+ mIntegrityFileManager,
+ mHandler);
+
+ mSpyPackageManager = spy(mRealContext.getPackageManager());
+ // setup mocks to prevent NPE
+ when(mMockContext.getPackageManager()).thenReturn(mSpyPackageManager);
+ when(mMockContext.getResources()).thenReturn(mMockResources);
+ when(mMockResources.getStringArray(anyInt())).thenReturn(new String[] {});
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mTestApk.delete();
+ }
+
+ // This is not a test of the class, but more of a safeguard that we don't block any install in
+ // the default case. This is needed because we don't have any emergency kill switch to disable
+ // this component.
+ @Test
+ public void default_allow() throws Exception {
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
LocalServices.addService(PackageManagerInternal.class, mPackageManagerInternal);
+ mService = AppIntegrityManagerServiceImpl.create(mMockContext);
+ ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mMockContext, times(2))
+ .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
+ Intent intent = makeVerificationIntent();
+
+ broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
+
+ // Since we are not mocking handler in this case, we must wait.
+ // 2 seconds should be a sensible timeout.
+ Thread.sleep(2000);
+ verify(mPackageManagerInternal)
+ .setIntegrityVerificationResult(
+ 1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ }
+
+ @Test
+ public void updateRuleSet_notAuthorized() throws Exception {
+ makeUsSystemApp();
+ Rule rule =
+ new Rule(
+ new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+ Rule.DENY);
+ TestUtils.assertExpectException(
+ SecurityException.class,
+ "Only system packages specified in config_integrityRuleProviderPackages are"
+ + " allowed to call this method.",
+ () ->
+ mService.updateRuleSet(
+ VERSION,
+ new ParceledListSlice<>(Arrays.asList(rule)),
+ /* statusReceiver= */ null));
+ }
+
+ @Test
+ public void updateRuleSet_notSystemApp() throws Exception {
+ whitelistUsAsRuleProvider();
+ Rule rule =
+ new Rule(
+ new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+ Rule.DENY);
+ TestUtils.assertExpectException(
+ SecurityException.class,
+ "Only system packages specified in config_integrityRuleProviderPackages are"
+ + " allowed to call this method.",
+ () ->
+ mService.updateRuleSet(
+ VERSION,
+ new ParceledListSlice<>(Arrays.asList(rule)),
+ /* statusReceiver= */ null));
+ }
+
+ @Test
+ public void updateRuleSet_authorized() throws Exception {
+ whitelistUsAsRuleProvider();
+ makeUsSystemApp();
+ Rule rule =
+ new Rule(
+ new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
+ Rule.DENY);
+
+ // no SecurityException
+ mService.updateRuleSet(
+ VERSION, new ParceledListSlice<>(Arrays.asList(rule)), mock(IntentSender.class));
+ }
+
+ @Test
+ public void updateRuleSet_correctMethodCall() throws Exception {
+ whitelistUsAsRuleProvider();
+ makeUsSystemApp();
+ IntentSender mockReceiver = mock(IntentSender.class);
+ List<Rule> rules =
+ Arrays.asList(
+ new Rule(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ PACKAGE_NAME,
+ /* isHashedValue= */ false),
+ Rule.DENY));
+
+ mService.updateRuleSet(VERSION, new ParceledListSlice<>(rules), mockReceiver);
+ runJobInHandler();
- mService = new AppIntegrityManagerServiceImpl(InstrumentationRegistry.getContext());
+ verify(mIntegrityFileManager).writeRules(VERSION, TEST_FRAMEWORK_PACKAGE, rules);
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mockReceiver).sendIntent(any(), anyInt(), intentCaptor.capture(), any(), any());
+ assertEquals(STATUS_SUCCESS, intentCaptor.getValue().getIntExtra(EXTRA_STATUS, -1));
}
@Test
- public void integrityVerification_allow() {
- int verificationId = 2;
- Intent integrityVerificationIntent = new Intent();
- integrityVerificationIntent.setAction(Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
- integrityVerificationIntent.putExtra(EXTRA_VERIFICATION_ID, verificationId);
+ public void updateRuleSet_fail() throws Exception {
+ whitelistUsAsRuleProvider();
+ makeUsSystemApp();
+ doThrow(new IOException()).when(mIntegrityFileManager).writeRules(any(), any(), any());
+ IntentSender mockReceiver = mock(IntentSender.class);
+ List<Rule> rules =
+ Arrays.asList(
+ new Rule(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ PACKAGE_NAME,
+ /* isHashedValue= */ false),
+ Rule.DENY));
- // We cannot send the broadcast using the context since it is a protected broadcast and
- // we will get a security exception.
- mService.handleIntegrityVerification(integrityVerificationIntent);
+ mService.updateRuleSet(VERSION, new ParceledListSlice<>(rules), mockReceiver);
+ runJobInHandler();
+
+ verify(mIntegrityFileManager).writeRules(VERSION, TEST_FRAMEWORK_PACKAGE, rules);
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mockReceiver).sendIntent(any(), anyInt(), intentCaptor.capture(), any(), any());
+ assertEquals(STATUS_FAILURE, intentCaptor.getValue().getIntExtra(EXTRA_STATUS, -1));
+ }
+
+ @Test
+ public void broadcastReceiverRegistration() throws Exception {
+ ArgumentCaptor<IntentFilter> intentFilterCaptor =
+ ArgumentCaptor.forClass(IntentFilter.class);
+
+ verify(mMockContext).registerReceiver(any(), intentFilterCaptor.capture(), any(), any());
+ assertEquals(1, intentFilterCaptor.getValue().countActions());
+ assertEquals(
+ Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION,
+ intentFilterCaptor.getValue().getAction(0));
+ assertEquals(1, intentFilterCaptor.getValue().countDataTypes());
+ assertEquals(PACKAGE_MIME_TYPE, intentFilterCaptor.getValue().getDataType(0));
+ }
+
+ @Test
+ public void handleBroadcast_correctArgs() throws Exception {
+ ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mMockContext)
+ .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
+ Intent intent = makeVerificationIntent();
+ when(mRuleEvaluationEngine.evaluate(any(), any())).thenReturn(IntegrityCheckResult.allow());
+
+ broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
+ runJobInHandler();
+
+ ArgumentCaptor<AppInstallMetadata> metadataCaptor =
+ ArgumentCaptor.forClass(AppInstallMetadata.class);
+ Map<String, String> allowedInstallers = new HashMap<>();
+ ArgumentCaptor<Map<String, String>> allowedInstallersCaptor =
+ ArgumentCaptor.forClass(allowedInstallers.getClass());
+ verify(mRuleEvaluationEngine)
+ .evaluate(metadataCaptor.capture(), allowedInstallersCaptor.capture());
+ AppInstallMetadata appInstallMetadata = metadataCaptor.getValue();
+ allowedInstallers = allowedInstallersCaptor.getValue();
+ assertEquals(PACKAGE_NAME, appInstallMetadata.getPackageName());
+ assertEquals(APP_CERT, appInstallMetadata.getAppCertificate());
+ assertEquals(INSTALLER_SHA256, appInstallMetadata.getInstallerName());
+ assertEquals(INSTALLER_CERT, appInstallMetadata.getInstallerCertificate());
+ assertEquals(VERSION_CODE, appInstallMetadata.getVersionCode());
+ assertFalse(appInstallMetadata.isPreInstalled());
+ // These are hardcoded in the test apk
+ assertEquals(2, allowedInstallers.size());
+ assertEquals("cert_1", allowedInstallers.get("store_1"));
+ assertEquals("cert_2", allowedInstallers.get("store_2"));
+ }
+
+ @Test
+ public void handleBroadcast_allow() throws Exception {
+ ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mMockContext)
+ .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
+ Intent intent = makeVerificationIntent();
+ when(mRuleEvaluationEngine.evaluate(any(), any())).thenReturn(IntegrityCheckResult.allow());
+
+ broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
+ runJobInHandler();
verify(mPackageManagerInternal)
- .setIntegrityVerificationResult(verificationId, PackageManager.VERIFICATION_ALLOW);
+ .setIntegrityVerificationResult(
+ 1, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ }
+
+ @Test
+ public void handleBroadcast_reject() throws Exception {
+ ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ verify(mMockContext)
+ .registerReceiver(broadcastReceiverCaptor.capture(), any(), any(), any());
+ when(mRuleEvaluationEngine.evaluate(any(), any()))
+ .thenReturn(
+ IntegrityCheckResult.deny(
+ new Rule(
+ new AtomicFormula.BooleanAtomicFormula(
+ AtomicFormula.PRE_INSTALLED, false),
+ Rule.DENY)));
+ Intent intent = makeVerificationIntent();
+
+ broadcastReceiverCaptor.getValue().onReceive(mMockContext, intent);
+ runJobInHandler();
+
+ verify(mPackageManagerInternal)
+ .setIntegrityVerificationResult(
+ 1, PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
+ }
+
+ private void whitelistUsAsRuleProvider() {
+ Resources mockResources = mock(Resources.class);
+ when(mockResources.getStringArray(R.array.config_integrityRuleProviderPackages))
+ .thenReturn(new String[] {TEST_FRAMEWORK_PACKAGE});
+ when(mMockContext.getResources()).thenReturn(mockResources);
+ }
+
+ private void runJobInHandler() {
+ ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
+ // sendMessageAtTime is the first non-final method in the call chain when "post" is invoked.
+ verify(mHandler).sendMessageAtTime(messageCaptor.capture(), anyLong());
+ messageCaptor.getValue().getCallback().run();
+ }
+
+ private void makeUsSystemApp() throws Exception {
+ PackageInfo packageInfo =
+ mRealContext.getPackageManager().getPackageInfo(TEST_FRAMEWORK_PACKAGE, 0);
+ packageInfo.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+ doReturn(packageInfo)
+ .when(mSpyPackageManager)
+ .getPackageInfo(eq(TEST_FRAMEWORK_PACKAGE), anyInt());
+ }
+
+ private Intent makeVerificationIntent() throws Exception {
+ Intent intent = new Intent();
+ intent.setDataAndType(Uri.fromFile(mTestApk), PACKAGE_MIME_TYPE);
+ intent.setAction(Intent.ACTION_PACKAGE_NEEDS_INTEGRITY_VERIFICATION);
+ intent.putExtra(EXTRA_VERIFICATION_ID, 1);
+ intent.putExtra(Intent.EXTRA_PACKAGE_NAME, PACKAGE_NAME);
+ intent.putExtra(EXTRA_VERIFICATION_INSTALLER_PACKAGE, INSTALLER);
+ intent.putExtra(
+ EXTRA_VERIFICATION_INSTALLER_UID,
+ mRealContext.getPackageManager().getPackageUid(INSTALLER, /* flags= */ 0));
+ intent.putExtra(Intent.EXTRA_VERSION_CODE, VERSION_CODE);
+ return intent;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
index ad74901ece2c..0bb2d4489b6b 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
@@ -44,48 +44,66 @@ import java.util.Optional;
@RunWith(JUnit4.class)
public class RuleXmlSerializerTest {
+ private static final String SAMPLE_INSTALLER_NAME = "com.test.installer";
+ private static final String SAMPLE_INSTALLER_CERT = "installer_cert";
+
@Test
- public void testXmlString_serializeEmptyRule() throws Exception {
- Rule rule = null;
+ public void testXmlString_serializeEmptyRuleList() throws Exception {
RuleSerializer xmlSerializer = new RuleXmlSerializer();
String expectedRules = "<RL />";
byte[] actualRules =
xmlSerializer.serialize(
- Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
+ Collections.emptyList(), /* formatVersion= */ Optional.empty());
assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
}
@Test
- public void testXmlString_serializeMultipleRules_oneEmpty() throws Exception {
- Rule rule1 = null;
- Rule rule2 =
+ public void testXmlString_serializeMultipleRules_indexingOrderPreserved() throws Exception {
+ String packageNameA = "aaa";
+ String packageNameB = "bbb";
+ String packageNameC = "ccc";
+ String appCert1 = "cert1";
+ String appCert2 = "cert2";
+ String appCert3 = "cert3";
+ Rule installerRule =
new Rule(
- new AtomicFormula.StringAtomicFormula(
- AtomicFormula.PACKAGE_NAME,
- "com.app.test",
- /* isHashedValue= */ false),
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_NAME,
+ SAMPLE_INSTALLER_NAME,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_CERTIFICATE,
+ SAMPLE_INSTALLER_CERT,
+ /* isHashedValue= */ false))),
Rule.DENY);
- RuleSerializer xmlSerializer = new RuleXmlSerializer();
- Map<String, String> packageNameAttrs = new LinkedHashMap<>();
- packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
- packageNameAttrs.put("V", "com.app.test");
- packageNameAttrs.put("H", "false");
- String expectedRules =
- "<RL>"
- + generateTagWithAttribute(
- /* tag= */ "R",
- Collections.singletonMap("E", String.valueOf(Rule.DENY)),
- /* closed= */ false)
- + generateTagWithAttribute(
- /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
- + "</R>"
- + "</RL>";
+ RuleSerializer xmlSerializer = new RuleXmlSerializer();
byte[] actualRules =
xmlSerializer.serialize(
- Arrays.asList(rule1, rule2), /* formatVersion= */ Optional.empty());
+ Arrays.asList(
+ installerRule,
+ getRuleWithAppCertificateAndSampleInstallerName(appCert1),
+ getRuleWithPackageNameAndSampleInstallerName(packageNameB),
+ getRuleWithAppCertificateAndSampleInstallerName(appCert3),
+ getRuleWithPackageNameAndSampleInstallerName(packageNameC),
+ getRuleWithAppCertificateAndSampleInstallerName(appCert2),
+ getRuleWithPackageNameAndSampleInstallerName(packageNameA)),
+ /* formatVersion= */ Optional.empty());
+
+ String expectedRules = "<RL>"
+ + getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(packageNameA)
+ + getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(packageNameB)
+ + getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(packageNameC)
+ + getSerializedCompoundRuleWithAppCertificateAndSampleInstallerName(appCert1)
+ + getSerializedCompoundRuleWithAppCertificateAndSampleInstallerName(appCert2)
+ + getSerializedCompoundRuleWithAppCertificateAndSampleInstallerName(appCert3)
+ + getSerializedCompoundRuleWithSampleInstallerNameAndCert()
+ + "</RL>";
assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
}
@@ -371,7 +389,7 @@ public class RuleXmlSerializerTest {
assertExpectException(
RuleSerializeException.class,
- /* expectedExceptionMessageRegex */ "Invalid formula type",
+ /* expectedExceptionMessageRegex */ "Malformed rule identified.",
() ->
xmlSerializer.serialize(
Collections.singletonList(rule),
@@ -393,6 +411,124 @@ public class RuleXmlSerializerTest {
return res.toString();
}
+ private Rule getRuleWithPackageNameAndSampleInstallerName(String packageName) {
+ return new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.PACKAGE_NAME,
+ packageName,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_NAME,
+ SAMPLE_INSTALLER_NAME,
+ /* isHashedValue= */ false))),
+ Rule.DENY);
+ }
+
+ private String getSerializedCompoundRuleWithPackageNameAndSampleInstallerName(
+ String packageName) {
+
+ Map<String, String> packageNameAttrs = new LinkedHashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.PACKAGE_NAME));
+ packageNameAttrs.put("V", packageName);
+ packageNameAttrs.put("H", "false");
+
+ Map<String, String> installerNameAttrs = new LinkedHashMap<>();
+ installerNameAttrs.put("K", String.valueOf(AtomicFormula.INSTALLER_NAME));
+ installerNameAttrs.put("V", SAMPLE_INSTALLER_NAME);
+ installerNameAttrs.put("H", "false");
+
+ return generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", installerNameAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>";
+ }
+
+
+ private Rule getRuleWithAppCertificateAndSampleInstallerName(String certificate) {
+ return new Rule(
+ new CompoundFormula(
+ CompoundFormula.AND,
+ Arrays.asList(
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.APP_CERTIFICATE,
+ certificate,
+ /* isHashedValue= */ false),
+ new AtomicFormula.StringAtomicFormula(
+ AtomicFormula.INSTALLER_NAME,
+ SAMPLE_INSTALLER_NAME,
+ /* isHashedValue= */ false))),
+ Rule.DENY);
+ }
+
+ private String getSerializedCompoundRuleWithAppCertificateAndSampleInstallerName(
+ String appCert) {
+
+ Map<String, String> packageNameAttrs = new LinkedHashMap<>();
+ packageNameAttrs.put("K", String.valueOf(AtomicFormula.APP_CERTIFICATE));
+ packageNameAttrs.put("V", appCert);
+ packageNameAttrs.put("H", "false");
+
+ Map<String, String> installerNameAttrs = new LinkedHashMap<>();
+ installerNameAttrs.put("K", String.valueOf(AtomicFormula.INSTALLER_NAME));
+ installerNameAttrs.put("V", SAMPLE_INSTALLER_NAME);
+ installerNameAttrs.put("H", "false");
+
+ return generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", packageNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", installerNameAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>";
+ }
+
+ private String getSerializedCompoundRuleWithSampleInstallerNameAndCert() {
+ Map<String, String> installerNameAttrs = new LinkedHashMap<>();
+ installerNameAttrs.put("K", String.valueOf(AtomicFormula.INSTALLER_NAME));
+ installerNameAttrs.put("V", SAMPLE_INSTALLER_NAME);
+ installerNameAttrs.put("H", "false");
+
+ Map<String, String> installerCertAttrs = new LinkedHashMap<>();
+ installerCertAttrs.put("K", String.valueOf(AtomicFormula.INSTALLER_CERTIFICATE));
+ installerCertAttrs.put("V", SAMPLE_INSTALLER_CERT);
+ installerCertAttrs.put("H", "false");
+
+ return generateTagWithAttribute(
+ /* tag= */ "R",
+ Collections.singletonMap("E", String.valueOf(Rule.DENY)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "OF",
+ Collections.singletonMap("C", String.valueOf(CompoundFormula.AND)),
+ /* closed= */ false)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", installerNameAttrs, /* closed= */ true)
+ + generateTagWithAttribute(
+ /* tag= */ "AF", installerCertAttrs, /* closed= */ true)
+ + "</OF>"
+ + "</R>";
+ }
+
private Formula getInvalidFormula() {
return new Formula() {
@Override
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
index ebd363386fa3..1fff4f084fc4 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
@@ -17,8 +17,7 @@
package com.android.server.pm;
import android.content.pm.PackageManager;
-import com.android.server.pm.PackageVerificationState;
-
+import android.content.pm.PackageManagerInternal;
import android.test.AndroidTestCase;
public class PackageVerificationStateTest extends AndroidTestCase {
@@ -29,7 +28,8 @@ public class PackageVerificationStateTest extends AndroidTestCase {
private static final int SUFFICIENT_UID_2 = 8938;
public void testPackageVerificationState_OnlyRequiredVerifier_AllowedInstall() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -44,7 +44,8 @@ public class PackageVerificationStateTest extends AndroidTestCase {
}
public void testPackageVerificationState_OnlyRequiredVerifier_DeniedInstall() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -59,7 +60,8 @@ public class PackageVerificationStateTest extends AndroidTestCase {
}
public void testPackageVerificationState_RequiredAndOneSufficient_RequiredDeniedInstall() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -84,7 +86,8 @@ public class PackageVerificationStateTest extends AndroidTestCase {
}
public void testPackageVerificationState_RequiredAndOneSufficient_SufficientDeniedInstall() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -109,7 +112,8 @@ public class PackageVerificationStateTest extends AndroidTestCase {
}
public void testPackageVerificationState_RequiredAndTwoSufficient_OneSufficientIsEnough() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -135,7 +139,8 @@ public class PackageVerificationStateTest extends AndroidTestCase {
}
public void testPackageVerificationState_RequiredAndTwoSufficient_SecondSufficientIsEnough() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -166,7 +171,8 @@ public class PackageVerificationStateTest extends AndroidTestCase {
}
public void testPackageVerificationState_RequiredAndTwoSufficient_RequiredOverrides() {
- PackageVerificationState state = new PackageVerificationState(REQUIRED_UID, null);
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
assertFalse("Verification should not be marked as complete yet",
state.isVerificationComplete());
@@ -202,4 +208,55 @@ public class PackageVerificationStateTest extends AndroidTestCase {
assertTrue("Installation should be marked as allowed still",
state.isInstallAllowed());
}
+
+ public void testAreAllVerificationsComplete_onlyVerificationPasses() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
+ assertFalse(state.areAllVerificationsComplete());
+
+ state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+
+ assertFalse(state.areAllVerificationsComplete());
+ }
+
+ public void testAreAllVerificationsComplete_onlyIntegrityCheckPasses() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
+ assertFalse(state.areAllVerificationsComplete());
+
+ state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+
+ assertFalse(state.areAllVerificationsComplete());
+ }
+
+ public void testAreAllVerificationsComplete_bothPasses() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
+ assertFalse(state.areAllVerificationsComplete());
+
+ state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
+ state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_ALLOW);
+
+ assertTrue(state.areAllVerificationsComplete());
+ }
+
+ public void testAreAllVerificationsComplete_onlyVerificationFails() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
+ assertFalse(state.areAllVerificationsComplete());
+
+ state.setVerifierResponse(REQUIRED_UID, PackageManager.VERIFICATION_REJECT);
+
+ assertFalse(state.areAllVerificationsComplete());
+ }
+
+ public void testAreAllVerificationsComplete_onlyIntegrityCheckFails() {
+ PackageVerificationState state = new PackageVerificationState(null);
+ state.setRequiredVerifierUid(REQUIRED_UID);
+ assertFalse(state.areAllVerificationsComplete());
+
+ state.setIntegrityVerificationResult(PackageManagerInternal.INTEGRITY_VERIFICATION_REJECT);
+
+ assertFalse(state.areAllVerificationsComplete());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 89723d14090b..65704c891318 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.os.Process.NOBODY_UID;
@@ -62,6 +63,7 @@ import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.never;
import android.app.ActivityOptions;
+import android.app.WindowConfiguration;
import android.app.servertransaction.ActivityConfigurationChangeItem;
import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.PauseActivityItem;
@@ -70,6 +72,7 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.platform.test.annotations.Presubmit;
@@ -376,6 +379,64 @@ public class ActivityRecordTests extends ActivityTestsBase {
}
@Test
+ public void ignoreRequestedOrientationInFreeformWindows() {
+ mStack.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
+ final Rect stableRect = new Rect();
+ mStack.getDisplay().mDisplayContent.getStableRect(stableRect);
+ final boolean isScreenPortrait = stableRect.width() <= stableRect.height();
+ final Rect bounds = new Rect(stableRect);
+ if (isScreenPortrait) {
+ // Landscape bounds
+ final int newHeight = stableRect.width() - 10;
+ bounds.top = stableRect.top + (stableRect.height() - newHeight) / 2;
+ bounds.bottom = bounds.top + newHeight;
+ } else {
+ // Portrait bounds
+ final int newWidth = stableRect.height() - 10;
+ bounds.left = stableRect.left + (stableRect.width() - newWidth) / 2;
+ bounds.right = bounds.left + newWidth;
+ }
+ mTask.setBounds(bounds);
+
+ // Requests orientation that's different from its bounds.
+ mActivity.setRequestedOrientation(
+ isScreenPortrait ? SCREEN_ORIENTATION_PORTRAIT : SCREEN_ORIENTATION_LANDSCAPE);
+
+ // Asserts it has orientation derived from bounds.
+ assertEquals(isScreenPortrait ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT,
+ mActivity.getConfiguration().orientation);
+ }
+
+ @Test
+ public void ignoreRequestedOrientationInSplitWindows() {
+ mStack.setWindowingMode(WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ final Rect stableRect = new Rect();
+ mStack.getDisplay().mDisplayContent.getStableRect(stableRect);
+ final boolean isScreenPortrait = stableRect.width() <= stableRect.height();
+ final Rect bounds = new Rect(stableRect);
+ if (isScreenPortrait) {
+ // Landscape bounds
+ final int newHeight = stableRect.width() - 10;
+ bounds.top = stableRect.top + (stableRect.height() - newHeight) / 2;
+ bounds.bottom = bounds.top + newHeight;
+ } else {
+ // Portrait bounds
+ final int newWidth = stableRect.height() - 10;
+ bounds.left = stableRect.left + (stableRect.width() - newWidth) / 2;
+ bounds.right = bounds.left + newWidth;
+ }
+ mTask.setBounds(bounds);
+
+ // Requests orientation that's different from its bounds.
+ mActivity.setRequestedOrientation(
+ isScreenPortrait ? SCREEN_ORIENTATION_PORTRAIT : SCREEN_ORIENTATION_LANDSCAPE);
+
+ // Asserts it has orientation derived from bounds.
+ assertEquals(isScreenPortrait ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT,
+ mActivity.getConfiguration().orientation);
+ }
+
+ @Test
public void testShouldMakeActive_deferredResume() {
mActivity.setState(ActivityStack.ActivityState.STOPPED, "Testing");
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
index 1a18df5b6fcf..de6d75235777 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java
@@ -427,6 +427,61 @@ public class TaskRecordTests extends ActivityTestsBase {
assertNotEquals(origScreenH, task.getConfiguration().screenHeightDp);
}
+ @Test
+ public void testInsetDisregardedWhenFreeformOverlapsNavBar() {
+ DisplayContent display = mService.mRootActivityContainer.getDefaultDisplay();
+ ActivityStack stack = display.createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD,
+ true /* onTop */);
+ DisplayInfo displayInfo = new DisplayInfo();
+ mService.mContext.getDisplay().getDisplayInfo(displayInfo);
+ final int displayHeight = displayInfo.logicalHeight;
+ final Task task = new TaskBuilder(mSupervisor).setStack(stack).build();
+ final Configuration inOutConfig = new Configuration();
+ final Configuration parentConfig = new Configuration();
+ final int longSide = 1200;
+ final int shortSide = 600;
+ parentConfig.densityDpi = 400;
+ parentConfig.screenHeightDp = 200; // 200 * 400 / 160 = 500px
+ parentConfig.screenWidthDp = 100; // 100 * 400 / 160 = 250px
+ parentConfig.windowConfiguration.setRotation(ROTATION_0);
+
+ final float density = 2.5f; // densityDpi / DENSITY_DEFAULT_SCALE = 400 / 160.0f
+ final int longSideDp = 480; // longSide / density = 1200 / 400 * 160
+ final int shortSideDp = 240; // shortSide / density = 600 / 400 * 160
+ final int screenLayout = parentConfig.screenLayout
+ & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
+ final int reducedScreenLayout =
+ Configuration.reduceScreenLayout(screenLayout, longSideDp, shortSideDp);
+
+ // Portrait bounds overlapping with navigation bar, without insets.
+ inOutConfig.windowConfiguration.getBounds().set(0,
+ displayHeight - 10 - longSide,
+ shortSide,
+ displayHeight - 10);
+ // Set to freeform mode to verify bug fix.
+ inOutConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
+
+ task.computeConfigResourceOverrides(inOutConfig, parentConfig);
+
+ assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp);
+ assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp);
+ assertEquals(reducedScreenLayout, inOutConfig.screenLayout);
+
+ inOutConfig.setToDefaults();
+ // Landscape bounds overlapping with navigtion bar, without insets.
+ inOutConfig.windowConfiguration.getBounds().set(0,
+ displayHeight - 10 - shortSide,
+ longSide,
+ displayHeight - 10);
+ inOutConfig.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
+
+ task.computeConfigResourceOverrides(inOutConfig, parentConfig);
+
+ assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp);
+ assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp);
+ assertEquals(reducedScreenLayout, inOutConfig.screenLayout);
+ }
+
/** Ensures that the alias intent won't have target component resolved. */
@Test
public void testTaskIntentActivityAlias() {
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 3940a3b0a1cf..9b9997f9b737 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -485,6 +485,86 @@ public class Annotation {
PreciseCallState.PRECISE_CALL_STATE_DISCONNECTING})
public @interface PreciseCallStates {}
+ @IntDef(value = {
+ DisconnectCause.NOT_VALID,
+ DisconnectCause.NOT_DISCONNECTED,
+ DisconnectCause.INCOMING_MISSED,
+ DisconnectCause.NORMAL,
+ DisconnectCause.LOCAL,
+ DisconnectCause.BUSY,
+ DisconnectCause.CONGESTION,
+ DisconnectCause.MMI,
+ DisconnectCause.INVALID_NUMBER,
+ DisconnectCause.NUMBER_UNREACHABLE,
+ DisconnectCause.SERVER_UNREACHABLE,
+ DisconnectCause.INVALID_CREDENTIALS,
+ DisconnectCause.OUT_OF_NETWORK,
+ DisconnectCause.SERVER_ERROR,
+ DisconnectCause.TIMED_OUT,
+ DisconnectCause.LOST_SIGNAL,
+ DisconnectCause.LIMIT_EXCEEDED,
+ DisconnectCause.INCOMING_REJECTED,
+ DisconnectCause.POWER_OFF,
+ DisconnectCause.OUT_OF_SERVICE,
+ DisconnectCause.ICC_ERROR,
+ DisconnectCause.CALL_BARRED,
+ DisconnectCause.FDN_BLOCKED,
+ DisconnectCause.CS_RESTRICTED,
+ DisconnectCause.CS_RESTRICTED_NORMAL,
+ DisconnectCause.CS_RESTRICTED_EMERGENCY,
+ DisconnectCause.UNOBTAINABLE_NUMBER,
+ DisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE,
+ DisconnectCause.CDMA_DROP,
+ DisconnectCause.CDMA_INTERCEPT,
+ DisconnectCause.CDMA_REORDER,
+ DisconnectCause.CDMA_SO_REJECT,
+ DisconnectCause.CDMA_RETRY_ORDER,
+ DisconnectCause.CDMA_ACCESS_FAILURE,
+ DisconnectCause.CDMA_PREEMPTED,
+ DisconnectCause.CDMA_NOT_EMERGENCY,
+ DisconnectCause.CDMA_ACCESS_BLOCKED,
+ DisconnectCause.ERROR_UNSPECIFIED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DisconnectCauses {
+ }
+
+ @IntDef(value = {
+ PreciseDisconnectCause.NOT_VALID,
+ PreciseDisconnectCause.NO_DISCONNECT_CAUSE_AVAILABLE,
+ PreciseDisconnectCause.UNOBTAINABLE_NUMBER,
+ PreciseDisconnectCause.NORMAL,
+ PreciseDisconnectCause.BUSY,
+ PreciseDisconnectCause.NUMBER_CHANGED,
+ PreciseDisconnectCause.STATUS_ENQUIRY,
+ PreciseDisconnectCause.NORMAL_UNSPECIFIED,
+ PreciseDisconnectCause.NO_CIRCUIT_AVAIL,
+ PreciseDisconnectCause.TEMPORARY_FAILURE,
+ PreciseDisconnectCause.SWITCHING_CONGESTION,
+ PreciseDisconnectCause.CHANNEL_NOT_AVAIL,
+ PreciseDisconnectCause.QOS_NOT_AVAIL,
+ PreciseDisconnectCause.BEARER_NOT_AVAIL,
+ PreciseDisconnectCause.ACM_LIMIT_EXCEEDED,
+ PreciseDisconnectCause.CALL_BARRED,
+ PreciseDisconnectCause.FDN_BLOCKED,
+ PreciseDisconnectCause.IMSI_UNKNOWN_IN_VLR,
+ PreciseDisconnectCause.IMEI_NOT_ACCEPTED,
+ PreciseDisconnectCause.CDMA_LOCKED_UNTIL_POWER_CYCLE,
+ PreciseDisconnectCause.CDMA_DROP,
+ PreciseDisconnectCause.CDMA_INTERCEPT,
+ PreciseDisconnectCause.CDMA_REORDER,
+ PreciseDisconnectCause.CDMA_SO_REJECT,
+ PreciseDisconnectCause.CDMA_RETRY_ORDER,
+ PreciseDisconnectCause.CDMA_ACCESS_FAILURE,
+ PreciseDisconnectCause.CDMA_PREEMPTED,
+ PreciseDisconnectCause.CDMA_NOT_EMERGENCY,
+ PreciseDisconnectCause.CDMA_ACCESS_BLOCKED,
+ PreciseDisconnectCause.ERROR_UNSPECIFIED,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PreciseDisconnectCauses {
+ }
+
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = {"RIL_RADIO_TECHNOLOGY_" }, value = {
ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN,
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 813b9fa3e698..4bb237f6c27c 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -4050,13 +4050,28 @@ public class CarrierConfigManager {
}
}
- /** {@hide} */
+ /**
+ * Gets the package name for a default carrier service.
+ * @return the package name for a default carrier service; empty string if not available.
+ *
+ * @hide
+ */
+ @NonNull
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public String getDefaultCarrierServicePackageName() {
try {
- return getICarrierConfigLoader().getDefaultCarrierServicePackageName();
- } catch (Throwable t) {
- return null;
+ ICarrierConfigLoader loader = getICarrierConfigLoader();
+ if (loader == null) {
+ Rlog.w(TAG, "getDefaultCarrierServicePackageName ICarrierConfigLoader is null");
+ return "";
+ }
+ return loader.getDefaultCarrierServicePackageName();
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "getDefaultCarrierServicePackageName ICarrierConfigLoader is null"
+ + ex.toString());
}
+ return "";
}
/**
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index b7dab161c331..e523fbab2bb0 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -19,6 +19,7 @@ package android.telephony;
import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -181,7 +182,8 @@ public abstract class CellIdentity implements Parcelable {
* @return a CellLocation object for this CellIdentity
* @hide
*/
- public abstract CellLocation asCellLocation();
+ @SystemApi
+ public abstract @NonNull CellLocation asCellLocation();
@Override
public boolean equals(Object other) {
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index 880d3db681b5..54236b426d98 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.os.Parcel;
import android.telephony.cdma.CdmaCellLocation;
@@ -198,6 +199,7 @@ public final class CellIdentityCdma extends CellIdentity {
}
/** @hide */
+ @NonNull
@Override
public CdmaCellLocation asCellLocation() {
CdmaCellLocation cl = new CdmaCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index 25c6577bdcf5..4e4454d6a1c2 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
@@ -200,6 +201,7 @@ public final class CellIdentityGsm extends CellIdentity {
}
/** @hide */
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 997b19f3d4eb..c3fc73b775d7 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.os.Build;
@@ -232,6 +233,7 @@ public final class CellIdentityLte extends CellIdentity {
*
* @hide
*/
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index edc838c163db..e3fec7b7f820 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -17,6 +17,7 @@
package android.telephony;
import android.annotation.IntRange;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.telephony.gsm.GsmCellLocation;
@@ -77,6 +78,7 @@ public final class CellIdentityNr extends CellIdentity {
* @return a CellLocation object for this CellIdentity.
* @hide
*/
+ @NonNull
@Override
public CellLocation asCellLocation() {
return new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 558e346284ea..8f812b6b892e 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -171,6 +171,7 @@ public final class CellIdentityTdscdma extends CellIdentity {
}
/** @hide */
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 031fed13d9f1..556bc32e7c36 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -16,6 +16,7 @@
package android.telephony;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
@@ -196,6 +197,7 @@ public final class CellIdentityWcdma extends CellIdentity {
}
/** @hide */
+ @NonNull
@Override
public GsmCellLocation asCellLocation() {
GsmCellLocation cl = new GsmCellLocation();
diff --git a/telephony/java/android/telephony/PreciseCallState.java b/telephony/java/android/telephony/PreciseCallState.java
index 9f75332c4a03..bfa6326c3c18 100644
--- a/telephony/java/android/telephony/PreciseCallState.java
+++ b/telephony/java/android/telephony/PreciseCallState.java
@@ -16,19 +16,18 @@
package android.telephony;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
+import android.telephony.Annotation.DisconnectCauses;
import android.telephony.Annotation.PreciseCallStates;
+import android.telephony.Annotation.PreciseDisconnectCauses;
import android.telephony.DisconnectCause;
import android.telephony.PreciseDisconnectCause;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
@@ -73,19 +72,26 @@ public final class PreciseCallState implements Parcelable {
private @PreciseCallStates int mRingingCallState = PRECISE_CALL_STATE_NOT_VALID;
private @PreciseCallStates int mForegroundCallState = PRECISE_CALL_STATE_NOT_VALID;
private @PreciseCallStates int mBackgroundCallState = PRECISE_CALL_STATE_NOT_VALID;
- private int mDisconnectCause = DisconnectCause.NOT_VALID;
- private int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
+ private @DisconnectCauses int mDisconnectCause = DisconnectCause.NOT_VALID;
+ private @PreciseDisconnectCauses int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
/**
- * Constructor
+ * Construct PreciseCallState with parameters
+ *
+ * @param ringingCall ring call state
+ * @param foregroundCall foreground call state
+ * @param backgroundCall background call state
+ * @param disconnectCause disconnect cause
+ * @param preciseDisconnectCause precise disconnect cause
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public PreciseCallState(@PreciseCallStates int ringingCall,
@PreciseCallStates int foregroundCall,
- @PreciseCallStates int backgroundCall, int disconnectCause,
- int preciseDisconnectCause) {
+ @PreciseCallStates int backgroundCall,
+ @DisconnectCauses int disconnectCause,
+ @PreciseDisconnectCauses int preciseDisconnectCause) {
mRingingCallState = ringingCall;
mForegroundCallState = foregroundCall;
mBackgroundCallState = backgroundCall;
diff --git a/telephony/java/android/telephony/SmsMessage.java b/telephony/java/android/telephony/SmsMessage.java
index b705d71c61d9..392d3eb37686 100644
--- a/telephony/java/android/telephony/SmsMessage.java
+++ b/telephony/java/android/telephony/SmsMessage.java
@@ -344,10 +344,12 @@ public class SmsMessage {
* @param use7bitOnly if true, characters that are not part of the radio-specific 7-bit encoding
* are counted as single space chars. If false, and if the messageBody contains non-7-bit
* encodable characters, length is calculated using a 16-bit encoding.
- * @return an int[4] with int[0] being the number of SMS's required, int[1] the number of code
+ * @return an int[6] with int[0] being the number of SMS's required, int[1] the number of code
* units used, and int[2] is the number of code units remaining until the next message.
* int[3] is an indicator of the encoding code unit size (see the ENCODING_* definitions in
- * SmsConstants).
+ * SmsConstants). int[4] is the GSM national language table to use, or 0 for the default
+ * 7-bit alphabet. int[5] The GSM national language shift table to use, or 0 for the default
+ * 7-bit extension table.
*/
public static int[] calculateLength(CharSequence msgBody, boolean use7bitOnly) {
return calculateLength(msgBody, use7bitOnly, SmsManager.getDefaultSmsSubscriptionId());
@@ -362,10 +364,12 @@ public class SmsMessage {
* are counted as single space chars. If false, and if the messageBody contains non-7-bit
* encodable characters, length is calculated using a 16-bit encoding.
* @param subId Subscription to take SMS format.
- * @return an int[4] with int[0] being the number of SMS's required, int[1] the number of code
+ * @return an int[6] with int[0] being the number of SMS's required, int[1] the number of code
* units used, and int[2] is the number of code units remaining until the next message.
* int[3] is an indicator of the encoding code unit size (see the ENCODING_* definitions in
- * SmsConstants).
+ * SmsConstants). int[4] is the GSM national language table to use, or 0 for the default
+ * 7-bit alphabet. int[5] The GSM national language shift table to use, or 0 for the default
+ * 7-bit extension table.
* @hide
*/
public static int[] calculateLength(CharSequence msgBody, boolean use7bitOnly, int subId) {
@@ -376,11 +380,13 @@ public class SmsMessage {
msgBody, use7bitOnly, true)
: com.android.internal.telephony.gsm.SmsMessage.calculateLength(
msgBody, use7bitOnly);
- int ret[] = new int[4];
+ int[] ret = new int[6];
ret[0] = ted.msgCount;
ret[1] = ted.codeUnitCount;
ret[2] = ted.codeUnitsRemaining;
ret[3] = ted.codeUnitSize;
+ ret[4] = ted.languageTable;
+ ret[5] = ted.languageShiftTable;
return ret;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 60fda0906948..39e57b775a8d 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1950,14 +1950,9 @@ public class TelephonyManager {
return null;
}
- Bundle bundle = telephony.getCellLocation(mContext.getOpPackageName(),
+ CellIdentity cellIdentity = telephony.getCellLocation(mContext.getOpPackageName(),
mContext.getFeatureId());
- if (bundle == null || bundle.isEmpty()) {
- Rlog.d(TAG, "getCellLocation returning null because CellLocation is unavailable");
- return null;
- }
-
- CellLocation cl = CellLocation.newFromBundle(bundle);
+ CellLocation cl = cellIdentity.asCellLocation();
if (cl == null || cl.isEmpty()) {
Rlog.d(TAG, "getCellLocation returning null because CellLocation is empty or"
+ " phone type doesn't match CellLocation type");
@@ -4248,7 +4243,7 @@ public class TelephonyManager {
* The returned set of subscriber IDs will include the subscriber ID corresponding to this
* TelephonyManager's subId.
*
- * This is deprecated and {@link #getMergedSubscriberIdsFromGroup()} should be used for data
+ * This is deprecated and {@link #getMergedImsisFromGroup()} should be used for data
* usage merging purpose.
* TODO: remove this API.
*
@@ -4269,25 +4264,27 @@ public class TelephonyManager {
}
/**
- * Return the set of subscriber IDs that should be considered "merged together" for data usage
- * purposes. Unlike {@link #getMergedSubscriberIds()} this API merge subscriberIds based on
- * subscription grouping: subscriberId of those in the same group will all be returned.
+ * Return the set of IMSIs that should be considered "merged together" for data usage
+ * purposes. Unlike {@link #getMergedSubscriberIds()} this API merge IMSIs based on
+ * subscription grouping: IMSI of those in the same group will all be returned.
+ * Return the current IMSI if there is no subscription group.
*
* <p>Requires the calling app to have READ_PRIVILEGED_PHONE_STATE permission.
*
* @hide
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public @Nullable String[] getMergedSubscriberIdsFromGroup() {
+ public @NonNull String[] getMergedImsisFromGroup() {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getMergedSubscriberIdsFromGroup(getSubId(), getOpPackageName());
+ return telephony.getMergedImsisFromGroup(getSubId(), getOpPackageName());
}
} catch (RemoteException ex) {
} catch (NullPointerException ex) {
}
- return null;
+ return new String[0];
}
/**
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 97b24aef4af5..b99fe904bbe8 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -30,6 +30,7 @@ import android.service.carrier.CarrierIdentifier;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telephony.CarrierRestrictionRules;
+import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.ClientRequestStats;
import android.telephony.IccOpenLogicalChannelResponse;
@@ -305,7 +306,8 @@ interface ITelephony {
*/
boolean isDataConnectivityPossible(int subId);
- Bundle getCellLocation(String callingPkg, String callingFeatureId);
+ // Uses CellIdentity which is Parcelable here; will convert to CellLocation in client.
+ CellIdentity getCellLocation(String callingPkg, String callingFeatureId);
/**
* Returns the ISO country code equivalent of the current registered
@@ -1134,7 +1136,7 @@ interface ITelephony {
/**
* @hide
*/
- String[] getMergedSubscriberIdsFromGroup(int subId, String callingPackage);
+ String[] getMergedImsisFromGroup(int subId, String callingPackage);
/**
* Override the operator branding for the current ICCID.
diff --git a/tests/ApkVerityTest/AndroidTest.xml b/tests/ApkVerityTest/AndroidTest.xml
index 51bcdea21f49..55704eda905e 100644
--- a/tests/ApkVerityTest/AndroidTest.xml
+++ b/tests/ApkVerityTest/AndroidTest.xml
@@ -22,7 +22,7 @@
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
<!-- Disable package verifier prevents it holding the target APK's fd that prevents cache
eviction. -->
- <option name="set-global-setting" key="package_verifier_enable" value="0" />
+ <option name="set-global-setting" key="verifier_verify_adb_installs" value="0" />
<option name="restore-settings" value="true" />
<!-- Skip in order to prevent reboot that confuses the test flow. -->
diff --git a/wifi/java/android/net/wifi/EasyConnectStatusCallback.java b/wifi/java/android/net/wifi/EasyConnectStatusCallback.java
index b8c82fd9e0ae..4fa93ee271e9 100644
--- a/wifi/java/android/net/wifi/EasyConnectStatusCallback.java
+++ b/wifi/java/android/net/wifi/EasyConnectStatusCallback.java
@@ -17,32 +17,46 @@
package android.net.wifi;
import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
-import android.os.Handler;
+import android.util.SparseArray;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.concurrent.Executor;
/**
* Easy Connect (DPP) Status Callback. Use this callback to get status updates (success, failure,
* progress) from the Easy Connect operation started with
- * {@link WifiManager#startEasyConnectAsConfiguratorInitiator(String,
- * int, int, Handler, EasyConnectStatusCallback)} or
- * {@link WifiManager#startEasyConnectAsEnrolleeInitiator(String,
- * Handler, EasyConnectStatusCallback)}
+ * {@link WifiManager#startEasyConnectAsConfiguratorInitiator(String, int, int, Executor,
+ * EasyConnectStatusCallback)} or {@link WifiManager#startEasyConnectAsEnrolleeInitiator(String,
+ * Executor, EasyConnectStatusCallback)}
*
* @hide
*/
@SystemApi
public abstract class EasyConnectStatusCallback {
/**
- * Easy Connect Success event: Configuration sent (Configurator mode).
+ * Easy Connect R1 Success event: Configuration sent (Configurator mode). This is the last
+ * and final Easy Connect event when either the local device or remote device implement R1.
+ * If both devices implement R2, this event will never be received, and the
+ * {@link EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED} will be received.
*/
public static final int EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT = 0;
+ /**
+ * East Connect R2 Success event: Configuration applied by Enrollee (Configurator mode).
+ * This is the last and final Easy Connect event when both the local device and remote device
+ * implement R2. If either the local device or remote device implement R1, this event will never
+ * be received, and the {@link EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT} will be received.
+ */
+ public static final int EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED = 1;
+
/** @hide */
@IntDef(prefix = {"EASY_CONNECT_EVENT_SUCCESS_"}, value = {
EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT,
+ EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface EasyConnectSuccessStatusCode {
@@ -58,10 +72,22 @@ public abstract class EasyConnectStatusCallback {
*/
public static final int EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING = 1;
+ /**
+ * Easy Connect R2 Progress event: Configuration sent to Enrollee, waiting for response
+ */
+ public static final int EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_SENT_WAITING_RESPONSE = 2;
+
+ /**
+ * Easy Connect R2 Progress event: Configuration accepted by Enrollee, waiting for response
+ */
+ public static final int EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_ACCEPTED = 3;
+
/** @hide */
@IntDef(prefix = {"EASY_CONNECT_EVENT_PROGRESS_"}, value = {
EASY_CONNECT_EVENT_PROGRESS_AUTHENTICATION_SUCCESS,
EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING,
+ EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_SENT_WAITING_RESPONSE,
+ EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_ACCEPTED,
})
@Retention(RetentionPolicy.SOURCE)
public @interface EasyConnectProgressStatusCode {
@@ -114,6 +140,20 @@ public abstract class EasyConnectStatusCallback {
*/
public static final int EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK = -9;
+ /**
+ * Easy Connect R2 Failure event: Enrollee cannot find the network.
+ */
+ public static final int EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK = -10;
+
+ /**
+ * Easy Connect R2 Failure event: Enrollee failed to authenticate with the network.
+ */
+ public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION = -11;
+
+ /**
+ * Easy Connect R2 Failure event: Enrollee rejected the configuration.
+ */
+ public static final int EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION = -12;
/** @hide */
@IntDef(prefix = {"EASY_CONNECT_EVENT_FAILURE_"}, value = {
@@ -126,6 +166,9 @@ public abstract class EasyConnectStatusCallback {
EASY_CONNECT_EVENT_FAILURE_GENERIC,
EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED,
EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK,
+ EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK,
+ EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION,
+ EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION,
})
@Retention(RetentionPolicy.SOURCE)
public @interface EasyConnectFailureStatusCode {
@@ -138,9 +181,8 @@ public abstract class EasyConnectStatusCallback {
* current Easy Connect
* session, and no further callbacks will be called. This callback is the successful outcome
* of a Easy Connect flow starting with
- * {@link WifiManager#startEasyConnectAsEnrolleeInitiator(String,
- * Handler,
- * EasyConnectStatusCallback)}.
+ * {@link WifiManager#startEasyConnectAsEnrolleeInitiator(String, Executor,
+ * EasyConnectStatusCallback)} .
*
* @param newNetworkId New Wi-Fi configuration with a network ID received from the configurator
*/
@@ -148,13 +190,11 @@ public abstract class EasyConnectStatusCallback {
/**
* Called when a Easy Connect success event takes place, except for when configuration is
- * received from
- * an external Configurator. The callback onSuccessConfigReceived will be used in this case.
- * This callback marks the successful end of the current Easy Connect session, and no further
- * callbacks will be called. This callback is the successful outcome of a Easy Connect flow
- * starting with
- * {@link WifiManager#startEasyConnectAsConfiguratorInitiator(String, int, int, Handler,
- * EasyConnectStatusCallback)}.
+ * received from an external Configurator. The callback onSuccessConfigReceived will be used in
+ * this case. This callback marks the successful end of the current Easy Connect session, and no
+ * further callbacks will be called. This callback is the successful outcome of a Easy Connect
+ * flow starting with {@link WifiManager#startEasyConnectAsConfiguratorInitiator(String, int,
+ * int, Executor,EasyConnectStatusCallback)}.
*
* @param code Easy Connect success status code.
*/
@@ -162,12 +202,36 @@ public abstract class EasyConnectStatusCallback {
/**
* Called when a Easy Connect Failure event takes place. This callback marks the unsuccessful
- * end of the
- * current Easy Connect session, and no further callbacks will be called.
+ * end of the current Easy Connect session, and no further callbacks will be called.
*
* @param code Easy Connect failure status code.
*/
- public abstract void onFailure(@EasyConnectFailureStatusCode int code);
+ public void onFailure(@EasyConnectFailureStatusCode int code) {}
+
+ /**
+ * Called when a Easy Connect Failure event takes place. This callback marks the unsuccessful
+ * end of the current Easy Connect session, and no further callbacks will be called.
+ *
+ * Note: Easy Connect (DPP) R2, provides additional details for the Configurator when the
+ * remote Enrollee is unable to connect to a network. The ssid, channelList and bandList
+ * inputs are initialized only for the EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK failure
+ * code, and the ssid and bandList are initialized for the
+ * EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION failure code.
+ *
+ * @param code Easy Connect failure status code.
+ * @param ssid SSID of the network the Enrollee tried to connect to.
+ * @param channelListArray List of Global Operating classes and channel sets the Enrollee used
+ * to scan to find the network, see the "DPP Connection Status Object"
+ * section in the specification for the format, and Table E-4 in
+ * IEEE Std 802.11-2016 - Global operating classes for more details.
+ * @param operatingClassArray Array of bands the Enrollee supports as expressed as the Global
+ * Operating Class, see Table E-4 in IEEE Std 802.11-2016 - Global
+ * operating classes.
+ */
+ public void onFailure(@EasyConnectFailureStatusCode int code, @Nullable String ssid,
+ @NonNull SparseArray<int[]> channelListArray, @NonNull int[] operatingClassArray) {
+ onFailure(code);
+ }
/**
* Called when Easy Connect events that indicate progress take place. Can be used by UI elements
diff --git a/wifi/java/android/net/wifi/IDppCallback.aidl b/wifi/java/android/net/wifi/IDppCallback.aidl
index c452c7664c12..d7a958a5b4b1 100644
--- a/wifi/java/android/net/wifi/IDppCallback.aidl
+++ b/wifi/java/android/net/wifi/IDppCallback.aidl
@@ -38,7 +38,7 @@ oneway interface IDppCallback
/**
* Called when DPP Failure events take place.
*/
- void onFailure(int status);
+ void onFailure(int status, String ssid, String channelList, in int[] bandArray);
/**
* Called when DPP events that indicate progress take place. Can be used by UI elements
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index b98d64dc78f1..5ab05834cd78 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -54,6 +54,7 @@ import android.text.TextUtils;
import android.util.CloseGuard;
import android.util.Log;
import android.util.Pair;
+import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -70,6 +71,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.StringTokenizer;
import java.util.concurrent.Executor;
/**
@@ -5177,6 +5179,7 @@ public class WifiManager {
@Override
public void onSuccessConfigReceived(int newNetworkId) {
Log.d(TAG, "Easy Connect onSuccessConfigReceived callback");
+ Binder.clearCallingIdentity();
mExecutor.execute(() -> {
mEasyConnectStatusCallback.onEnrolleeSuccess(newNetworkId);
});
@@ -5185,22 +5188,28 @@ public class WifiManager {
@Override
public void onSuccess(int status) {
Log.d(TAG, "Easy Connect onSuccess callback");
+ Binder.clearCallingIdentity();
mExecutor.execute(() -> {
mEasyConnectStatusCallback.onConfiguratorSuccess(status);
});
}
@Override
- public void onFailure(int status) {
+ public void onFailure(int status, String ssid, String channelList,
+ int[] operatingClassArray) {
Log.d(TAG, "Easy Connect onFailure callback");
+ Binder.clearCallingIdentity();
mExecutor.execute(() -> {
- mEasyConnectStatusCallback.onFailure(status);
+ SparseArray<int[]> channelListArray = parseDppChannelList(channelList);
+ mEasyConnectStatusCallback.onFailure(status, ssid, channelListArray,
+ operatingClassArray);
});
}
@Override
public void onProgress(int status) {
Log.d(TAG, "Easy Connect onProgress callback");
+ Binder.clearCallingIdentity();
mExecutor.execute(() -> {
mEasyConnectStatusCallback.onProgress(status);
});
@@ -5532,4 +5541,77 @@ public class WifiManager {
throw e.rethrowFromSystemServer();
}
}
+
+ /**
+ * Parse the list of channels the DPP enrollee reports when it fails to find an AP.
+ *
+ * @param channelList List of channels in the format defined in the DPP specification.
+ * @return A parsed sparse array, where the operating class is the key.
+ * @hide
+ */
+ @VisibleForTesting
+ public static SparseArray<int[]> parseDppChannelList(String channelList) {
+ SparseArray<int[]> channelListArray = new SparseArray<>();
+
+ if (TextUtils.isEmpty(channelList)) {
+ return channelListArray;
+ }
+ StringTokenizer str = new StringTokenizer(channelList, ",");
+ String classStr = null;
+ List<Integer> channelsInClass = new ArrayList<>();
+
+ try {
+ while (str.hasMoreElements()) {
+ String cur = str.nextToken();
+
+ /**
+ * Example for a channel list:
+ *
+ * 81/1,2,3,4,5,6,7,8,9,10,11,115/36,40,44,48,118/52,56,60,64,121/100,104,108,112,
+ * 116,120,124,128,132,136,140,0/144,124/149,153,157,161,125/165
+ *
+ * Detect operating class by the delimiter of '/' and use a string tokenizer with
+ * ',' as a delimiter.
+ */
+ int classDelim = cur.indexOf('/');
+ if (classDelim != -1) {
+ if (classStr != null) {
+ // Store the last channel array in the sparse array, where the operating
+ // class is the key (as an integer).
+ int[] channelsArray = new int[channelsInClass.size()];
+ for (int i = 0; i < channelsInClass.size(); i++) {
+ channelsArray[i] = channelsInClass.get(i);
+ }
+ channelListArray.append(Integer.parseInt(classStr), channelsArray);
+ channelsInClass = new ArrayList<>();
+ }
+
+ // Init a new operating class and store the first channel
+ classStr = cur.substring(0, classDelim);
+ String channelStr = cur.substring(classDelim + 1);
+ channelsInClass.add(Integer.parseInt(channelStr));
+ } else {
+ if (classStr == null) {
+ // Invalid format
+ Log.e(TAG, "Cannot parse DPP channel list");
+ return new SparseArray<>();
+ }
+ channelsInClass.add(Integer.parseInt(cur));
+ }
+ }
+
+ // Store the last array
+ if (classStr != null) {
+ int[] channelsArray = new int[channelsInClass.size()];
+ for (int i = 0; i < channelsInClass.size(); i++) {
+ channelsArray[i] = channelsInClass.get(i);
+ }
+ channelListArray.append(Integer.parseInt(classStr), channelsArray);
+ }
+ return channelListArray;
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "Cannot parse DPP channel list");
+ return new SparseArray<>();
+ }
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index 8fedda48aa0d..8badcc0c2552 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -724,21 +724,6 @@ public class WifiScanner {
public int min24GHzRssi;
/** Minimum 6GHz RSSI for a BSSID to be considered */
public int min6GHzRssi;
- /** Maximum score that a network can have before bonuses */
- public int initialScoreMax;
- /**
- * Only report when there is a network's score this much higher
- * than the current connection.
- */
- public int currentConnectionBonus;
- /** score bonus for all networks with the same network flag */
- public int sameNetworkBonus;
- /** score bonus for networks that are not open */
- public int secureBonus;
- /** 5GHz RSSI score bonus (applied to all 5GHz networks) */
- public int band5GHzBonus;
- /** 6GHz RSSI score bonus (applied to all 5GHz networks) */
- public int band6GHzBonus;
/** Pno Network filter list */
public PnoNetwork[] networkList;
@@ -753,12 +738,6 @@ public class WifiScanner {
dest.writeInt(min5GHzRssi);
dest.writeInt(min24GHzRssi);
dest.writeInt(min6GHzRssi);
- dest.writeInt(initialScoreMax);
- dest.writeInt(currentConnectionBonus);
- dest.writeInt(sameNetworkBonus);
- dest.writeInt(secureBonus);
- dest.writeInt(band5GHzBonus);
- dest.writeInt(band6GHzBonus);
if (networkList != null) {
dest.writeInt(networkList.length);
for (int i = 0; i < networkList.length; i++) {
@@ -781,12 +760,6 @@ public class WifiScanner {
settings.min5GHzRssi = in.readInt();
settings.min24GHzRssi = in.readInt();
settings.min6GHzRssi = in.readInt();
- settings.initialScoreMax = in.readInt();
- settings.currentConnectionBonus = in.readInt();
- settings.sameNetworkBonus = in.readInt();
- settings.secureBonus = in.readInt();
- settings.band5GHzBonus = in.readInt();
- settings.band6GHzBonus = in.readInt();
int numNetworks = in.readInt();
settings.networkList = new PnoNetwork[numNetworks];
for (int i = 0; i < numNetworks; i++) {
diff --git a/wifi/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java b/wifi/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java
new file mode 100644
index 000000000000..b10141434b0b
--- /dev/null
+++ b/wifi/tests/src/android/net/wifi/EasyConnectStatusCallbackTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.util.SparseArray;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link android.net.wifi.EasyConnectStatusCallbackTest}.
+ */
+@SmallTest
+public class EasyConnectStatusCallbackTest {
+ private EasyConnectStatusCallback mEasyConnectStatusCallback = new EasyConnectStatusCallback() {
+ @Override
+ public void onEnrolleeSuccess(int newNetworkId) {
+
+ }
+
+ @Override
+ public void onConfiguratorSuccess(int code) {
+
+ }
+
+ @Override
+ public void onProgress(int code) {
+
+ }
+
+ @Override
+ public void onFailure(int code) {
+ mOnFailureR1EventReceived = true;
+ mLastCode = code;
+ }
+ };
+ private boolean mOnFailureR1EventReceived;
+ private int mLastCode;
+
+ @Before
+ public void setUp() {
+ mOnFailureR1EventReceived = false;
+ mLastCode = 0;
+ }
+
+ /**
+ * Test that the legacy R1 onFailure is called by default if the R2 onFailure is not overridden
+ * by the app.
+ */
+ @Test
+ public void testR1OnFailureCalled() {
+
+ SparseArray<int[]> channelList = new SparseArray<>();
+ int[] channelArray = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
+
+ channelList.append(81, channelArray);
+ mEasyConnectStatusCallback.onFailure(
+ EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK,
+ "SomeSSID", channelList, new int[] {81});
+
+ assertTrue(mOnFailureR1EventReceived);
+ assertEquals(mLastCode,
+ EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK);
+ }
+}
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 4a46744a2d32..821661196f4f 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -89,6 +89,7 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.connectivity.WifiActivityEnergyInfo;
import android.os.test.TestLooper;
+import android.util.SparseArray;
import androidx.test.filters.SmallTest;
@@ -2089,4 +2090,63 @@ public class WifiManagerTest {
.thenReturn(new Long(~WifiManager.WIFI_FEATURE_WAPI));
assertFalse(mWifiManager.isWapiSupported());
}
+
+ /*
+ * Test that DPP channel list is parsed correctly
+ */
+ @Test
+ public void testparseDppChannelList() throws Exception {
+ String channelList = "81/1,2,3,4,5,6,7,8,9,10,11,115/36,40,44,48";
+ SparseArray<int[]> expectedResult = new SparseArray<>();
+ expectedResult.append(81, new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11});
+ expectedResult.append(115, new int[]{36, 40, 44, 48});
+
+ SparseArray<int[]> result = WifiManager.parseDppChannelList(channelList);
+ assertEquals(expectedResult.size(), result.size());
+
+ int index = 0;
+ int key;
+
+ // Compare the two primitive int arrays
+ do {
+ try {
+ key = result.keyAt(index);
+ } catch (java.lang.ArrayIndexOutOfBoundsException e) {
+ break;
+ }
+ int[] expected = expectedResult.get(key);
+ int[] output = result.get(key);
+ assertEquals(expected.length, output.length);
+ for (int i = 0; i < output.length; i++) {
+ assertEquals(expected[i], output[i]);
+ }
+ index++;
+ } while (true);
+ }
+
+ /*
+ * Test that DPP channel list parser gracefully fails for invalid input
+ */
+ @Test
+ public void testparseDppChannelListWithInvalidFormats() throws Exception {
+ String channelList = "1,2,3,4,5,6,7,8,9,10,11,36,40,44,48";
+ SparseArray<int[]> result = WifiManager.parseDppChannelList(channelList);
+ assertEquals(result.size(), 0);
+
+ channelList = "ajgalskgjalskjg3-09683dh";
+ result = WifiManager.parseDppChannelList(channelList);
+ assertEquals(result.size(), 0);
+
+ channelList = "13/abc,46////";
+ result = WifiManager.parseDppChannelList(channelList);
+ assertEquals(result.size(), 0);
+
+ channelList = "11/4,5,13/";
+ result = WifiManager.parseDppChannelList(channelList);
+ assertEquals(result.size(), 0);
+
+ channelList = "/24,6";
+ result = WifiManager.parseDppChannelList(channelList);
+ assertEquals(result.size(), 0);
+ }
}
diff --git a/wifi/tests/src/android/net/wifi/WifiScannerTest.java b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
index fa4f711056db..1af0bcbf3f30 100644
--- a/wifi/tests/src/android/net/wifi/WifiScannerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiScannerTest.java
@@ -80,12 +80,6 @@ public class WifiScannerTest {
private static final int TEST_PNOSETTINGS_MIN_5GHZ_RSSI = -60;
private static final int TEST_PNOSETTINGS_MIN_2GHZ_RSSI = -70;
private static final int TEST_PNOSETTINGS_MIN_6GHZ_RSSI = -55;
- private static final int TEST_PNOSETTINGS_INITIAL_SCORE_MAX = 50;
- private static final int TEST_PNOSETTINGS_CURRENT_CONNECTION_BONUS = 10;
- private static final int TEST_PNOSETTINGS_SAME_NETWORK_BONUS = 11;
- private static final int TEST_PNOSETTINGS_SECURE_BONUS = 12;
- private static final int TEST_PNOSETTINGS_BAND_5GHZ_BONUS = 13;
- private static final int TEST_PNOSETTINGS_BAND_6GHZ_BONUS = 15;
private static final String TEST_SSID_1 = "TEST1";
private static final String TEST_SSID_2 = "TEST2";
private static final int[] TEST_FREQUENCIES_1 = {};
@@ -186,12 +180,6 @@ public class WifiScannerTest {
pnoSettings.min5GHzRssi = TEST_PNOSETTINGS_MIN_5GHZ_RSSI;
pnoSettings.min24GHzRssi = TEST_PNOSETTINGS_MIN_2GHZ_RSSI;
pnoSettings.min6GHzRssi = TEST_PNOSETTINGS_MIN_6GHZ_RSSI;
- pnoSettings.initialScoreMax = TEST_PNOSETTINGS_INITIAL_SCORE_MAX;
- pnoSettings.currentConnectionBonus = TEST_PNOSETTINGS_CURRENT_CONNECTION_BONUS;
- pnoSettings.sameNetworkBonus = TEST_PNOSETTINGS_SAME_NETWORK_BONUS;
- pnoSettings.secureBonus = TEST_PNOSETTINGS_SECURE_BONUS;
- pnoSettings.band5GHzBonus = TEST_PNOSETTINGS_BAND_5GHZ_BONUS;
- pnoSettings.band6GHzBonus = TEST_PNOSETTINGS_BAND_6GHZ_BONUS;
Parcel parcel = Parcel.obtain();
pnoSettings.writeToParcel(parcel, 0);
@@ -205,14 +193,6 @@ public class WifiScannerTest {
assertEquals(TEST_PNOSETTINGS_MIN_5GHZ_RSSI, pnoSettingsDeserialized.min5GHzRssi);
assertEquals(TEST_PNOSETTINGS_MIN_2GHZ_RSSI, pnoSettingsDeserialized.min24GHzRssi);
assertEquals(TEST_PNOSETTINGS_MIN_6GHZ_RSSI, pnoSettingsDeserialized.min6GHzRssi);
- assertEquals(TEST_PNOSETTINGS_INITIAL_SCORE_MAX, pnoSettingsDeserialized.initialScoreMax);
- assertEquals(TEST_PNOSETTINGS_CURRENT_CONNECTION_BONUS,
- pnoSettingsDeserialized.currentConnectionBonus);
- assertEquals(TEST_PNOSETTINGS_SAME_NETWORK_BONUS,
- pnoSettingsDeserialized.sameNetworkBonus);
- assertEquals(TEST_PNOSETTINGS_SECURE_BONUS, pnoSettingsDeserialized.secureBonus);
- assertEquals(TEST_PNOSETTINGS_BAND_5GHZ_BONUS, pnoSettingsDeserialized.band5GHzBonus);
- assertEquals(TEST_PNOSETTINGS_BAND_6GHZ_BONUS, pnoSettingsDeserialized.band6GHzBonus);
// Test parsing of PnoNetwork
assertEquals(pnoSettings.networkList.length, pnoSettingsDeserialized.networkList.length);