summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp9
-rw-r--r--PREUPLOAD.cfg2
-rw-r--r--apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java2
-rw-r--r--apct-tests/perftests/surfaceflinger/AndroidTest.xml12
-rw-r--r--apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java176
-rw-r--r--apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java2
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobInfo.java4
-rw-r--r--apex/jobscheduler/framework/java/android/app/job/JobScheduler.java17
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java38
-rw-r--r--cmds/abx/Android.bp7
-rwxr-xr-xcmds/abx/abx.sh (renamed from cmds/abx/abx)0
-rwxr-xr-xcmds/abx/abx2xml.sh (renamed from cmds/abx/abx2xml)0
-rwxr-xr-xcmds/abx/xml2abx.sh (renamed from cmds/abx/xml2abx)0
-rw-r--r--cmds/bmgr/Android.bp2
-rwxr-xr-xcmds/bmgr/bmgr.sh (renamed from cmds/bmgr/bmgr)0
-rw-r--r--cmds/bu/Android.bp2
-rwxr-xr-xcmds/bu/bu.sh (renamed from cmds/bu/bu)0
-rw-r--r--cmds/content/Android.bp2
-rwxr-xr-xcmds/content/content.sh (renamed from cmds/content/content)0
-rw-r--r--cmds/device_config/Android.bp2
-rwxr-xr-xcmds/device_config/device_config.sh (renamed from cmds/device_config/device_config)0
-rw-r--r--cmds/dpm/Android.bp2
-rwxr-xr-xcmds/dpm/dpm.sh (renamed from cmds/dpm/dpm)0
-rw-r--r--cmds/hid/Android.bp2
-rwxr-xr-xcmds/hid/hid.sh (renamed from cmds/hid/hid)0
-rw-r--r--cmds/ime/Android.bp2
-rwxr-xr-xcmds/ime/ime.sh (renamed from cmds/ime/ime)0
-rw-r--r--cmds/input/Android.bp2
-rwxr-xr-xcmds/input/input.sh (renamed from cmds/input/input)0
-rw-r--r--cmds/locksettings/Android.bp2
-rwxr-xr-xcmds/locksettings/locksettings.sh (renamed from cmds/locksettings/locksettings)0
-rw-r--r--cmds/pm/Android.bp2
-rwxr-xr-xcmds/pm/pm.sh (renamed from cmds/pm/pm)0
-rw-r--r--cmds/requestsync/Android.bp2
-rwxr-xr-xcmds/requestsync/requestsync.sh (renamed from cmds/requestsync/requestsync)0
-rw-r--r--cmds/settings/Android.bp2
-rwxr-xr-xcmds/settings/settings.sh (renamed from cmds/settings/settings)0
-rw-r--r--cmds/sm/Android.bp2
-rwxr-xr-xcmds/sm/sm.sh (renamed from cmds/sm/sm)0
-rw-r--r--cmds/svc/Android.bp2
-rwxr-xr-xcmds/svc/svc.sh (renamed from cmds/svc/svc)0
-rw-r--r--cmds/telecom/Android.bp2
-rwxr-xr-xcmds/telecom/telecom.sh (renamed from cmds/telecom/telecom)0
-rw-r--r--cmds/uiautomator/cmds/uiautomator/Android.bp2
-rwxr-xr-xcmds/uiautomator/cmds/uiautomator/uiautomator.sh (renamed from cmds/uiautomator/cmds/uiautomator/uiautomator)0
-rw-r--r--cmds/uinput/Android.bp7
-rwxr-xr-xcmds/uinput/uinput.sh (renamed from cmds/uinput/uinput)0
-rw-r--r--cmds/vr/Android.bp2
-rwxr-xr-xcmds/vr/vr.sh (renamed from cmds/vr/vr)0
-rw-r--r--cmds/wm/Android.bp2
-rwxr-xr-xcmds/wm/wm.sh (renamed from cmds/wm/wm)0
-rw-r--r--core/api/current.txt5
-rw-r--r--core/api/system-current.txt32
-rw-r--r--core/api/test-current.txt13
-rw-r--r--core/java/android/app/NotificationChannel.java2
-rw-r--r--core/java/android/app/VoiceInteractor.java6
-rw-r--r--core/java/android/app/admin/PreferentialNetworkServiceConfig.java11
-rw-r--r--core/java/android/app/ambientcontext/AmbientContextCallback.java47
-rw-r--r--core/java/android/app/ambientcontext/AmbientContextEvent.java19
-rw-r--r--core/java/android/app/ambientcontext/AmbientContextManager.java68
-rw-r--r--core/java/android/app/ambientcontext/IAmbientContextManager.aidl6
-rw-r--r--core/java/android/app/ambientcontext/IAmbientContextObserver.aidl30
-rw-r--r--core/java/android/companion/BluetoothLeDeviceFilter.java7
-rw-r--r--core/java/android/content/AttributionSource.java11
-rw-r--r--core/java/android/content/pm/ActivityInfo.java11
-rw-r--r--core/java/android/content/pm/LauncherApps.java12
-rw-r--r--core/java/android/content/pm/ShortcutInfo.java3
-rw-r--r--core/java/android/content/res/GradientColor.java16
-rw-r--r--core/java/android/hardware/HardwareBuffer.aidl2
-rw-r--r--core/java/android/hardware/biometrics/IBiometricContextListener.aidl5
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java13
-rw-r--r--core/java/android/hardware/radio/ProgramSelector.java8
-rw-r--r--core/java/android/hardware/radio/RadioManager.java5
-rw-r--r--core/java/android/metrics/LogMaker.java3
-rw-r--r--core/java/android/os/BatteryStats.java76
-rw-r--r--core/java/android/os/GraphicsEnvironment.java19
-rw-r--r--core/java/android/os/StrictMode.java28
-rw-r--r--core/java/android/os/VibrationAttributes.java5
-rw-r--r--core/java/android/os/incremental/IncrementalStorage.java3
-rw-r--r--core/java/android/os/strictmode/ExplicitGcViolation.java3
-rw-r--r--core/java/android/service/autofill/OptionalValidators.java5
-rw-r--r--core/java/android/service/autofill/RequiredValidators.java5
-rw-r--r--core/java/android/service/voice/VoiceInteractionSession.java3
-rw-r--r--core/java/android/speech/tts/FileSynthesisCallback.java5
-rw-r--r--core/java/android/util/ArrayMap.java17
-rw-r--r--core/java/android/util/ArraySet.java15
-rw-r--r--core/java/android/util/proto/ProtoInputStream.java33
-rw-r--r--core/java/android/util/proto/ProtoUtils.java23
-rw-r--r--core/java/android/view/FrameMetrics.java6
-rw-r--r--core/java/android/view/GestureDetector.java5
-rw-r--r--core/java/android/view/SurfaceControl.java2
-rw-r--r--core/java/android/window/WindowContainerTransaction.java21
-rw-r--r--core/java/com/android/internal/inputmethod/InputMethodDebug.java2
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHistory.java53
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHistoryIterator.java35
-rw-r--r--core/java/com/android/internal/widget/LocalImageResolver.java65
-rw-r--r--core/java/com/android/internal/widget/LockscreenCredential.java3
-rw-r--r--core/jni/OWNERS4
-rw-r--r--core/jni/com_android_internal_content_NativeLibraryHelper.cpp97
-rw-r--r--core/jni/com_android_internal_security_VerityUtils.cpp6
-rw-r--r--core/proto/android/app/notificationmanager.proto2
-rw-r--r--core/res/AndroidManifest.xml24
-rw-r--r--core/res/res/values/config.xml13
-rw-r--r--core/res/res/values/strings.xml2
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/android/provider/FontsContractTest.java25
-rw-r--r--core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java47
-rw-r--r--data/etc/services.core.protolog.json36
-rw-r--r--graphics/java/android/graphics/ColorSpace.java3
-rw-r--r--ktfmt_includes.txt17
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java3
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java8
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java4
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java12
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java21
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java12
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_education_ic_light_bulb.xml (renamed from libs/WindowManager/Shell/res/drawable/letterbox_education_ic_letterboxed_app.xml)15
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml16
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_education_ic_screen_rotation.xml26
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml18
-rw-r--r--libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml2
-rw-r--r--libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml33
-rw-r--r--libs/WindowManager/Shell/res/values/dimen.xml13
-rw-r--r--libs/WindowManager/Shell/res/values/strings.xml11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java54
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java57
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt29
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/LaunchBubbleHelper.kt1
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt40
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt24
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt38
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt21
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt23
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt3
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt20
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt21
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt21
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt21
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java3
-rw-r--r--libs/hwui/Android.bp6
-rw-r--r--libs/hwui/SkiaCanvas.cpp86
-rw-r--r--media/Android.bp8
-rw-r--r--media/java/android/media/AudioDeviceVolumeManager.java29
-rw-r--r--media/java/android/media/AudioSystem.java6
-rw-r--r--media/java/android/media/MediaPlayer.java32
-rw-r--r--media/java/android/media/VolumeInfo.java8
-rw-r--r--media/java/android/media/audiopolicy/AudioProductStrategy.java5
-rw-r--r--media/java/android/media/audiopolicy/AudioVolumeGroup.java2
-rw-r--r--media/java/android/media/metrics/PlaybackMetrics.java7
-rw-r--r--media/java/android/media/session/ISession.aidl2
-rw-r--r--media/java/android/media/session/MediaSession.java2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraErrorCollector.java20
-rw-r--r--opengl/java/android/opengl/GLLogWrapper.java70
-rw-r--r--packages/SettingsLib/Spa/build.gradle4
-rw-r--r--packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/SpaEnvironment.kt6
-rw-r--r--packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt6
-rw-r--r--packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferenceMain.kt52
-rw-r--r--packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePage.kt (renamed from packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PreferencePage.kt)2
-rw-r--r--packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt (renamed from packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SwitchPreferencePage.kt)2
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt7
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt (renamed from packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListModel.kt)36
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java6
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java10
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java3
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java13
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java19
-rw-r--r--packages/SystemUI/AndroidManifest.xml2
-rw-r--r--packages/SystemUI/ktfmt_includes.txt870
-rw-r--r--packages/SystemUI/res-keyguard/values/strings.xml2
-rw-r--r--packages/SystemUI/res/layout/dream_overlay_media_entry_chip.xml29
-rw-r--r--packages/SystemUI/res/layout/media_ttt_chip.xml4
-rw-r--r--packages/SystemUI/res/layout/sidefps_view.xml2
-rw-r--r--packages/SystemUI/res/values/ids.xml4
-rw-r--r--packages/SystemUI/res/values/strings.xml4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/ScreenDecorations.java200
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java63
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt60
-rw-r--r--packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt65
-rw-r--r--packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt70
-rw-r--r--packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/complication/DreamMediaEntryComplication.java135
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamMediaEntryComplicationComponent.java81
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipRootView.kt38
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/PanelView.java75
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java61
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java77
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt49
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java206
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java84
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java97
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt70
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/OWNERS4
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java27
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java282
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java45
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt200
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamMediaEntryComplicationTest.java94
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt82
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt45
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt54
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java27
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java123
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java302
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt151
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt34
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt79
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java4
-rw-r--r--services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java2
-rw-r--r--services/backup/java/com/android/server/backup/UserBackupManagerService.java2
-rw-r--r--services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java7
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java3
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java3
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java89
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerShellCommand.java7
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java82
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueueImpl.java37
-rw-r--r--services/core/java/com/android/server/am/ContentProviderHelper.java3
-rw-r--r--services/core/java/com/android/server/am/DropboxRateLimiter.java11
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java9
-rw-r--r--services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java86
-rw-r--r--services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java81
-rw-r--r--services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java38
-rw-r--r--services/core/java/com/android/server/appop/DiscreteRegistry.java3
-rw-r--r--services/core/java/com/android/server/audio/BtHelper.java4
-rw-r--r--services/core/java/com/android/server/backup/BackupUtils.java6
-rw-r--r--services/core/java/com/android/server/biometrics/log/BiometricContext.java3
-rw-r--r--services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java27
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java36
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java4
-rw-r--r--services/core/java/com/android/server/display/BrightnessMappingStrategy.java6
-rw-r--r--services/core/java/com/android/server/display/DisplayControl.java55
-rw-r--r--services/core/java/com/android/server/display/DisplayDeviceConfig.java113
-rw-r--r--services/core/java/com/android/server/display/OverlayDisplayAdapter.java4
-rw-r--r--services/core/java/com/android/server/display/VirtualDisplayAdapter.java5
-rw-r--r--services/core/java/com/android/server/display/WifiDisplayAdapter.java4
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java2
-rw-r--r--services/core/java/com/android/server/logcat/LogcatManagerService.java27
-rw-r--r--services/core/java/com/android/server/media/MediaButtonReceiverHolder.java7
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java16
-rw-r--r--services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java5
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java11
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerInternalBase.java6
-rw-r--r--services/core/java/com/android/server/pm/UserManagerInternal.java11
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java17
-rw-r--r--services/core/java/com/android/server/pm/dex/DexManager.java46
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java84
-rw-r--r--services/core/java/com/android/server/power/LowPowerStandbyController.java18
-rw-r--r--services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java5
-rw-r--r--services/core/java/com/android/server/power/stats/BatteryStatsImpl.java10
-rw-r--r--services/core/java/com/android/server/power/stats/MeasuredEnergySnapshot.java143
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java44
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java11
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java92
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java12
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java21
-rw-r--r--services/core/java/com/android/server/wm/Task.java32
-rw-r--r--services/core/java/com/android/server/wm/TaskPersister.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java51
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java7
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfacePlacer.java2
-rw-r--r--services/core/jni/Android.bp3
-rw-r--r--services/core/jni/com_android_server_display_DisplayControl.cpp52
-rw-r--r--services/core/jni/onload.cpp2
-rw-r--r--services/core/xsd/display-device-config/autobrightness.xsd33
-rw-r--r--services/core/xsd/display-device-config/display-device-config.xsd71
-rw-r--r--services/core/xsd/display-device-config/schema/current.txt15
-rw-r--r--services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java1
-rw-r--r--services/tests/mockingservicestests/jni/Android.bp3
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java304
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java6
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java41
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/ambientcontext/AmbientContextManagerServiceTest.java16
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java59
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java37
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java105
-rw-r--r--services/tests/servicestests/src/com/android/server/logcat/LogcatManagerServiceTest.java28
-rw-r--r--services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java126
-rw-r--r--services/tests/servicestests/src/com/android/server/power/stats/MeasuredEnergySnapshotTest.java12
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/CombinationKeyTests.java78
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/KeyCombinationManagerTests.java (renamed from services/tests/wmtests/src/com/android/server/policy/KeyCombinationTests.java)6
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java98
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java169
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java371
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java69
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTransactionTests.java89
-rw-r--r--services/usage/java/com/android/server/usage/AppTimeLimitController.java4
-rw-r--r--telecomm/java/android/telecom/DisconnectCause.java4
-rwxr-xr-xtelephony/common/com/google/android/mms/pdu/PduParser.java2
-rw-r--r--telephony/java/android/telephony/PhysicalChannelConfig.java3
-rw-r--r--telephony/java/android/telephony/SignalThresholdInfo.java4
-rw-r--r--telephony/java/android/telephony/SmsManager.java4
-rw-r--r--telephony/java/android/telephony/SubscriptionInfo.java6
-rw-r--r--telephony/java/android/telephony/TelephonyScanManager.java2
-rw-r--r--tests/HandwritingIme/src/com/google/android/test/handwritingime/HandwritingIme.java121
-rw-r--r--tests/HandwritingIme/src/com/google/android/test/handwritingime/InkView.java2
-rw-r--r--tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java4
-rw-r--r--tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java5
-rw-r--r--tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java5
-rw-r--r--tools/aapt2/Debug.cpp4
-rw-r--r--tools/aapt2/format/binary/TableFlattener.cpp10
-rw-r--r--tools/aapt2/format/binary/TableFlattener_test.cpp44
365 files changed, 7174 insertions, 3208 deletions
diff --git a/Android.bp b/Android.bp
index c0a70b99827e..2c550fdfb675 100644
--- a/Android.bp
+++ b/Android.bp
@@ -428,6 +428,15 @@ java_library {
name: "framework-minus-apex-intdefs",
defaults: ["framework-minus-apex-defaults"],
plugins: ["intdef-annotation-processor"],
+
+ // Errorprone and android lint will already run on framework-minus-apex, don't rerun them on
+ // the intdefs version in order to speed up the build.
+ errorprone: {
+ enabled: false,
+ },
+ lint: {
+ enabled: false,
+ },
}
// This "framework" module is NOT installed to the device. It's
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 1d92778a9117..9a4323a119f0 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -25,6 +25,6 @@ hidden_api_txt_checksorted_hook = ${REPO_ROOT}/tools/platform-compat/hiddenapi/c
hidden_api_txt_exclude_hook = ${REPO_ROOT}/frameworks/base/tools/hiddenapi/exclude.sh ${PREUPLOAD_COMMIT} ${REPO_ROOT}
-ktfmt_hook = ${REPO_ROOT}/external/ktfmt/ktfmt.py --check -i ${REPO_ROOT}/frameworks/base/ktfmt_includes.txt ${PREUPLOAD_FILES}
+ktfmt_hook = ${REPO_ROOT}/external/ktfmt/ktfmt.py --check -i ${REPO_ROOT}/frameworks/base/packages/SystemUI/ktfmt_includes.txt ${PREUPLOAD_FILES}
ktlint_hook = ${REPO_ROOT}/prebuilts/ktlint/ktlint.py -f ${PREUPLOAD_FILES}
diff --git a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
index 3781b6dcf162..03e5468a342a 100644
--- a/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
+++ b/apct-tests/perftests/blobstore/src/com/android/perftests/blob/BlobStorePerfTests.java
@@ -257,7 +257,7 @@ public class BlobStorePerfTests {
runShellCommand(String.format(
"cmd blob_store delete-blob --algo %s --digest %s --label %s --expiry %d --tag %s",
blobHandle.algorithm,
- Base64.getEncoder().encode(blobHandle.digest),
+ Base64.getEncoder().encodeToString(blobHandle.digest),
blobHandle.label,
blobHandle.expiryTimeMillis,
blobHandle.tag));
diff --git a/apct-tests/perftests/surfaceflinger/AndroidTest.xml b/apct-tests/perftests/surfaceflinger/AndroidTest.xml
index 0f3a0681f85e..53e5d99409e2 100644
--- a/apct-tests/perftests/surfaceflinger/AndroidTest.xml
+++ b/apct-tests/perftests/surfaceflinger/AndroidTest.xml
@@ -44,7 +44,7 @@
<option name="hidden-api-checks" value="false"/>
<!-- Listener related args for collecting the traces and waiting for the device to stabilize. -->
- <option name="device-listeners" value="android.device.collectors.PerfettoListener,android.device.collectors.SimpleperfListener" />
+ <option name="device-listeners" value="android.device.collectors.ProcLoadListener,android.device.collectors.PerfettoListener,android.device.collectors.SimpleperfListener" />
<!-- Guarantee that user defined RunListeners will be running before any of the default listeners defined in this runner. -->
<option name="instrumentation-arg" key="newRunListenerMode" value="true" />
@@ -58,7 +58,15 @@
<option name="instrumentation-arg" key="arguments" value="&quot;&quot;" />
<option name="instrumentation-arg" key="events_to_record" value="instructions,cpu-cycles,raw-l3d-cache-refill,sched:sched_waking" />
<option name="instrumentation-arg" key="processes_to_record" value="surfaceflinger" />
- <option name="instrumentation-arg" key="symbols_to_report" value="&quot;android::SurfaceFlinger::commit(long, long, long)&quot;" />
+ <option name="instrumentation-arg" key="symbols_to_report" value="&quot;android::SurfaceFlinger::commit(;android::SurfaceFlinger::composite(&quot;" />
+
+ <!-- ProcLoadListener related arguments -->
+ <!-- Wait for device last minute threshold to reach 3 with 2 minute timeout before starting the test run -->
+ <option name="instrumentation-arg" key="procload-collector:per_run" value="true" />
+ <option name="instrumentation-arg" key="proc-loadavg-threshold" value="3" />
+ <option name="instrumentation-arg" key="proc-loadavg-timeout" value="120000" />
+ <option name="instrumentation-arg" key="proc-loadavg-interval" value="10000" />
+
</test>
<metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
diff --git a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java
index f4d0c053fb66..45d164c96cd8 100644
--- a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java
+++ b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java
@@ -16,6 +16,7 @@
package android.surfaceflinger;
+import android.graphics.Bitmap;
import android.graphics.Color;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
@@ -23,14 +24,19 @@ import android.view.SurfaceControl;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import androidx.test.filters.LargeTest;
+import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.RuleChain;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
+import java.util.Random;
+
@LargeTest
@RunWith(AndroidJUnit4.class)
public class SurfaceFlingerPerfTest {
@@ -48,19 +54,175 @@ public class SurfaceFlingerPerfTest {
public void setup() {
mActivityRule.getScenario().onActivity(activity -> mActivity = activity);
}
+
+ @After
+ public void teardown() {
+ mSurfaceControls.forEach(SurfaceControl::release);
+ mByfferTrackers.forEach(BufferFlinger::freeBuffers);
+ }
+
+
+ private ArrayList<BufferFlinger> mByfferTrackers = new ArrayList<>();
+ private BufferFlinger createBufferTracker(int color) {
+ BufferFlinger bufferTracker = new BufferFlinger(BUFFER_COUNT, color);
+ mByfferTrackers.add(bufferTracker);
+ return bufferTracker;
+ }
+
+ private ArrayList<SurfaceControl> mSurfaceControls = new ArrayList<>();
+ private SurfaceControl createSurfaceControl() throws InterruptedException {
+ SurfaceControl sc = mActivity.createChildSurfaceControl();
+ mSurfaceControls.add(sc);
+ return sc;
+ }
+
@Test
- public void submitSingleBuffer() throws Exception {
- SurfaceControl sc = mActivity.getChildSurfaceControl();
+ public void singleBuffer() throws Exception {
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
- BufferFlinger bufferflinger = new BufferFlinger(BUFFER_COUNT, Color.GREEN);
- BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ bufferTracker.addBuffer(t, sc);
t.show(sc);
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
while (state.keepRunning()) {
- bufferflinger.addBuffer(t, sc);
+ bufferTracker.addBuffer(t, sc);
t.apply();
}
- bufferflinger.freeBuffers();
}
-}
+ static int getRandomColorComponent() {
+ return new Random().nextInt(155) + 100;
+ }
+
+ @Test
+ public void multipleBuffers() throws Exception {
+ final int MAX_BUFFERS = 10;
+
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.argb(getRandomColorComponent(),
+ getRandomColorComponent(), getRandomColorComponent(),
+ getRandomColorComponent()));
+ bufferTracker.addBuffer(t, sc);
+ t.setPosition(sc, i * 10, i * 10);
+ t.show(sc);
+ }
+ t.apply(true);
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ mByfferTrackers.get(i).addBuffer(t, mSurfaceControls.get(i));
+ }
+ t.apply();
+ }
+ }
+
+ @Test
+ public void multipleOpaqueBuffers() throws Exception {
+ final int MAX_BUFFERS = 10;
+
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.rgb(getRandomColorComponent(),
+ getRandomColorComponent(), getRandomColorComponent()));
+ bufferTracker.addBuffer(t, sc);
+ t.setOpaque(sc, true);
+ t.setPosition(sc, i * 10, i * 10);
+ t.show(sc);
+ }
+ t.apply(true);
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ mByfferTrackers.get(i).addBuffer(t, mSurfaceControls.get(i));
+ }
+ t.apply();
+ }
+ }
+
+ @Test
+ public void geometryChanges() throws Exception {
+ final int MAX_POSITION = 10;
+ final float MAX_SCALE = 2.0f;
+
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ bufferTracker.addBuffer(t, sc);
+ t.show(sc).apply(true);
+
+ int step = 0;
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ step = ++step % MAX_POSITION;
+ t.setPosition(sc, step, step);
+ float scale = ((step * MAX_SCALE) / MAX_POSITION) + 0.5f;
+ t.setScale(sc, scale, scale);
+ t.apply();
+ }
+ }
+
+ @Test
+ public void geometryWithBufferChanges() throws Exception {
+ final int MAX_POSITION = 10;
+
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ bufferTracker.addBuffer(t, sc);
+ t.show(sc).apply(true);
+
+ int step = 0;
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ step = ++step % MAX_POSITION;
+ t.setPosition(sc, step, step);
+ float scale = ((step * 2.0f) / MAX_POSITION) + 0.5f;
+ t.setScale(sc, scale, scale);
+ bufferTracker.addBuffer(t, sc);
+ t.apply();
+ }
+ }
+
+ @Test
+ public void addRemoveLayers() throws Exception {
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ SurfaceControl childSurfaceControl = new SurfaceControl.Builder()
+ .setName("childLayer").setBLASTLayer().build();
+ bufferTracker.addBuffer(t, childSurfaceControl);
+ t.reparent(childSurfaceControl, sc);
+ t.apply();
+ t.remove(childSurfaceControl).apply();
+ }
+ }
+
+ @Test
+ public void displayScreenshot() throws Exception {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Bitmap screenshot =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation().takeScreenshot();
+ screenshot.recycle();
+ }
+ }
+
+ @Test
+ public void layerScreenshot() throws Exception {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Bitmap screenshot =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation().takeScreenshot(
+ mActivity.getWindow());
+ screenshot.recycle();
+ }
+ }
+
+}
diff --git a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java
index a9b2a3118bc1..832a0cd1e917 100644
--- a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java
+++ b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java
@@ -43,7 +43,7 @@ public class SurfaceFlingerTestActivity extends Activity {
setContentView(mTestSurfaceView);
}
- public SurfaceControl getChildSurfaceControl() throws InterruptedException {
+ public SurfaceControl createChildSurfaceControl() throws InterruptedException {
return mTestSurfaceView.getChildSurfaceControlHelper();
}
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index f49cdbf403f0..ab0ac5aa8856 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -1312,6 +1312,9 @@ public class JobInfo implements Parcelable {
* Calling this method will override any requirements previously defined
* by {@link #setRequiredNetwork(NetworkRequest)}; you typically only
* want to call one of these methods.
+ * <p> Starting in Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+ * {@link JobScheduler} may try to shift the execution of jobs requiring
+ * {@link #NETWORK_TYPE_ANY} to when there is access to an un-metered network.
* <p class="note">
* When your job executes in
* {@link JobService#onStartJob(JobParameters)}, be sure to use the
@@ -1742,6 +1745,7 @@ public class JobInfo implements Parcelable {
* <li>Bypass Doze, app standby, and battery saver network restrictions</li>
* <li>Be less likely to be killed than regular jobs</li>
* <li>Be subject to background location throttling</li>
+ * <li>Be exempt from delay to optimize job execution</li>
* </ol>
*
* <p>
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
index 632ecb2c0381..dfdb29091ad9 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
@@ -45,8 +45,23 @@ import java.util.List;
* </p>
* <p>
* The framework will be intelligent about when it executes jobs, and attempt to batch
- * and defer them as much as possible. Typically if you don't specify a deadline on a job, it
+ * and defer them as much as possible. Typically, if you don't specify a deadline on a job, it
* can be run at any moment depending on the current state of the JobScheduler's internal queue.
+ * </p>
+ * <p>
+ * Starting in Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
+ * JobScheduler may try to optimize job execution by shifting execution to times with more available
+ * system resources in order to lower user impact. Factors in system health include sufficient
+ * battery, idle, charging, and access to an un-metered network. Jobs will initially be treated as
+ * if they have all these requirements, but as their deadlines approach, restrictions will become
+ * less strict. Requested requirements will not be affected by this change.
+ * </p>
+ *
+ * {@see android.app.job.JobInfo.Builder#setRequiresBatteryNotLow(boolean)}
+ * {@see android.app.job.JobInfo.Builder#setRequiresDeviceIdle(boolean)}
+ * {@see android.app.job.JobInfo.Builder#setRequiresCharging(boolean)}
+ * {@see android.app.job.JobInfo.Builder#setRequiredNetworkType(int)}
+ *
* <p>
* While a job is running, the system holds a wakelock on behalf of your app. For this reason,
* you do not need to take any action to guarantee that the device stays awake for the
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
index 448a808ff52f..e7f03279e1b0 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -43,6 +43,7 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.database.ContentObserver;
import android.net.Uri;
+import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
import android.os.Binder;
import android.os.Handler;
@@ -163,6 +164,7 @@ public class InternalResourceService extends SystemService {
@GuardedBy("mLock")
private final SparseArrayMap<String, Boolean> mVipOverrides = new SparseArrayMap<>();
+ private volatile boolean mHasBattery = true;
private volatile boolean mIsEnabled;
private volatile int mBootPhase;
private volatile boolean mExemptListLoaded;
@@ -204,6 +206,15 @@ public class InternalResourceService extends SystemService {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
+ case Intent.ACTION_BATTERY_CHANGED: {
+ final boolean hasBattery =
+ intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, mHasBattery);
+ if (mHasBattery != hasBattery) {
+ mHasBattery = hasBattery;
+ mConfigObserver.updateEnabledStatus();
+ }
+ }
+ break;
case Intent.ACTION_BATTERY_LEVEL_CHANGED:
onBatteryLevelChanged();
break;
@@ -713,6 +724,12 @@ public class InternalResourceService extends SystemService {
return packages;
}
+ private boolean isTareSupported() {
+ // TARE is presently designed for devices with batteries. Don't enable it on
+ // battery-less devices for now.
+ return mHasBattery;
+ }
+
@GuardedBy("mLock")
private void loadInstalledPackageListLocked() {
mPkgCache.clear();
@@ -731,6 +748,7 @@ public class InternalResourceService extends SystemService {
private void registerListeners() {
final IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(Intent.ACTION_BATTERY_LEVEL_CHANGED);
filter.addAction(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
@@ -765,6 +783,7 @@ public class InternalResourceService extends SystemService {
return;
}
synchronized (mLock) {
+ mCompleteEconomicPolicy.setup(mConfigObserver.getAllDeviceConfigProperties());
loadInstalledPackageListLocked();
final boolean isFirstSetup = !mScribe.recordExists();
if (isFirstSetup) {
@@ -803,10 +822,7 @@ public class InternalResourceService extends SystemService {
if (mBootPhase < PHASE_THIRD_PARTY_APPS_CAN_START || !mIsEnabled) {
return;
}
- synchronized (mLock) {
- mHandler.post(this::setupHeavyWork);
- mCompleteEconomicPolicy.setup(mConfigObserver.getAllDeviceConfigProperties());
- }
+ mHandler.post(this::setupHeavyWork);
}
private void onBootPhaseBootCompleted() {
@@ -985,7 +1001,7 @@ public class InternalResourceService extends SystemService {
@Override
public void registerAffordabilityChangeListener(int userId, @NonNull String pkgName,
@NonNull AffordabilityChangeListener listener, @NonNull ActionBill bill) {
- if (isSystem(userId, pkgName)) {
+ if (!isTareSupported() || isSystem(userId, pkgName)) {
// The system's affordability never changes.
return;
}
@@ -1008,6 +1024,9 @@ public class InternalResourceService extends SystemService {
@Override
public void registerTareStateChangeListener(@NonNull TareStateChangeListener listener) {
+ if (!isTareSupported()) {
+ return;
+ }
mStateChangeListeners.add(listener);
}
@@ -1180,11 +1199,10 @@ public class InternalResourceService extends SystemService {
private void updateEnabledStatus() {
// User setting should override DeviceConfig setting.
- // NOTE: There's currently no way for a user to reset the value (via UI), so if a user
- // manually toggles TARE via UI, we'll always defer to the user's current setting
final boolean isTareEnabledDC = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_TARE,
KEY_DC_ENABLE_TARE, Settings.Global.DEFAULT_ENABLE_TARE == 1);
- final boolean isTareEnabled = Settings.Global.getInt(mContentResolver,
+ final boolean isTareEnabled = isTareSupported()
+ && Settings.Global.getInt(mContentResolver,
Settings.Global.ENABLE_TARE, isTareEnabledDC ? 1 : 0) == 1;
if (mIsEnabled != isTareEnabled) {
mIsEnabled = isTareEnabled;
@@ -1268,6 +1286,10 @@ public class InternalResourceService extends SystemService {
}
private void dumpInternal(final IndentingPrintWriter pw, final boolean dumpAll) {
+ if (!isTareSupported()) {
+ pw.print("Unsupported by device");
+ return;
+ }
synchronized (mLock) {
pw.print("Is enabled: ");
pw.println(mIsEnabled);
diff --git a/cmds/abx/Android.bp b/cmds/abx/Android.bp
index 50a0b75b3276..a832dea20673 100644
--- a/cmds/abx/Android.bp
+++ b/cmds/abx/Android.bp
@@ -1,4 +1,3 @@
-
package {
default_applicable_licenses: ["frameworks_base_cmds_abx_license"],
}
@@ -18,7 +17,7 @@ license {
java_binary {
name: "abx",
- wrapper: "abx",
+ wrapper: "abx.sh",
srcs: ["**/*.java"],
required: [
"abx2xml",
@@ -28,10 +27,10 @@ java_binary {
sh_binary {
name: "abx2xml",
- src: "abx2xml",
+ src: "abx2xml.sh",
}
sh_binary {
name: "xml2abx",
- src: "xml2abx",
+ src: "xml2abx.sh",
}
diff --git a/cmds/abx/abx b/cmds/abx/abx.sh
index 0a9362d64398..0a9362d64398 100755
--- a/cmds/abx/abx
+++ b/cmds/abx/abx.sh
diff --git a/cmds/abx/abx2xml b/cmds/abx/abx2xml.sh
index 0a9362d64398..0a9362d64398 100755
--- a/cmds/abx/abx2xml
+++ b/cmds/abx/abx2xml.sh
diff --git a/cmds/abx/xml2abx b/cmds/abx/xml2abx.sh
index 0a9362d64398..0a9362d64398 100755
--- a/cmds/abx/xml2abx
+++ b/cmds/abx/xml2abx.sh
diff --git a/cmds/bmgr/Android.bp b/cmds/bmgr/Android.bp
index 14beb5561dba..a85669a20e99 100644
--- a/cmds/bmgr/Android.bp
+++ b/cmds/bmgr/Android.bp
@@ -20,6 +20,6 @@ license {
java_binary {
name: "bmgr",
- wrapper: "bmgr",
+ wrapper: "bmgr.sh",
srcs: ["**/*.java"],
}
diff --git a/cmds/bmgr/bmgr b/cmds/bmgr/bmgr.sh
index b068d10dcbcf..b068d10dcbcf 100755
--- a/cmds/bmgr/bmgr
+++ b/cmds/bmgr/bmgr.sh
diff --git a/cmds/bu/Android.bp b/cmds/bu/Android.bp
index 5b4ec3197cdd..b61a7a6e6429 100644
--- a/cmds/bu/Android.bp
+++ b/cmds/bu/Android.bp
@@ -20,6 +20,6 @@ license {
java_binary {
name: "bu",
- wrapper: "bu",
+ wrapper: "bu.sh",
srcs: ["**/*.java"],
}
diff --git a/cmds/bu/bu b/cmds/bu/bu.sh
index e50b53da4325..e50b53da4325 100755
--- a/cmds/bu/bu
+++ b/cmds/bu/bu.sh
diff --git a/cmds/content/Android.bp b/cmds/content/Android.bp
index c70d01ec8f0b..0dd0f034e405 100644
--- a/cmds/content/Android.bp
+++ b/cmds/content/Android.bp
@@ -19,6 +19,6 @@ license {
java_binary {
name: "content",
- wrapper: "content",
+ wrapper: "content.sh",
srcs: ["**/*.java"],
}
diff --git a/cmds/content/content b/cmds/content/content.sh
index 91f2dfb16ac9..91f2dfb16ac9 100755
--- a/cmds/content/content
+++ b/cmds/content/content.sh
diff --git a/cmds/device_config/Android.bp b/cmds/device_config/Android.bp
index 69572d8690c4..83b2730c874f 100644
--- a/cmds/device_config/Android.bp
+++ b/cmds/device_config/Android.bp
@@ -14,5 +14,5 @@ package {
sh_binary {
name: "device_config",
- src: "device_config",
+ src: "device_config.sh",
}
diff --git a/cmds/device_config/device_config b/cmds/device_config/device_config.sh
index a949bd528263..a949bd528263 100755
--- a/cmds/device_config/device_config
+++ b/cmds/device_config/device_config.sh
diff --git a/cmds/dpm/Android.bp b/cmds/dpm/Android.bp
index 6819d0982d2c..29bee4958be6 100644
--- a/cmds/dpm/Android.bp
+++ b/cmds/dpm/Android.bp
@@ -20,5 +20,5 @@ license {
sh_binary {
name: "dpm",
- src: "dpm",
+ src: "dpm.sh",
}
diff --git a/cmds/dpm/dpm b/cmds/dpm/dpm.sh
index 784db5b352a9..784db5b352a9 100755
--- a/cmds/dpm/dpm
+++ b/cmds/dpm/dpm.sh
diff --git a/cmds/hid/Android.bp b/cmds/hid/Android.bp
index 295c71c65368..a6e27698e36c 100644
--- a/cmds/hid/Android.bp
+++ b/cmds/hid/Android.bp
@@ -20,7 +20,7 @@ license {
java_binary {
name: "hid",
- wrapper: "hid",
+ wrapper: "hid.sh",
srcs: ["**/*.java"],
required: ["libhidcommand_jni"],
}
diff --git a/cmds/hid/hid b/cmds/hid/hid.sh
index 43c76345c9e1..43c76345c9e1 100755
--- a/cmds/hid/hid
+++ b/cmds/hid/hid.sh
diff --git a/cmds/ime/Android.bp b/cmds/ime/Android.bp
index 6dd3ba1ca7ef..5f54ffacbb00 100644
--- a/cmds/ime/Android.bp
+++ b/cmds/ime/Android.bp
@@ -20,5 +20,5 @@ license {
sh_binary {
name: "ime",
- src: "ime",
+ src: "ime.sh",
}
diff --git a/cmds/ime/ime b/cmds/ime/ime.sh
index 7d2f72f74010..7d2f72f74010 100755
--- a/cmds/ime/ime
+++ b/cmds/ime/ime.sh
diff --git a/cmds/input/Android.bp b/cmds/input/Android.bp
index 2e30176971d7..8f44f3e34ef7 100644
--- a/cmds/input/Android.bp
+++ b/cmds/input/Android.bp
@@ -20,5 +20,5 @@ license {
sh_binary {
name: "input",
- src: "input",
+ src: "input.sh",
}
diff --git a/cmds/input/input b/cmds/input/input.sh
index d7d041431b49..d7d041431b49 100755
--- a/cmds/input/input
+++ b/cmds/input/input.sh
diff --git a/cmds/locksettings/Android.bp b/cmds/locksettings/Android.bp
index 3869c8fcdabc..5ee582450361 100644
--- a/cmds/locksettings/Android.bp
+++ b/cmds/locksettings/Android.bp
@@ -23,6 +23,6 @@ package {
java_binary {
name: "locksettings",
- wrapper: "locksettings",
+ wrapper: "locksettings.sh",
srcs: ["**/*.java"],
}
diff --git a/cmds/locksettings/locksettings b/cmds/locksettings/locksettings.sh
index 0ef4fa9f6771..0ef4fa9f6771 100755
--- a/cmds/locksettings/locksettings
+++ b/cmds/locksettings/locksettings.sh
diff --git a/cmds/pm/Android.bp b/cmds/pm/Android.bp
index 847dbabdf4c0..0e61a9e35d5e 100644
--- a/cmds/pm/Android.bp
+++ b/cmds/pm/Android.bp
@@ -20,5 +20,5 @@ license {
sh_binary {
name: "pm",
- src: "pm",
+ src: "pm.sh",
}
diff --git a/cmds/pm/pm b/cmds/pm/pm.sh
index 4d1f94554a78..4d1f94554a78 100755
--- a/cmds/pm/pm
+++ b/cmds/pm/pm.sh
diff --git a/cmds/requestsync/Android.bp b/cmds/requestsync/Android.bp
index 57e8dd355b26..8718f79c0d70 100644
--- a/cmds/requestsync/Android.bp
+++ b/cmds/requestsync/Android.bp
@@ -20,6 +20,6 @@ license {
java_binary {
name: "requestsync",
- wrapper: "requestsync",
+ wrapper: "requestsync.sh",
srcs: ["**/*.java"],
}
diff --git a/cmds/requestsync/requestsync b/cmds/requestsync/requestsync.sh
index 2d5d0e41705a..2d5d0e41705a 100755
--- a/cmds/requestsync/requestsync
+++ b/cmds/requestsync/requestsync.sh
diff --git a/cmds/settings/Android.bp b/cmds/settings/Android.bp
index cc730062f9df..8180fd6cab61 100644
--- a/cmds/settings/Android.bp
+++ b/cmds/settings/Android.bp
@@ -14,5 +14,5 @@ package {
sh_binary {
name: "settings",
- src: "settings",
+ src: "settings.sh",
}
diff --git a/cmds/settings/settings b/cmds/settings/settings.sh
index d41ccc62811a..d41ccc62811a 100755
--- a/cmds/settings/settings
+++ b/cmds/settings/settings.sh
diff --git a/cmds/sm/Android.bp b/cmds/sm/Android.bp
index ecfacaeecfd9..403022a2d2ae 100644
--- a/cmds/sm/Android.bp
+++ b/cmds/sm/Android.bp
@@ -20,6 +20,6 @@ license {
java_binary {
name: "sm",
- wrapper: "sm",
+ wrapper: "sm.sh",
srcs: ["**/*.java"],
}
diff --git a/cmds/sm/sm b/cmds/sm/sm.sh
index 30eae00a990d..30eae00a990d 100755
--- a/cmds/sm/sm
+++ b/cmds/sm/sm.sh
diff --git a/cmds/svc/Android.bp b/cmds/svc/Android.bp
index 41a3ebd2f514..a2460875f28e 100644
--- a/cmds/svc/Android.bp
+++ b/cmds/svc/Android.bp
@@ -20,6 +20,6 @@ license {
java_binary {
name: "svc",
- wrapper: "svc",
+ wrapper: "svc.sh",
srcs: ["**/*.java"],
}
diff --git a/cmds/svc/svc b/cmds/svc/svc.sh
index a2c9de32b3d0..a2c9de32b3d0 100755
--- a/cmds/svc/svc
+++ b/cmds/svc/svc.sh
diff --git a/cmds/telecom/Android.bp b/cmds/telecom/Android.bp
index 4da79c54477b..be027105ae98 100644
--- a/cmds/telecom/Android.bp
+++ b/cmds/telecom/Android.bp
@@ -20,6 +20,6 @@ license {
java_binary {
name: "telecom",
- wrapper: "telecom",
+ wrapper: "telecom.sh",
srcs: ["**/*.java"],
}
diff --git a/cmds/telecom/telecom b/cmds/telecom/telecom.sh
index a19036bf5bd8..a19036bf5bd8 100755
--- a/cmds/telecom/telecom
+++ b/cmds/telecom/telecom.sh
diff --git a/cmds/uiautomator/cmds/uiautomator/Android.bp b/cmds/uiautomator/cmds/uiautomator/Android.bp
index 56e2e70958fa..51323860725b 100644
--- a/cmds/uiautomator/cmds/uiautomator/Android.bp
+++ b/cmds/uiautomator/cmds/uiautomator/Android.bp
@@ -25,7 +25,7 @@ package {
java_binary {
name: "uiautomator",
- wrapper: "uiautomator",
+ wrapper: "uiautomator.sh",
srcs: ["src/**/*.java"],
static_libs: ["uiautomator.core"],
}
diff --git a/cmds/uiautomator/cmds/uiautomator/uiautomator b/cmds/uiautomator/cmds/uiautomator/uiautomator.sh
index 889c2b524dfd..889c2b524dfd 100755
--- a/cmds/uiautomator/cmds/uiautomator/uiautomator
+++ b/cmds/uiautomator/cmds/uiautomator/uiautomator.sh
diff --git a/cmds/uinput/Android.bp b/cmds/uinput/Android.bp
index 260cfc781ebc..4b08d968ac4a 100644
--- a/cmds/uinput/Android.bp
+++ b/cmds/uinput/Android.bp
@@ -20,9 +20,10 @@ license {
java_binary {
name: "uinput",
- wrapper: "uinput",
- srcs: ["**/*.java",
- ":uinputcommand_aidl"
+ wrapper: "uinput.sh",
+ srcs: [
+ "**/*.java",
+ ":uinputcommand_aidl",
],
required: ["libuinputcommand_jni"],
}
diff --git a/cmds/uinput/uinput b/cmds/uinput/uinput.sh
index ab2770ee2043..ab2770ee2043 100755
--- a/cmds/uinput/uinput
+++ b/cmds/uinput/uinput.sh
diff --git a/cmds/vr/Android.bp b/cmds/vr/Android.bp
index 893649155fd8..61795b4cc052 100644
--- a/cmds/vr/Android.bp
+++ b/cmds/vr/Android.bp
@@ -20,6 +20,6 @@ license {
java_binary {
name: "vr",
- wrapper: "vr",
+ wrapper: "vr.sh",
srcs: ["**/*.java"],
}
diff --git a/cmds/vr/vr b/cmds/vr/vr.sh
index dbde02a4ac7f..dbde02a4ac7f 100755
--- a/cmds/vr/vr
+++ b/cmds/vr/vr.sh
diff --git a/cmds/wm/Android.bp b/cmds/wm/Android.bp
index cf6b0193fe87..4d00f175211d 100644
--- a/cmds/wm/Android.bp
+++ b/cmds/wm/Android.bp
@@ -20,5 +20,5 @@ license {
sh_binary {
name: "wm",
- src: "wm",
+ src: "wm.sh",
}
diff --git a/cmds/wm/wm b/cmds/wm/wm.sh
index cb45be20c24a..cb45be20c24a 100755
--- a/cmds/wm/wm
+++ b/cmds/wm/wm.sh
diff --git a/core/api/current.txt b/core/api/current.txt
index d5194529d981..a26ca4fceae9 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -32172,6 +32172,7 @@ package android.os {
method @NonNull public android.os.StrictMode.ThreadPolicy.Builder detectCustomSlowCalls();
method @NonNull public android.os.StrictMode.ThreadPolicy.Builder detectDiskReads();
method @NonNull public android.os.StrictMode.ThreadPolicy.Builder detectDiskWrites();
+ method @NonNull public android.os.StrictMode.ThreadPolicy.Builder detectExplicitGc();
method @NonNull public android.os.StrictMode.ThreadPolicy.Builder detectNetwork();
method @NonNull public android.os.StrictMode.ThreadPolicy.Builder detectResourceMismatches();
method @NonNull public android.os.StrictMode.ThreadPolicy.Builder detectUnbufferedIo();
@@ -32186,6 +32187,7 @@ package android.os {
method @NonNull public android.os.StrictMode.ThreadPolicy.Builder permitCustomSlowCalls();
method @NonNull public android.os.StrictMode.ThreadPolicy.Builder permitDiskReads();
method @NonNull public android.os.StrictMode.ThreadPolicy.Builder permitDiskWrites();
+ method @NonNull public android.os.StrictMode.ThreadPolicy.Builder permitExplicitGc();
method @NonNull public android.os.StrictMode.ThreadPolicy.Builder permitNetwork();
method @NonNull public android.os.StrictMode.ThreadPolicy.Builder permitResourceMismatches();
method @NonNull public android.os.StrictMode.ThreadPolicy.Builder permitUnbufferedIo();
@@ -32767,6 +32769,9 @@ package android.os.strictmode {
public final class DiskWriteViolation extends android.os.strictmode.Violation {
}
+ public final class ExplicitGcViolation extends android.os.strictmode.Violation {
+ }
+
public final class FileUriExposedViolation extends android.os.strictmode.Violation {
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index ef8ae7095d65..a87f2e2bdaee 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -6134,6 +6134,11 @@ package android.media {
field public static final int ROLE_OUTPUT = 2; // 0x2
}
+ public class AudioDeviceVolumeManager {
+ ctor public AudioDeviceVolumeManager(@NonNull android.content.Context);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setDeviceVolume(@NonNull android.media.VolumeInfo, @NonNull android.media.AudioDeviceAttributes);
+ }
+
public final class AudioFocusInfo implements android.os.Parcelable {
method public int describeContents();
method @NonNull public android.media.AudioAttributes getAttributes();
@@ -6453,6 +6458,33 @@ package android.media {
method public void onSpatializerOutputChanged(@NonNull android.media.Spatializer, @IntRange(from=0) int);
}
+ public final class VolumeInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public static android.media.VolumeInfo getDefaultVolumeInfo();
+ method public int getMaxVolumeIndex();
+ method public int getMinVolumeIndex();
+ method public int getStreamType();
+ method @Nullable public android.media.audiopolicy.AudioVolumeGroup getVolumeGroup();
+ method public int getVolumeIndex();
+ method public boolean hasStreamType();
+ method public boolean hasVolumeGroup();
+ method public boolean isMuted();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.media.VolumeInfo> CREATOR;
+ field public static final int INDEX_NOT_SET = -100; // 0xffffff9c
+ }
+
+ public static final class VolumeInfo.Builder {
+ ctor public VolumeInfo.Builder(int);
+ ctor public VolumeInfo.Builder(@NonNull android.media.audiopolicy.AudioVolumeGroup);
+ ctor public VolumeInfo.Builder(@NonNull android.media.VolumeInfo);
+ method @NonNull public android.media.VolumeInfo build();
+ method @NonNull public android.media.VolumeInfo.Builder setMaxVolumeIndex(int);
+ method @NonNull public android.media.VolumeInfo.Builder setMinVolumeIndex(int);
+ method @NonNull public android.media.VolumeInfo.Builder setMuted(boolean);
+ method @NonNull public android.media.VolumeInfo.Builder setVolumeIndex(int);
+ }
+
}
package android.media.audiofx {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 53014a3c580e..73c666446400 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -793,6 +793,7 @@ package android.content.pm {
field public static final long FORCE_RESIZE_APP = 174042936L; // 0xa5faf38L
field public static final long NEVER_SANDBOX_DISPLAY_APIS = 184838306L; // 0xb0468a2L
field public static final long OVERRIDE_MIN_ASPECT_RATIO = 174042980L; // 0xa5faf64L
+ field public static final long OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN = 218959984L; // 0xd0d1070L
field public static final long OVERRIDE_MIN_ASPECT_RATIO_LARGE = 180326787L; // 0xabf9183L
field public static final float OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE = 1.7777778f;
field public static final long OVERRIDE_MIN_ASPECT_RATIO_MEDIUM = 180326845L; // 0xabf91bdL
@@ -1826,10 +1827,6 @@ package android.os {
method public static void setViolationLogger(android.os.StrictMode.ViolationLogger);
}
- public static final class StrictMode.ThreadPolicy.Builder {
- method @NonNull public android.os.StrictMode.ThreadPolicy.Builder detectExplicitGc();
- }
-
public static final class StrictMode.ViolationInfo implements android.os.Parcelable {
ctor public StrictMode.ViolationInfo(android.os.Parcel);
ctor public StrictMode.ViolationInfo(android.os.Parcel, boolean);
@@ -2038,13 +2035,6 @@ package android.os.storage {
}
-package android.os.strictmode {
-
- public final class ExplicitGcViolation extends android.os.strictmode.Violation {
- }
-
-}
-
package android.os.vibrator {
public final class PrebakedSegment extends android.os.vibrator.VibrationEffectSegment {
@@ -3386,6 +3376,7 @@ package android.window {
method @NonNull public android.window.WindowContainerTransaction createTaskFragment(@NonNull android.window.TaskFragmentCreationParams);
method @NonNull public android.window.WindowContainerTransaction deleteTaskFragment(@NonNull android.window.WindowContainerToken);
method public int describeContents();
+ method @NonNull public android.window.WindowContainerTransaction removeTask(@NonNull android.window.WindowContainerToken);
method @NonNull public android.window.WindowContainerTransaction reorder(@NonNull android.window.WindowContainerToken, boolean);
method @NonNull public android.window.WindowContainerTransaction reparent(@NonNull android.window.WindowContainerToken, @Nullable android.window.WindowContainerToken, boolean);
method @NonNull public android.window.WindowContainerTransaction reparentActivityToTaskFragment(@NonNull android.os.IBinder, @NonNull android.os.IBinder);
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index b9ad595778e4..7215987b0d87 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -753,7 +753,7 @@ public final class NotificationChannel implements Parcelable {
/**
* Returns the vibration pattern for notifications posted to this channel. Will be ignored if
- * vibration is not enabled ({@link #shouldVibrate()}.
+ * vibration is not enabled ({@link #shouldVibrate()}).
*/
public long[] getVibrationPattern() {
return mVibration;
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java
index 7014d6963538..a5a50d695793 100644
--- a/core/java/android/app/VoiceInteractor.java
+++ b/core/java/android/app/VoiceInteractor.java
@@ -43,6 +43,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -1103,7 +1104,10 @@ public final class VoiceInteractor {
}
try {
boolean[] res = mInteractor.supportsCommands(mContext.getOpPackageName(), commands);
- if (DEBUG) Log.d(TAG, "supportsCommands: cmds=" + commands + " res=" + res);
+ if (DEBUG) {
+ Log.d(TAG, "supportsCommands: cmds=" + Arrays.toString(commands) + " res="
+ + Arrays.toString(res));
+ }
return res;
} catch (RemoteException e) {
throw new RuntimeException("Voice interactor has died", e);
diff --git a/core/java/android/app/admin/PreferentialNetworkServiceConfig.java b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java
index 24b4f4b99ad0..63c9839a87e3 100644
--- a/core/java/android/app/admin/PreferentialNetworkServiceConfig.java
+++ b/core/java/android/app/admin/PreferentialNetworkServiceConfig.java
@@ -203,17 +203,14 @@ public final class PreferentialNetworkServiceConfig implements Parcelable {
return mIsEnabled == that.mIsEnabled
&& mAllowFallbackToDefaultConnection == that.mAllowFallbackToDefaultConnection
&& mNetworkId == that.mNetworkId
- && Objects.equals(mIncludedUids, that.mIncludedUids)
- && Objects.equals(mExcludedUids, that.mExcludedUids);
+ && Arrays.equals(mIncludedUids, that.mIncludedUids)
+ && Arrays.equals(mExcludedUids, that.mExcludedUids);
}
@Override
public int hashCode() {
- return ((Objects.hashCode(mIsEnabled) * 17)
- + (Objects.hashCode(mAllowFallbackToDefaultConnection) * 19)
- + (Objects.hashCode(mIncludedUids) * 23)
- + (Objects.hashCode(mExcludedUids) * 29)
- + mNetworkId * 31);
+ return Objects.hash(mIsEnabled, mAllowFallbackToDefaultConnection,
+ Arrays.hashCode(mIncludedUids), Arrays.hashCode(mExcludedUids), mNetworkId);
}
/**
diff --git a/core/java/android/app/ambientcontext/AmbientContextCallback.java b/core/java/android/app/ambientcontext/AmbientContextCallback.java
new file mode 100644
index 000000000000..9133d7fe6634
--- /dev/null
+++ b/core/java/android/app/ambientcontext/AmbientContextCallback.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.ambientcontext;
+
+import android.annotation.NonNull;
+
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Callback for listening to Ambient Context events and status changes. See {@link
+ * AmbientContextManager#registerObserver(AmbientContextEventRequest, AmbientContextCallback,
+ * Executor)}
+ *
+ * @hide
+ */
+public interface AmbientContextCallback {
+ /**
+ * Called when AmbientContextManager service detects events.
+ *
+ * @param events a list of detected events.
+ */
+ void onEvents(@NonNull List<AmbientContextEvent> events);
+
+ /**
+ * Called with a statusCode when
+ * {@link AmbientContextManager#registerObserver(AmbientContextEventRequest,
+ * Executor, AmbientContextCallback)} completes, to indicate if the registration is successful
+ *
+ * @param statusCode the status of the service.
+ */
+ void onRegistrationComplete(@NonNull @AmbientContextManager.StatusCode int statusCode);
+}
diff --git a/core/java/android/app/ambientcontext/AmbientContextEvent.java b/core/java/android/app/ambientcontext/AmbientContextEvent.java
index 11e695ad7fad..af48fde6423a 100644
--- a/core/java/android/app/ambientcontext/AmbientContextEvent.java
+++ b/core/java/android/app/ambientcontext/AmbientContextEvent.java
@@ -59,11 +59,21 @@ public final class AmbientContextEvent implements Parcelable {
*/
public static final int EVENT_SNORE = 2;
+ /**
+ * The integer indicating a double-tap event was detected.
+ * For detecting this event type, there's no specific consent activity to request access, but
+ * the consent is implied through the double tap toggle in the Settings app.
+ *
+ * @hide
+ */
+ public static final int EVENT_BACK_DOUBLE_TAP = 3;
+
/** @hide */
@IntDef(prefix = { "EVENT_" }, value = {
EVENT_UNKNOWN,
EVENT_COUGH,
EVENT_SNORE,
+ EVENT_BACK_DOUBLE_TAP,
}) public @interface EventCode {}
/** The integer indicating an unknown level. */
@@ -150,7 +160,8 @@ public final class AmbientContextEvent implements Parcelable {
@IntDef(prefix = "EVENT_", value = {
EVENT_UNKNOWN,
EVENT_COUGH,
- EVENT_SNORE
+ EVENT_SNORE,
+ EVENT_BACK_DOUBLE_TAP
})
@Retention(RetentionPolicy.SOURCE)
@DataClass.Generated.Member
@@ -166,6 +177,8 @@ public final class AmbientContextEvent implements Parcelable {
return "EVENT_COUGH";
case EVENT_SNORE:
return "EVENT_SNORE";
+ case EVENT_BACK_DOUBLE_TAP:
+ return "EVENT_BACK_DOUBLE_TAP";
default: return Integer.toHexString(value);
}
}
@@ -478,10 +491,10 @@ public final class AmbientContextEvent implements Parcelable {
}
@DataClass.Generated(
- time = 1642040319323L,
+ time = 1659950304931L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/app/ambientcontext/AmbientContextEvent.java",
- inputSignatures = "public static final int EVENT_UNKNOWN\npublic static final int EVENT_COUGH\npublic static final int EVENT_SNORE\npublic static final int LEVEL_UNKNOWN\npublic static final int LEVEL_LOW\npublic static final int LEVEL_MEDIUM_LOW\npublic static final int LEVEL_MEDIUM\npublic static final int LEVEL_MEDIUM_HIGH\npublic static final int LEVEL_HIGH\nprivate final @android.app.ambientcontext.AmbientContextEvent.EventCode int mEventType\nprivate final @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInstant.class) @android.annotation.NonNull java.time.Instant mStartTime\nprivate final @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInstant.class) @android.annotation.NonNull java.time.Instant mEndTime\nprivate final @android.app.ambientcontext.AmbientContextEvent.LevelValue int mConfidenceLevel\nprivate final @android.app.ambientcontext.AmbientContextEvent.LevelValue int mDensityLevel\nprivate static int defaultEventType()\nprivate static @android.annotation.NonNull java.time.Instant defaultStartTime()\nprivate static @android.annotation.NonNull java.time.Instant defaultEndTime()\nprivate static int defaultConfidenceLevel()\nprivate static int defaultDensityLevel()\nclass AmbientContextEvent extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=false, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
+ inputSignatures = "public static final int EVENT_UNKNOWN\npublic static final int EVENT_COUGH\npublic static final int EVENT_SNORE\npublic static final int EVENT_BACK_DOUBLE_TAP\npublic static final int LEVEL_UNKNOWN\npublic static final int LEVEL_LOW\npublic static final int LEVEL_MEDIUM_LOW\npublic static final int LEVEL_MEDIUM\npublic static final int LEVEL_MEDIUM_HIGH\npublic static final int LEVEL_HIGH\nprivate final @android.app.ambientcontext.AmbientContextEvent.EventCode int mEventType\nprivate final @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInstant.class) @android.annotation.NonNull java.time.Instant mStartTime\nprivate final @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInstant.class) @android.annotation.NonNull java.time.Instant mEndTime\nprivate final @android.app.ambientcontext.AmbientContextEvent.LevelValue int mConfidenceLevel\nprivate final @android.app.ambientcontext.AmbientContextEvent.LevelValue int mDensityLevel\nprivate static int defaultEventType()\nprivate static @android.annotation.NonNull java.time.Instant defaultStartTime()\nprivate static @android.annotation.NonNull java.time.Instant defaultEndTime()\nprivate static int defaultConfidenceLevel()\nprivate static int defaultDensityLevel()\nclass AmbientContextEvent extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genBuilder=true, genConstructor=false, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/app/ambientcontext/AmbientContextManager.java b/core/java/android/app/ambientcontext/AmbientContextManager.java
index 308c5edfd0f4..9cb1a204b312 100644
--- a/core/java/android/app/ambientcontext/AmbientContextManager.java
+++ b/core/java/android/app/ambientcontext/AmbientContextManager.java
@@ -282,7 +282,7 @@ public final class AmbientContextManager {
Preconditions.checkArgument(!resultPendingIntent.isImmutable());
try {
RemoteCallback callback = new RemoteCallback(result -> {
- int statusCode = result.getInt(STATUS_RESPONSE_BUNDLE_KEY);
+ int statusCode = result.getInt(STATUS_RESPONSE_BUNDLE_KEY);
final long identity = Binder.clearCallingIdentity();
try {
executor.execute(() -> statusConsumer.accept(statusCode));
@@ -297,6 +297,72 @@ public final class AmbientContextManager {
}
/**
+ * Allows app to register as a {@link AmbientContextEvent} observer. Same as {@link
+ * #registerObserver(AmbientContextEventRequest, PendingIntent, Executor, Consumer)},
+ * but use {@link AmbientContextCallback} instead of {@link PendingIntent} as a callback on
+ * detected events.
+ * Registering another observer from the same package that has already been
+ * registered will override the previous observer. If the same app previously calls
+ * {@link #registerObserver(AmbientContextEventRequest, AmbientContextCallback, Executor)},
+ * and now calls
+ * {@link #registerObserver(AmbientContextEventRequest, PendingIntent, Executor, Consumer)},
+ * the previous observer will be replaced with the new observer with the PendingIntent callback.
+ * Or vice versa.
+ *
+ * When the registration completes, a status will be returned to client through
+ * {@link AmbientContextCallback#onRegistrationComplete(int)}.
+ * If the AmbientContextManager service is not enabled yet, or the underlying detection service
+ * is not running yet, {@link AmbientContextManager#STATUS_SERVICE_UNAVAILABLE} will be
+ * returned, and the detection won't be really started.
+ * If the underlying detection service feature is not enabled, or the requested event type is
+ * not enabled yet, {@link AmbientContextManager#STATUS_NOT_SUPPORTED} will be returned, and the
+ * detection won't be really started.
+ * If there is no user consent, {@link AmbientContextManager#STATUS_ACCESS_DENIED} will be
+ * returned, and the detection won't be really started.
+ * Otherwise, it will try to start the detection. And if it starts successfully, it will return
+ * {@link AmbientContextManager#STATUS_SUCCESS}. If it fails to start the detection, then
+ * it will return {@link AmbientContextManager#STATUS_SERVICE_UNAVAILABLE}
+ * After registerObserver succeeds and when the service detects an event, the service will
+ * trigger {@link AmbientContextCallback#onEvents(List)}.
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT)
+ public void registerObserver(
+ @NonNull AmbientContextEventRequest request,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull AmbientContextCallback ambientContextCallback) {
+ try {
+ IAmbientContextObserver observer = new IAmbientContextObserver.Stub() {
+ @Override
+ public void onEvents(List<AmbientContextEvent> events) throws RemoteException {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> ambientContextCallback.onEvents(events));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public void onRegistrationComplete(int statusCode) throws RemoteException {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(
+ () -> ambientContextCallback.onRegistrationComplete(statusCode));
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ };
+
+ mService.registerObserverWithCallback(request, mContext.getPackageName(), observer);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Unregisters the requesting app as an {@code AmbientContextEvent} observer. Unregistering an
* observer that was already unregistered or never registered will have no effect.
*/
diff --git a/core/java/android/app/ambientcontext/IAmbientContextManager.aidl b/core/java/android/app/ambientcontext/IAmbientContextManager.aidl
index 0d9ecfdfe8f6..8f06e76db559 100644
--- a/core/java/android/app/ambientcontext/IAmbientContextManager.aidl
+++ b/core/java/android/app/ambientcontext/IAmbientContextManager.aidl
@@ -18,6 +18,7 @@ package android.app.ambientcontext;
import android.app.PendingIntent;
import android.app.ambientcontext.AmbientContextEventRequest;
+import android.app.ambientcontext.IAmbientContextObserver;
import android.os.RemoteCallback;
/**
@@ -29,6 +30,11 @@ interface IAmbientContextManager {
void registerObserver(in AmbientContextEventRequest request,
in PendingIntent resultPendingIntent,
in RemoteCallback statusCallback);
+
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT)")
+ void registerObserverWithCallback(in AmbientContextEventRequest request,
+ String packageName,
+ in IAmbientContextObserver observer);
void unregisterObserver(in String callingPackage);
void queryServiceStatus(in int[] eventTypes, in String callingPackage,
in RemoteCallback statusCallback);
diff --git a/core/java/android/app/ambientcontext/IAmbientContextObserver.aidl b/core/java/android/app/ambientcontext/IAmbientContextObserver.aidl
new file mode 100644
index 000000000000..529e2fea7edc
--- /dev/null
+++ b/core/java/android/app/ambientcontext/IAmbientContextObserver.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app.ambientcontext;
+
+import android.app.ambientcontext.AmbientContextEvent;
+
+/**
+ * Callback interface of AmbientContextManager.
+ *
+ * @hide
+ */
+oneway interface IAmbientContextObserver {
+ void onEvents(in List<AmbientContextEvent> events);
+ void onRegistrationComplete(in int statusCode);
+}
+
diff --git a/core/java/android/companion/BluetoothLeDeviceFilter.java b/core/java/android/companion/BluetoothLeDeviceFilter.java
index e6091f04a72a..2934cd27da19 100644
--- a/core/java/android/companion/BluetoothLeDeviceFilter.java
+++ b/core/java/android/companion/BluetoothLeDeviceFilter.java
@@ -204,9 +204,10 @@ public final class BluetoothLeDeviceFilter implements DeviceFilter<ScanResult> {
@Override
public int hashCode() {
- return Objects.hash(mNamePattern, mScanFilter, mRawDataFilter, mRawDataFilterMask,
- mRenamePrefix, mRenameSuffix, mRenameBytesFrom, mRenameBytesLength,
- mRenameNameFrom, mRenameNameLength, mRenameBytesReverseOrder);
+ return Objects.hash(mNamePattern, mScanFilter, Arrays.hashCode(mRawDataFilter),
+ Arrays.hashCode(mRawDataFilterMask), mRenamePrefix, mRenameSuffix,
+ mRenameBytesFrom, mRenameBytesLength, mRenameNameFrom, mRenameNameLength,
+ mRenameBytesReverseOrder);
}
@Override
diff --git a/core/java/android/content/AttributionSource.java b/core/java/android/content/AttributionSource.java
index 3f2fa2188d24..b0c6cbced4f9 100644
--- a/core/java/android/content/AttributionSource.java
+++ b/core/java/android/content/AttributionSource.java
@@ -495,14 +495,9 @@ public final class AttributionSource implements Parcelable {
@Override
public int hashCode() {
- int _hash = 1;
- _hash = 31 * _hash + mAttributionSourceState.uid;
- _hash = 31 * _hash + Objects.hashCode(mAttributionSourceState.packageName);
- _hash = 31 * _hash + Objects.hashCode(mAttributionSourceState.attributionTag);
- _hash = 31 * _hash + Objects.hashCode(mAttributionSourceState.token);
- _hash = 31 * _hash + Objects.hashCode(mAttributionSourceState.renouncedPermissions);
- _hash = 31 * _hash + Objects.hashCode(getNext());
- return _hash;
+ return Objects.hash(mAttributionSourceState.uid, mAttributionSourceState.packageName,
+ mAttributionSourceState.attributionTag, mAttributionSourceState.token,
+ Arrays.hashCode(mAttributionSourceState.renouncedPermissions), getNext());
}
@Override
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index e92be7cb64e2..26c947b5f916 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1120,6 +1120,17 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
public static final long OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN = 208648326L;
/**
+ * Overrides the min aspect ratio restriction in portrait fullscreen in order to use all
+ * available screen space.
+ * @hide
+ */
+ @ChangeId
+ @Disabled
+ @Overridable
+ @TestApi
+ public static final long OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN = 218959984L;
+
+ /**
* Compares activity window layout min width/height with require space for multi window to
* determine if it can be put into multi window mode.
*/
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index f780f815fa89..f8c49744d834 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -1723,7 +1723,8 @@ public class LauncherApps {
public void onPackagesAvailable(UserHandle user, String[] packageNames, boolean replacing)
throws RemoteException {
if (DEBUG) {
- Log.d(TAG, "onPackagesAvailable " + user.getIdentifier() + "," + packageNames);
+ Log.d(TAG, "onPackagesAvailable " + user.getIdentifier() + ","
+ + Arrays.toString(packageNames));
}
synchronized (LauncherApps.this) {
for (CallbackMessageHandler callback : mCallbacks) {
@@ -1736,7 +1737,8 @@ public class LauncherApps {
public void onPackagesUnavailable(UserHandle user, String[] packageNames, boolean replacing)
throws RemoteException {
if (DEBUG) {
- Log.d(TAG, "onPackagesUnavailable " + user.getIdentifier() + "," + packageNames);
+ Log.d(TAG, "onPackagesUnavailable " + user.getIdentifier() + ","
+ + Arrays.toString(packageNames));
}
synchronized (LauncherApps.this) {
for (CallbackMessageHandler callback : mCallbacks) {
@@ -1750,7 +1752,8 @@ public class LauncherApps {
Bundle launcherExtras)
throws RemoteException {
if (DEBUG) {
- Log.d(TAG, "onPackagesSuspended " + user.getIdentifier() + "," + packageNames);
+ Log.d(TAG, "onPackagesSuspended " + user.getIdentifier() + ","
+ + Arrays.toString(packageNames));
}
synchronized (LauncherApps.this) {
for (CallbackMessageHandler callback : mCallbacks) {
@@ -1763,7 +1766,8 @@ public class LauncherApps {
public void onPackagesUnsuspended(UserHandle user, String[] packageNames)
throws RemoteException {
if (DEBUG) {
- Log.d(TAG, "onPackagesUnsuspended " + user.getIdentifier() + "," + packageNames);
+ Log.d(TAG, "onPackagesUnsuspended " + user.getIdentifier() + ","
+ + Arrays.toString(packageNames));
}
synchronized (LauncherApps.this) {
for (CallbackMessageHandler callback : mCallbacks) {
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 52774e354c90..1f83d7532f04 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -53,6 +53,7 @@ import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -2617,7 +2618,7 @@ public final class ShortcutInfo implements Parcelable {
addIndentOrComma(sb, indent);
sb.append("persons=");
- sb.append(mPersons);
+ sb.append(Arrays.toString(mPersons));
addIndentOrComma(sb, indent);
diff --git a/core/java/android/content/res/GradientColor.java b/core/java/android/content/res/GradientColor.java
index 35ad5033e395..7bc551d7f49e 100644
--- a/core/java/android/content/res/GradientColor.java
+++ b/core/java/android/content/res/GradientColor.java
@@ -22,13 +22,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.ActivityInfo.Config;
import android.content.res.Resources.Theme;
-
-import com.android.internal.R;
-import com.android.internal.util.GrowingArrayUtils;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
import android.graphics.LinearGradient;
import android.graphics.RadialGradient;
import android.graphics.Shader;
@@ -38,9 +31,16 @@ import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
+import com.android.internal.R;
+import com.android.internal.util.GrowingArrayUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
/**
* Lets you define a gradient color, which is used inside
@@ -466,7 +466,7 @@ public class GradientColor extends ComplexColor {
}
if (tempColors.length < 2) {
Log.w(TAG, "<gradient> tag requires 2 color values specified!" + tempColors.length
- + " " + tempColors);
+ + " " + Arrays.toString(tempColors));
}
if (mGradientType == GradientDrawable.LINEAR_GRADIENT) {
diff --git a/core/java/android/hardware/HardwareBuffer.aidl b/core/java/android/hardware/HardwareBuffer.aidl
index 5bdd96677da5..1333f0da725f 100644
--- a/core/java/android/hardware/HardwareBuffer.aidl
+++ b/core/java/android/hardware/HardwareBuffer.aidl
@@ -16,4 +16,4 @@
package android.hardware;
-parcelable HardwareBuffer;
+@JavaOnlyStableParcelable @NdkOnlyStableParcelable parcelable HardwareBuffer ndk_header "android/hardware_buffer_aidl.h";
diff --git a/core/java/android/hardware/biometrics/IBiometricContextListener.aidl b/core/java/android/hardware/biometrics/IBiometricContextListener.aidl
index 55cab52fc4f7..2e8e763b0ee4 100644
--- a/core/java/android/hardware/biometrics/IBiometricContextListener.aidl
+++ b/core/java/android/hardware/biometrics/IBiometricContextListener.aidl
@@ -23,5 +23,8 @@ package android.hardware.biometrics;
* @hide
*/
oneway interface IBiometricContextListener {
- void onDozeChanged(boolean isDozing);
+ // Called when doze or awake (screen on) status changes.
+ // These may be called while the device is still transitioning to the new state
+ // (i.e. about to become awake or enter doze)
+ void onDozeChanged(boolean isDozing, boolean isAwake);
}
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index c614cdbc3199..72d812269374 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -1433,10 +1433,17 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
}
@NonNull
- private static float[] createEnrollStageThresholds(@NonNull Context context) {
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+ private float[] createEnrollStageThresholds(@NonNull Context context) {
// TODO(b/200604947): Fetch this value from FingerprintService, rather than internal config
- final String[] enrollStageThresholdStrings = context.getResources().getStringArray(
- com.android.internal.R.array.config_udfps_enroll_stage_thresholds);
+ final String[] enrollStageThresholdStrings;
+ if (isPowerbuttonFps()) {
+ enrollStageThresholdStrings = context.getResources().getStringArray(
+ com.android.internal.R.array.config_sfps_enroll_stage_thresholds);
+ } else {
+ enrollStageThresholdStrings = context.getResources().getStringArray(
+ com.android.internal.R.array.config_udfps_enroll_stage_thresholds);
+ }
final float[] enrollStageThresholds = new float[enrollStageThresholdStrings.length];
for (int i = 0; i < enrollStageThresholds.length; i++) {
diff --git a/core/java/android/hardware/radio/ProgramSelector.java b/core/java/android/hardware/radio/ProgramSelector.java
index 6300a12c3137..a13eadaefe5a 100644
--- a/core/java/android/hardware/radio/ProgramSelector.java
+++ b/core/java/android/hardware/radio/ProgramSelector.java
@@ -491,8 +491,12 @@ public final class ProgramSelector implements Parcelable {
public String toString() {
StringBuilder sb = new StringBuilder("ProgramSelector(type=").append(mProgramType)
.append(", primary=").append(mPrimaryId);
- if (mSecondaryIds.length > 0) sb.append(", secondary=").append(mSecondaryIds);
- if (mVendorIds.length > 0) sb.append(", vendor=").append(mVendorIds);
+ if (mSecondaryIds.length > 0) {
+ sb.append(", secondary=").append(Arrays.toString(mSecondaryIds));
+ }
+ if (mVendorIds.length > 0) {
+ sb.append(", vendor=").append(Arrays.toString(mVendorIds));
+ }
sb.append(")");
return sb.toString();
}
diff --git a/core/java/android/hardware/radio/RadioManager.java b/core/java/android/hardware/radio/RadioManager.java
index 8180caa1557b..43341166d720 100644
--- a/core/java/android/hardware/radio/RadioManager.java
+++ b/core/java/android/hardware/radio/RadioManager.java
@@ -505,7 +505,8 @@ public class RadioManager {
public int hashCode() {
return Objects.hash(mId, mServiceName, mClassId, mImplementor, mProduct, mVersion,
mSerial, mNumTuners, mNumAudioSources, mIsInitializationRequired,
- mIsCaptureSupported, mBands, mIsBgScanSupported, mDabFrequencyTable, mVendorInfo);
+ mIsCaptureSupported, Arrays.hashCode(mBands), mIsBgScanSupported,
+ mDabFrequencyTable, mVendorInfo);
}
@Override
@@ -525,7 +526,7 @@ public class RadioManager {
if (mNumAudioSources != other.mNumAudioSources) return false;
if (mIsInitializationRequired != other.mIsInitializationRequired) return false;
if (mIsCaptureSupported != other.mIsCaptureSupported) return false;
- if (!Objects.equals(mBands, other.mBands)) return false;
+ if (!Arrays.equals(mBands, other.mBands)) return false;
if (mIsBgScanSupported != other.mIsBgScanSupported) return false;
if (!Objects.equals(mDabFrequencyTable, other.mDabFrequencyTable)) return false;
if (!Objects.equals(mVendorInfo, other.mVendorInfo)) return false;
diff --git a/core/java/android/metrics/LogMaker.java b/core/java/android/metrics/LogMaker.java
index a19eb5668d55..8644d9103dcb 100644
--- a/core/java/android/metrics/LogMaker.java
+++ b/core/java/android/metrics/LogMaker.java
@@ -23,6 +23,7 @@ import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import java.util.Arrays;
/**
@@ -395,7 +396,7 @@ public class LogMaker {
out[i * 2] = entries.keyAt(i);
out[i * 2 + 1] = entries.valueAt(i);
}
- int size = out.toString().getBytes().length;
+ int size = Arrays.toString(out).getBytes().length;
if (size > MAX_SERIALIZED_SIZE) {
Log.i(TAG, "Log line too long, did not emit: " + size + " bytes.");
throw new RuntimeException();
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index da206268917e..0ad596b682ce 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1767,6 +1767,49 @@ public abstract class BatteryStats {
}
/**
+ * Measured energy delta from the previous reading.
+ */
+ public static final class MeasuredEnergyDetails {
+ /**
+ * Description of the energy consumer, such as CPU, DISPLAY etc
+ */
+ public static final class EnergyConsumer {
+ /**
+ * See android.hardware.power.stats.EnergyConsumerType
+ */
+ public int type;
+ /**
+ * Used when there are multipe energy consumers of the same type, such
+ * as CPU clusters, multiple displays on foldable devices etc.
+ */
+ public int ordinal;
+ /**
+ * Human-readable name of the energy consumer, e.g. "CPU"
+ */
+ public String name;
+ }
+ public EnergyConsumer[] consumers;
+ public long[] chargeUC;
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < consumers.length; i++) {
+ if (chargeUC[i] == POWER_DATA_UNAVAILABLE) {
+ continue;
+ }
+ if (sb.length() != 0) {
+ sb.append(' ');
+ }
+ sb.append(consumers[i].name);
+ sb.append('=');
+ sb.append(chargeUC[i]);
+ }
+ return sb.toString();
+ }
+ }
+
+ /**
* Battery history record.
*/
public static final class HistoryItem {
@@ -1886,6 +1929,7 @@ public abstract class BatteryStats {
public static final int STATE2_BLUETOOTH_SCAN_FLAG = 1 << 20;
public static final int STATE2_CELLULAR_HIGH_TX_POWER_FLAG = 1 << 19;
public static final int STATE2_USB_DATA_LINK_FLAG = 1 << 18;
+ public static final int STATE2_EXTENSIONS_FLAG = 1 << 17;
public static final int MOST_INTERESTING_STATES2 =
STATE2_POWER_SAVE_FLAG | STATE2_WIFI_ON_FLAG | STATE2_DEVICE_IDLE_MASK
@@ -1905,6 +1949,9 @@ public abstract class BatteryStats {
// Non-null when there is more detailed information at this step.
public HistoryStepDetails stepDetails;
+ // Non-null when there is measured energy information
+ public MeasuredEnergyDetails measuredEnergyDetails;
+
public static final int EVENT_FLAG_START = 0x8000;
public static final int EVENT_FLAG_FINISH = 0x4000;
@@ -2113,6 +2160,7 @@ public abstract class BatteryStats {
eventCode = EVENT_NONE;
eventTag = null;
tagsFirstOccurrence = false;
+ measuredEnergyDetails = null;
}
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
@@ -2162,6 +2210,7 @@ public abstract class BatteryStats {
}
tagsFirstOccurrence = o.tagsFirstOccurrence;
currentTime = o.currentTime;
+ measuredEnergyDetails = o.measuredEnergyDetails;
}
public boolean sameNonEvent(HistoryItem o) {
@@ -6951,6 +7000,14 @@ public abstract class BatteryStats {
item.append("\"");
}
}
+ if ((rec.states2 & HistoryItem.STATE2_EXTENSIONS_FLAG) != 0) {
+ if (!checkin) {
+ item.append(" ext=");
+ if (rec.measuredEnergyDetails != null) {
+ item.append("E");
+ }
+ }
+ }
if (rec.eventCode != HistoryItem.EVENT_NONE) {
item.append(checkin ? "," : " ");
if ((rec.eventCode&HistoryItem.EVENT_FLAG_START) != 0) {
@@ -7075,6 +7132,25 @@ public abstract class BatteryStats {
item.append("\n");
}
}
+ if (rec.measuredEnergyDetails != null) {
+ if (!checkin) {
+ item.append(" Energy: ");
+ item.append(rec.measuredEnergyDetails);
+ item.append("\n");
+ } else {
+ item.append(BATTERY_STATS_CHECKIN_VERSION); item.append(',');
+ item.append(HISTORY_DATA); item.append(",0,XE");
+ for (int i = 0; i < rec.measuredEnergyDetails.consumers.length; i++) {
+ if (rec.measuredEnergyDetails.chargeUC[i] != POWER_DATA_UNAVAILABLE) {
+ item.append(',');
+ item.append(rec.measuredEnergyDetails.consumers[i].name);
+ item.append('=');
+ item.append(rec.measuredEnergyDetails.chargeUC[i]);
+ }
+ }
+ item.append("\n");
+ }
+ }
oldState = rec.states;
oldState2 = rec.states2;
// Clear High Tx Power Flag for volta positioning
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 43a6be5df202..fb8f84acc8f3 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -469,7 +469,15 @@ public class GraphicsEnvironment {
* 2) The per-application switch (i.e. Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS and
* Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES; which corresponds to the
* “angle_gl_driver_selection_pkgs” and “angle_gl_driver_selection_values” settings); if it
- * forces a choice; otherwise ...
+ * forces a choice;
+ * - Workaround Note: ANGLE and Vulkan currently have issues with applications that use YUV
+ * target functionality. The ANGLE broadcast receiver code will apply a "deferlist" at
+ * the first boot of a newly-flashed device. However, there is a gap in time between
+ * when applications can start and when the deferlist is applied. For now, assume that
+ * if ANGLE is the system driver and Settings.Global.ANGLE_GL_DRIVER_SELECTION_PKGS is
+ * empty, that the deferlist has not yet been applied. In this case, select the Legacy
+ * driver.
+ * otherwise ...
* 3) Use ANGLE if isAngleEnabledByGameMode() returns true; otherwise ...
* 4) The global switch (i.e. use the system driver, whether ANGLE or legacy;
* a.k.a. mAngleIsSystemDriver, which is set by the device’s “ro.hardware.egl” property)
@@ -509,9 +517,16 @@ public class GraphicsEnvironment {
final List<String> optInValues = getGlobalSettingsString(
contentResolver, bundle, Settings.Global.ANGLE_GL_DRIVER_SELECTION_VALUES);
Log.v(TAG, "Currently set values for:");
- Log.v(TAG, " angle_gl_driver_selection_pkgs = " + optInPackages);
+ Log.v(TAG, " angle_gl_driver_selection_pkgs =" + optInPackages);
Log.v(TAG, " angle_gl_driver_selection_values =" + optInValues);
+ // If ANGLE is the system driver AND the deferlist has not yet been applied, select the
+ // Legacy driver
+ if (mAngleIsSystemDriver && optInPackages.size() <= 1) {
+ Log.v(TAG, "Ignoring angle_gl_driver_selection_* until deferlist has been applied");
+ return ANGLE_GL_DRIVER_TO_USE_LEGACY;
+ }
+
// Make sure we have good settings to use
if (optInPackages.size() != optInValues.size()) {
Log.w(TAG,
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 412a33a1c124..113a64048796 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -26,6 +26,9 @@ import android.annotation.TestApi;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.IActivityManager;
+import android.app.compat.CompatChanges;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -344,6 +347,13 @@ public final class StrictMode {
public static final int NETWORK_POLICY_LOG = 1;
/** {@hide} */
public static final int NETWORK_POLICY_REJECT = 2;
+
+ /**
+ * Detect explicit calls to {@link Runtime#gc()}.
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ static final long DETECT_EXPLICIT_GC = 3400644L;
// TODO: wrap in some ImmutableHashMap thing.
// Note: must be before static initialization of sVmPolicy.
@@ -496,6 +506,7 @@ public final class StrictMode {
* <p>As of the Gingerbread release this includes network and disk operations but will
* likely expand in future releases.
*/
+ @SuppressWarnings("AndroidFrameworkCompatChange")
public @NonNull Builder detectAll() {
detectDiskReads();
detectDiskWrites();
@@ -511,6 +522,9 @@ public final class StrictMode {
if (targetSdk >= Build.VERSION_CODES.O) {
detectUnbufferedIo();
}
+ if (CompatChanges.isChangeEnabled(DETECT_EXPLICIT_GC)) {
+ detectExplicitGc();
+ }
return this;
}
@@ -591,26 +605,16 @@ public final class StrictMode {
}
/**
- * Detect explicit GC requests, i.e. calls to Runtime.gc().
- *
- * @hide
+ * Detect calls to {@link Runtime#gc()}.
*/
- @TestApi
public @NonNull Builder detectExplicitGc() {
- // TODO(b/3400644): Un-hide this for next API update
- // TODO(b/3400644): Un-hide ExplicitGcViolation for next API update
- // TODO(b/3400644): Make DETECT_EXPLICIT_GC a @TestApi for next API update
- // TODO(b/3400644): Call this from detectAll in next API update
return enable(DETECT_THREAD_EXPLICIT_GC);
}
/**
- * Disable detection of explicit GC requests, i.e. calls to Runtime.gc().
- *
- * @hide
+ * Disable detection of calls to {@link Runtime#gc()}.
*/
public @NonNull Builder permitExplicitGc() {
- // TODO(b/3400644): Un-hide this for next API update
return disable(DETECT_THREAD_EXPLICIT_GC);
}
diff --git a/core/java/android/os/VibrationAttributes.java b/core/java/android/os/VibrationAttributes.java
index 06930bb32090..392bf4ec3ece 100644
--- a/core/java/android/os/VibrationAttributes.java
+++ b/core/java/android/os/VibrationAttributes.java
@@ -145,7 +145,8 @@ public final class VibrationAttributes implements Parcelable {
*/
@IntDef(prefix = { "FLAG_" }, flag = true, value = {
FLAG_BYPASS_INTERRUPTION_POLICY,
- FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF
+ FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF,
+ FLAG_INVALIDATE_SETTINGS_CACHE
})
@Retention(RetentionPolicy.SOURCE)
public @interface Flag{}
@@ -182,7 +183,7 @@ public final class VibrationAttributes implements Parcelable {
*
* @hide
*/
- public static final int FLAG_INVALIDATE_SETTINGS_CACHE = 0x3;
+ public static final int FLAG_INVALIDATE_SETTINGS_CACHE = 0x4;
/**
* All flags supported by vibrator service, update it when adding new flag.
diff --git a/core/java/android/os/incremental/IncrementalStorage.java b/core/java/android/os/incremental/IncrementalStorage.java
index 13b22d370030..a1ed2533f544 100644
--- a/core/java/android/os/incremental/IncrementalStorage.java
+++ b/core/java/android/os/incremental/IncrementalStorage.java
@@ -26,6 +26,7 @@ import android.os.RemoteException;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
+import java.util.Arrays;
import java.util.Objects;
import java.util.UUID;
@@ -515,7 +516,7 @@ public final class IncrementalStorage {
throw new IOException("Unsupported log2BlockSize: " + hashingInfo.log2BlockSize);
}
if (hashingInfo.salt != null && hashingInfo.salt.length > 0) {
- throw new IOException("Unsupported salt: " + hashingInfo.salt);
+ throw new IOException("Unsupported salt: " + Arrays.toString(hashingInfo.salt));
}
if (hashingInfo.rawRootHash.length != INCFS_MAX_HASH_SIZE) {
throw new IOException("rawRootHash has to be " + INCFS_MAX_HASH_SIZE + " bytes");
diff --git a/core/java/android/os/strictmode/ExplicitGcViolation.java b/core/java/android/os/strictmode/ExplicitGcViolation.java
index 583ed1ab4505..c4ae82ddbc05 100644
--- a/core/java/android/os/strictmode/ExplicitGcViolation.java
+++ b/core/java/android/os/strictmode/ExplicitGcViolation.java
@@ -19,10 +19,7 @@ import android.annotation.TestApi;
/**
* See #{@link android.os.StrictMode.ThreadPolicy.Builder#detectExplicitGc()}.
- *
- * @hide
*/
-@TestApi
public final class ExplicitGcViolation extends Violation {
/** @hide */
public ExplicitGcViolation() {
diff --git a/core/java/android/service/autofill/OptionalValidators.java b/core/java/android/service/autofill/OptionalValidators.java
index 7189c886aa06..204353942b03 100644
--- a/core/java/android/service/autofill/OptionalValidators.java
+++ b/core/java/android/service/autofill/OptionalValidators.java
@@ -25,6 +25,8 @@ import android.util.Log;
import com.android.internal.util.Preconditions;
+import java.util.Arrays;
+
/**
* Compound validator that returns {@code true} on {@link #isValid(ValueFinder)} if any
* of its subvalidators returns {@code true} as well.
@@ -61,7 +63,8 @@ final class OptionalValidators extends InternalValidator {
public String toString() {
if (!sDebug) return super.toString();
- return new StringBuilder("OptionalValidators: [validators=").append(mValidators)
+ return new StringBuilder("OptionalValidators: [validators=")
+ .append(Arrays.toString(mValidators))
.append("]")
.toString();
}
diff --git a/core/java/android/service/autofill/RequiredValidators.java b/core/java/android/service/autofill/RequiredValidators.java
index 619eba0a79ad..054582e01f71 100644
--- a/core/java/android/service/autofill/RequiredValidators.java
+++ b/core/java/android/service/autofill/RequiredValidators.java
@@ -25,6 +25,8 @@ import android.util.Log;
import com.android.internal.util.Preconditions;
+import java.util.Arrays;
+
/**
* Compound validator that only returns {@code true} on {@link #isValid(ValueFinder)} if all
* of its subvalidators return {@code true} as well.
@@ -60,7 +62,8 @@ final class RequiredValidators extends InternalValidator {
public String toString() {
if (!sDebug) return super.toString();
- return new StringBuilder("RequiredValidators: [validators=").append(mValidators)
+ return new StringBuilder("RequiredValidators: [validators=")
+ .append(Arrays.toString(mValidators))
.append("]")
.toString();
}
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index d08a67e68676..f0f16dbbb39e 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -75,6 +75,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -599,7 +600,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
VoiceInteractor.PickOptionRequest.Option[] selections, Bundle result) {
try {
if (DEBUG) Log.d(TAG, "sendPickOptionResult: req=" + mInterface
- + " finished=" + finished + " selections=" + selections
+ + " finished=" + finished + " selections=" + Arrays.toString(selections)
+ " result=" + result);
if (finished) {
finishRequest();
diff --git a/core/java/android/speech/tts/FileSynthesisCallback.java b/core/java/android/speech/tts/FileSynthesisCallback.java
index 3bde32b1e5f2..3177c5c8509e 100644
--- a/core/java/android/speech/tts/FileSynthesisCallback.java
+++ b/core/java/android/speech/tts/FileSynthesisCallback.java
@@ -24,6 +24,7 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
+import java.util.Arrays;
/**
* Speech synthesis request that writes the audio to a WAV file.
@@ -152,8 +153,8 @@ class FileSynthesisCallback extends AbstractSynthesisCallback {
@Override
public int audioAvailable(byte[] buffer, int offset, int length) {
if (DBG) {
- Log.d(TAG, "FileSynthesisRequest.audioAvailable(" + buffer + "," + offset
- + "," + length + ")");
+ Log.d(TAG, "FileSynthesisRequest.audioAvailable(" + Arrays.toString(buffer)
+ + "," + offset + "," + length + ")");
}
FileChannel fileChannel = null;
synchronized (mStateLock) {
diff --git a/core/java/android/util/ArrayMap.java b/core/java/android/util/ArrayMap.java
index c0bc9912af3d..155f508f6242 100644
--- a/core/java/android/util/ArrayMap.java
+++ b/core/java/android/util/ArrayMap.java
@@ -23,6 +23,7 @@ import com.android.internal.util.ArrayUtils;
import libcore.util.EmptyArray;
+import java.util.Arrays;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Map;
@@ -231,7 +232,7 @@ public final class ArrayMap<K, V> implements Map<K, V> {
array[0] = array[1] = null;
mTwiceBaseCacheSize--;
if (DEBUG) {
- Log.d(TAG, "Retrieving 2x cache " + mHashes
+ Log.d(TAG, "Retrieving 2x cache " + Arrays.toString(mHashes)
+ " now have " + mTwiceBaseCacheSize + " entries");
}
return;
@@ -258,7 +259,7 @@ public final class ArrayMap<K, V> implements Map<K, V> {
array[0] = array[1] = null;
mBaseCacheSize--;
if (DEBUG) {
- Log.d(TAG, "Retrieving 1x cache " + mHashes
+ Log.d(TAG, "Retrieving 1x cache " + Arrays.toString(mHashes)
+ " now have " + mBaseCacheSize + " entries");
}
return;
@@ -295,8 +296,10 @@ public final class ArrayMap<K, V> implements Map<K, V> {
}
mTwiceBaseCache = array;
mTwiceBaseCacheSize++;
- if (DEBUG) Log.d(TAG, "Storing 2x cache " + array
- + " now have " + mTwiceBaseCacheSize + " entries");
+ if (DEBUG) {
+ Log.d(TAG, "Storing 2x cache " + Arrays.toString(array)
+ + " now have " + mTwiceBaseCacheSize + " entries");
+ }
}
}
} else if (hashes.length == BASE_SIZE) {
@@ -309,8 +312,10 @@ public final class ArrayMap<K, V> implements Map<K, V> {
}
mBaseCache = array;
mBaseCacheSize++;
- if (DEBUG) Log.d(TAG, "Storing 1x cache " + array
- + " now have " + mBaseCacheSize + " entries");
+ if (DEBUG) {
+ Log.d(TAG, "Storing 1x cache " + Arrays.toString(array)
+ + " now have " + mBaseCacheSize + " entries");
+ }
}
}
}
diff --git a/core/java/android/util/ArraySet.java b/core/java/android/util/ArraySet.java
index b5c75b9276b7..73114e26e417 100644
--- a/core/java/android/util/ArraySet.java
+++ b/core/java/android/util/ArraySet.java
@@ -23,6 +23,7 @@ import android.compat.annotation.UnsupportedAppUsage;
import libcore.util.EmptyArray;
import java.lang.reflect.Array;
+import java.util.Arrays;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
@@ -194,8 +195,8 @@ public final class ArraySet<E> implements Collection<E>, Set<E> {
array[0] = array[1] = null;
sTwiceBaseCacheSize--;
if (DEBUG) {
- Log.d(TAG, "Retrieving 2x cache " + mHashes + " now have "
- + sTwiceBaseCacheSize + " entries");
+ Log.d(TAG, "Retrieving 2x cache " + Arrays.toString(mHashes)
+ + " now have " + sTwiceBaseCacheSize + " entries");
}
return;
}
@@ -221,8 +222,8 @@ public final class ArraySet<E> implements Collection<E>, Set<E> {
array[0] = array[1] = null;
sBaseCacheSize--;
if (DEBUG) {
- Log.d(TAG, "Retrieving 1x cache " + mHashes + " now have "
- + sBaseCacheSize + " entries");
+ Log.d(TAG, "Retrieving 1x cache " + Arrays.toString(mHashes)
+ + " now have " + sBaseCacheSize + " entries");
}
return;
}
@@ -259,8 +260,8 @@ public final class ArraySet<E> implements Collection<E>, Set<E> {
sTwiceBaseCache = array;
sTwiceBaseCacheSize++;
if (DEBUG) {
- Log.d(TAG, "Storing 2x cache " + array + " now have " + sTwiceBaseCacheSize
- + " entries");
+ Log.d(TAG, "Storing 2x cache " + Arrays.toString(array) + " now have "
+ + sTwiceBaseCacheSize + " entries");
}
}
}
@@ -275,7 +276,7 @@ public final class ArraySet<E> implements Collection<E>, Set<E> {
sBaseCache = array;
sBaseCacheSize++;
if (DEBUG) {
- Log.d(TAG, "Storing 1x cache " + array + " now have "
+ Log.d(TAG, "Storing 1x cache " + Arrays.toString(array) + " now have "
+ sBaseCacheSize + " entries");
}
}
diff --git a/core/java/android/util/proto/ProtoInputStream.java b/core/java/android/util/proto/ProtoInputStream.java
index 9789b10a0a61..9a15cd5dbfff 100644
--- a/core/java/android/util/proto/ProtoInputStream.java
+++ b/core/java/android/util/proto/ProtoInputStream.java
@@ -21,6 +21,8 @@ import android.util.LongArray;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Objects;
/**
* Class to read to a protobuf stream.
@@ -968,26 +970,17 @@ public final class ProtoInputStream extends ProtoStream {
public String dumpDebugData() {
StringBuilder sb = new StringBuilder();
- sb.append("\nmFieldNumber : 0x" + Integer.toHexString(mFieldNumber));
- sb.append("\nmWireType : 0x" + Integer.toHexString(mWireType));
- sb.append("\nmState : 0x" + Integer.toHexString(mState));
- sb.append("\nmDiscardedBytes : 0x" + Integer.toHexString(mDiscardedBytes));
- sb.append("\nmOffset : 0x" + Integer.toHexString(mOffset));
- sb.append("\nmExpectedObjectTokenStack : ");
- if (mExpectedObjectTokenStack == null) {
- sb.append("null");
- } else {
- sb.append(mExpectedObjectTokenStack);
- }
- sb.append("\nmDepth : 0x" + Integer.toHexString(mDepth));
- sb.append("\nmBuffer : ");
- if (mBuffer == null) {
- sb.append("null");
- } else {
- sb.append(mBuffer);
- }
- sb.append("\nmBufferSize : 0x" + Integer.toHexString(mBufferSize));
- sb.append("\nmEnd : 0x" + Integer.toHexString(mEnd));
+ sb.append("\nmFieldNumber : 0x").append(Integer.toHexString(mFieldNumber));
+ sb.append("\nmWireType : 0x").append(Integer.toHexString(mWireType));
+ sb.append("\nmState : 0x").append(Integer.toHexString(mState));
+ sb.append("\nmDiscardedBytes : 0x").append(Integer.toHexString(mDiscardedBytes));
+ sb.append("\nmOffset : 0x").append(Integer.toHexString(mOffset));
+ sb.append("\nmExpectedObjectTokenStack : ")
+ .append(Objects.toString(mExpectedObjectTokenStack));
+ sb.append("\nmDepth : 0x").append(Integer.toHexString(mDepth));
+ sb.append("\nmBuffer : ").append(Arrays.toString(mBuffer));
+ sb.append("\nmBufferSize : 0x").append(Integer.toHexString(mBufferSize));
+ sb.append("\nmEnd : 0x").append(Integer.toHexString(mEnd));
return sb.toString();
}
diff --git a/core/java/android/util/proto/ProtoUtils.java b/core/java/android/util/proto/ProtoUtils.java
index 8464d2d808d6..58d991370f56 100644
--- a/core/java/android/util/proto/ProtoUtils.java
+++ b/core/java/android/util/proto/ProtoUtils.java
@@ -20,6 +20,7 @@ import android.util.AggStats;
import android.util.Duration;
import java.io.IOException;
+import java.util.Arrays;
/**
* This class contains a list of helper functions to write common proto in
@@ -91,27 +92,27 @@ public class ProtoUtils {
final int wireType = proto.getWireType();
long fieldConstant;
- sb.append("Offset : 0x" + Integer.toHexString(proto.getOffset()));
- sb.append("\nField Number : 0x" + Integer.toHexString(proto.getFieldNumber()));
+ sb.append("Offset : 0x").append(Integer.toHexString(proto.getOffset()));
+ sb.append("\nField Number : 0x").append(Integer.toHexString(proto.getFieldNumber()));
sb.append("\nWire Type : ");
switch (wireType) {
case ProtoStream.WIRE_TYPE_VARINT:
- sb.append("varint");
fieldConstant = ProtoStream.makeFieldId(fieldNumber,
ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_INT64);
- sb.append("\nField Value : 0x" + Long.toHexString(proto.readLong(fieldConstant)));
+ sb.append("varint\nField Value : 0x");
+ sb.append(Long.toHexString(proto.readLong(fieldConstant)));
break;
case ProtoStream.WIRE_TYPE_FIXED64:
- sb.append("fixed64");
fieldConstant = ProtoStream.makeFieldId(fieldNumber,
ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_FIXED64);
- sb.append("\nField Value : 0x" + Long.toHexString(proto.readLong(fieldConstant)));
+ sb.append("fixed64\nField Value : 0x");
+ sb.append(Long.toHexString(proto.readLong(fieldConstant)));
break;
case ProtoStream.WIRE_TYPE_LENGTH_DELIMITED:
- sb.append("length delimited");
fieldConstant = ProtoStream.makeFieldId(fieldNumber,
ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_BYTES);
- sb.append("\nField Bytes : " + proto.readBytes(fieldConstant));
+ sb.append("length delimited\nField Bytes : ");
+ sb.append(Arrays.toString(proto.readBytes(fieldConstant)));
break;
case ProtoStream.WIRE_TYPE_START_GROUP:
sb.append("start group");
@@ -120,13 +121,13 @@ public class ProtoUtils {
sb.append("end group");
break;
case ProtoStream.WIRE_TYPE_FIXED32:
- sb.append("fixed32");
fieldConstant = ProtoStream.makeFieldId(fieldNumber,
ProtoStream.FIELD_COUNT_SINGLE | ProtoStream.FIELD_TYPE_FIXED32);
- sb.append("\nField Value : 0x" + Integer.toHexString(proto.readInt(fieldConstant)));
+ sb.append("fixed32\nField Value : 0x");
+ sb.append(Integer.toHexString(proto.readInt(fieldConstant)));
break;
default:
- sb.append("unknown(" + proto.getWireType() + ")");
+ sb.append("unknown(").append(proto.getWireType()).append(")");
}
return sb.toString();
}
diff --git a/core/java/android/view/FrameMetrics.java b/core/java/android/view/FrameMetrics.java
index 380c1045aea8..9e25a3e18c0c 100644
--- a/core/java/android/view/FrameMetrics.java
+++ b/core/java/android/view/FrameMetrics.java
@@ -116,8 +116,10 @@ public final class FrameMetrics {
* and be issued to the display subsystem.
* </p>
* <p>
- * Equal to the sum of the values of all other time-valued metric
- * identifiers.
+ * The total duration is the difference in time between when the frame
+ * began and when it ended. This value may not be exactly equal to the
+ * sum of the values of all other time-valued metric identifiers because
+ * some stages may happen concurrently.
* </p>
*/
public static final int TOTAL_DURATION = 8;
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index 57ba7e9e816f..f9bb880b1881 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -653,7 +653,7 @@ public class GestureDetector {
break;
case MotionEvent.ACTION_MOVE:
- if (mInLongPress || mInContextClick) {
+ if ((mCurrentDownEvent == null) || mInLongPress || mInContextClick) {
break;
}
@@ -736,6 +736,9 @@ public class GestureDetector {
break;
case MotionEvent.ACTION_UP:
+ if (mCurrentDownEvent == null) {
+ break;
+ }
mStillDown = false;
MotionEvent currentUpEvent = MotionEvent.obtain(ev);
if (mIsDoubleTapping) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index e0f02d6e567a..2a45fa563abf 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -1943,7 +1943,7 @@ public final class SurfaceControl implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(supportedDisplayModes, activeDisplayModeId, activeDisplayModeId,
+ return Objects.hash(Arrays.hashCode(supportedDisplayModes), activeDisplayModeId,
activeColorMode, hdrCapabilities);
}
}
diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java
index db58704b5d6a..c3fd21649f46 100644
--- a/core/java/android/window/WindowContainerTransaction.java
+++ b/core/java/android/window/WindowContainerTransaction.java
@@ -443,6 +443,17 @@ public final class WindowContainerTransaction implements Parcelable {
}
/**
+ * Finds and removes a task and its children using its container token. The task is removed
+ * from recents.
+ * @param containerToken ContainerToken of Task to be removed
+ */
+ @NonNull
+ public WindowContainerTransaction removeTask(@NonNull WindowContainerToken containerToken) {
+ mHierarchyOps.add(HierarchyOp.createForRemoveTask(containerToken.asBinder()));
+ return this;
+ }
+
+ /**
* Sends a pending intent in sync.
* @param sender The PendingIntent sender.
* @param intent The fillIn intent to patch over the sender's base intent.
@@ -1141,6 +1152,7 @@ public final class WindowContainerTransaction implements Parcelable {
public static final int HIERARCHY_OP_TYPE_REMOVE_INSETS_PROVIDER = 17;
public static final int HIERARCHY_OP_TYPE_REQUEST_FOCUS_ON_TASK_FRAGMENT = 18;
public static final int HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP = 19;
+ public static final int HIERARCHY_OP_TYPE_REMOVE_TASK = 20;
// The following key(s) are for use with mLaunchOptions:
// When launching a task (eg. from recents), this is the taskId to be launched.
@@ -1270,6 +1282,13 @@ public final class WindowContainerTransaction implements Parcelable {
.build();
}
+ /** create a hierarchy op for deleting a task **/
+ public static HierarchyOp createForRemoveTask(@NonNull IBinder container) {
+ return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REMOVE_TASK)
+ .setContainer(container)
+ .build();
+ }
+
/** Only creates through {@link Builder}. */
private HierarchyOp(int type) {
mType = type;
@@ -1453,6 +1472,8 @@ public final class WindowContainerTransaction implements Parcelable {
case HIERARCHY_OP_TYPE_SET_ALWAYS_ON_TOP:
return "{setAlwaysOnTop: container=" + mContainer
+ " alwaysOnTop=" + mAlwaysOnTop + "}";
+ case HIERARCHY_OP_TYPE_REMOVE_TASK:
+ return "{RemoveTask: task=" + mContainer + "}";
default:
return "{mType=" + mType + " container=" + mContainer + " reparent=" + mReparent
+ " mToTop=" + mToTop
diff --git a/core/java/com/android/internal/inputmethod/InputMethodDebug.java b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
index 33cb56f4ce69..b5fc05bc9938 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodDebug.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
@@ -227,6 +227,8 @@ public final class InputMethodDebug {
return "HIDE_DOCKED_STACK_ATTACHED";
case SoftInputShowHideReason.HIDE_RECENTS_ANIMATION:
return "HIDE_RECENTS_ANIMATION";
+ case SoftInputShowHideReason.HIDE_BUBBLES:
+ return "HIDE_BUBBLES";
case SoftInputShowHideReason.HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR:
return "HIDE_SAME_WINDOW_FOCUSED_WITHOUT_EDITOR";
case SoftInputShowHideReason.HIDE_REMOVE_CLIENT:
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 6909965edcd8..7001c69f4042 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -21,6 +21,7 @@ import android.os.BatteryManager;
import android.os.BatteryStats.HistoryItem;
import android.os.BatteryStats.HistoryStepDetails;
import android.os.BatteryStats.HistoryTag;
+import android.os.BatteryStats.MeasuredEnergyDetails;
import android.os.Parcel;
import android.os.ParcelFormatException;
import android.os.Process;
@@ -113,6 +114,9 @@ public class BatteryStatsHistory {
// therefore the tag value is written in the parcel
static final int TAG_FIRST_OCCURRENCE_FLAG = 0x8000;
+ static final int EXTENSION_MEASURED_ENERGY_HEADER_FLAG = 0x00000001;
+ static final int EXTENSION_MEASURED_ENERGY_FLAG = 0x00000002;
+
private final Parcel mHistoryBuffer;
private final File mSystemDir;
private final HistoryStepDetailsCalculator mStepDetailsCalculator;
@@ -183,6 +187,7 @@ public class BatteryStatsHistory {
private long mTrackRunningHistoryElapsedRealtimeMs = 0;
private long mTrackRunningHistoryUptimeMs = 0;
private long mHistoryBaseTimeMs;
+ private boolean mMeasuredEnergyHeaderWritten = false;
private byte mLastHistoryStepLevel = 0;
@@ -293,6 +298,7 @@ public class BatteryStatsHistory {
mLastHistoryElapsedRealtimeMs = 0;
mTrackRunningHistoryElapsedRealtimeMs = 0;
mTrackRunningHistoryUptimeMs = 0;
+ mMeasuredEnergyHeaderWritten = false;
mHistoryBuffer.setDataSize(0);
mHistoryBuffer.setDataPosition(0);
@@ -933,6 +939,16 @@ public class BatteryStatsHistory {
}
/**
+ * Records measured energy data.
+ */
+ public void recordMeasuredEnergyDetails(long elapsedRealtimeMs, long uptimeMs,
+ MeasuredEnergyDetails measuredEnergyDetails) {
+ mHistoryCur.measuredEnergyDetails = measuredEnergyDetails;
+ mHistoryCur.states2 |= HistoryItem.STATE2_EXTENSIONS_FLAG;
+ writeHistoryItem(elapsedRealtimeMs, uptimeMs);
+ }
+
+ /**
* Records a history item with the amount of charge consumed by WiFi. Used on certain devices
* equipped with on-device power metering.
*/
@@ -1219,6 +1235,8 @@ public class BatteryStatsHistory {
for (Map.Entry<HistoryTag, Integer> entry : mHistoryTagPool.entrySet()) {
entry.setValue(entry.getValue() | BatteryStatsHistory.TAG_FIRST_OCCURRENCE_FLAG);
}
+ mMeasuredEnergyHeaderWritten = false;
+
// Make a copy of mHistoryCur.
HistoryItem copy = new HistoryItem();
copy.setTo(cur);
@@ -1256,6 +1274,7 @@ public class BatteryStatsHistory {
cur.eventCode = HistoryItem.EVENT_NONE;
cur.eventTag = null;
cur.tagsFirstOccurrence = false;
+ cur.measuredEnergyDetails = null;
if (DEBUG) {
Slog.i(TAG, "Writing history buffer: was " + mHistoryBufferLastPos
+ " now " + mHistoryBuffer.dataPosition()
@@ -1348,6 +1367,7 @@ public class BatteryStatsHistory {
return;
}
+ int extensionFlags = 0;
final long deltaTime = cur.time - last.time;
final int lastBatteryLevelInt = buildBatteryLevelInt(last);
final int lastStateInt = buildStateInt(last);
@@ -1374,6 +1394,17 @@ public class BatteryStatsHistory {
if (stateIntChanged) {
firstToken |= BatteryStatsHistory.DELTA_STATE_FLAG;
}
+ if (cur.measuredEnergyDetails != null) {
+ extensionFlags |= BatteryStatsHistory.EXTENSION_MEASURED_ENERGY_FLAG;
+ if (!mMeasuredEnergyHeaderWritten) {
+ extensionFlags |= BatteryStatsHistory.EXTENSION_MEASURED_ENERGY_HEADER_FLAG;
+ }
+ }
+ if (extensionFlags != 0) {
+ cur.states2 |= HistoryItem.STATE2_EXTENSIONS_FLAG;
+ } else {
+ cur.states2 &= ~HistoryItem.STATE2_EXTENSIONS_FLAG;
+ }
final boolean state2IntChanged = cur.states2 != last.states2;
if (state2IntChanged) {
firstToken |= BatteryStatsHistory.DELTA_STATE2_FLAG;
@@ -1491,6 +1522,28 @@ public class BatteryStatsHistory {
}
dest.writeDouble(cur.modemRailChargeMah);
dest.writeDouble(cur.wifiRailChargeMah);
+ if (extensionFlags != 0) {
+ dest.writeInt(extensionFlags);
+ if (cur.measuredEnergyDetails != null) {
+ if (DEBUG) {
+ Slog.i(TAG, "WRITE DELTA: measuredEnergyDetails=" + cur.measuredEnergyDetails);
+ }
+ if (!mMeasuredEnergyHeaderWritten) {
+ MeasuredEnergyDetails.EnergyConsumer[] consumers =
+ cur.measuredEnergyDetails.consumers;
+ dest.writeInt(consumers.length);
+ for (MeasuredEnergyDetails.EnergyConsumer consumer : consumers) {
+ dest.writeInt(consumer.type);
+ dest.writeInt(consumer.ordinal);
+ dest.writeString(consumer.name);
+ }
+ mMeasuredEnergyHeaderWritten = true;
+ }
+ for (long chargeUC : cur.measuredEnergyDetails.chargeUC) {
+ dest.writeLong(chargeUC);
+ }
+ }
+ }
}
private int buildBatteryLevelInt(HistoryItem h) {
diff --git a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
index 1bf878cb9119..ee3d15b1ad7e 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistoryIterator.java
@@ -33,6 +33,7 @@ public class BatteryStatsHistoryIterator {
private final BatteryStats.HistoryStepDetails mReadHistoryStepDetails =
new BatteryStats.HistoryStepDetails();
private final SparseArray<BatteryStats.HistoryTag> mHistoryTags = new SparseArray<>();
+ private BatteryStats.MeasuredEnergyDetails mMeasuredEnergyDetails;
public BatteryStatsHistoryIterator(@NonNull BatteryStatsHistory history) {
mBatteryStatsHistory = history;
@@ -198,6 +199,40 @@ public class BatteryStatsHistoryIterator {
}
cur.modemRailChargeMah = src.readDouble();
cur.wifiRailChargeMah = src.readDouble();
+ if ((cur.states2 & BatteryStats.HistoryItem.STATE2_EXTENSIONS_FLAG) != 0) {
+ final int extensionFlags = src.readInt();
+ if ((extensionFlags & BatteryStatsHistory.EXTENSION_MEASURED_ENERGY_HEADER_FLAG) != 0) {
+ if (mMeasuredEnergyDetails == null) {
+ mMeasuredEnergyDetails = new BatteryStats.MeasuredEnergyDetails();
+ }
+
+ final int consumerCount = src.readInt();
+ mMeasuredEnergyDetails.consumers =
+ new BatteryStats.MeasuredEnergyDetails.EnergyConsumer[consumerCount];
+ mMeasuredEnergyDetails.chargeUC = new long[consumerCount];
+ for (int i = 0; i < consumerCount; i++) {
+ BatteryStats.MeasuredEnergyDetails.EnergyConsumer consumer =
+ new BatteryStats.MeasuredEnergyDetails.EnergyConsumer();
+ consumer.type = src.readInt();
+ consumer.ordinal = src.readInt();
+ consumer.name = src.readString();
+ mMeasuredEnergyDetails.consumers[i] = consumer;
+ }
+ }
+
+ if ((extensionFlags & BatteryStatsHistory.EXTENSION_MEASURED_ENERGY_FLAG) != 0) {
+ if (mMeasuredEnergyDetails == null) {
+ throw new IllegalStateException("MeasuredEnergyDetails without a header");
+ }
+
+ for (int i = 0; i < mMeasuredEnergyDetails.chargeUC.length; i++) {
+ mMeasuredEnergyDetails.chargeUC[i] = src.readLong();
+ }
+ cur.measuredEnergyDetails = mMeasuredEnergyDetails;
+ }
+ } else {
+ cur.measuredEnergyDetails = null;
+ }
}
private boolean readHistoryTag(Parcel src, int index, BatteryStats.HistoryTag outTag) {
diff --git a/core/java/com/android/internal/widget/LocalImageResolver.java b/core/java/com/android/internal/widget/LocalImageResolver.java
index b11ea2961c17..9ef7ce38fc09 100644
--- a/core/java/com/android/internal/widget/LocalImageResolver.java
+++ b/core/java/com/android/internal/widget/LocalImageResolver.java
@@ -19,6 +19,8 @@ package com.android.internal.widget;
import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.ImageDecoder;
@@ -109,13 +111,13 @@ public class LocalImageResolver {
}
break;
case Icon.TYPE_RESOURCE:
- if (!(TextUtils.isEmpty(icon.getResPackage())
- || context.getPackageName().equals(icon.getResPackage()))) {
- // We can't properly resolve icons from other packages here, so fall back.
+ Resources res = resolveResourcesForIcon(context, icon);
+ if (res == null) {
+ // We couldn't resolve resources properly, fall back to icon loading.
return icon.loadDrawable(context);
}
- Drawable result = resolveImage(icon.getResId(), context, maxWidth, maxHeight);
+ Drawable result = resolveImage(res, icon.getResId(), maxWidth, maxHeight);
if (result != null) {
return tintDrawable(icon, result);
}
@@ -159,6 +161,13 @@ public class LocalImageResolver {
}
@Nullable
+ private static Drawable resolveImage(Resources res, @DrawableRes int resId, int maxWidth,
+ int maxHeight) {
+ final ImageDecoder.Source source = ImageDecoder.createSource(res, resId);
+ return resolveImage(source, maxWidth, maxHeight);
+ }
+
+ @Nullable
private static Drawable resolveBitmapImage(Icon icon, Context context, int maxWidth,
int maxHeight) {
@@ -259,4 +268,52 @@ public class LocalImageResolver {
}
return icon.getUri();
}
+
+ /**
+ * Resolves the correct resources package for a given Icon - it may come from another
+ * package.
+ *
+ * @see Icon#loadDrawableInner(Context)
+ * @hide
+ *
+ * @return resources instance if the operation succeeded, null otherwise
+ */
+ @Nullable
+ @VisibleForTesting
+ public static Resources resolveResourcesForIcon(Context context, Icon icon) {
+ if (icon.getType() != Icon.TYPE_RESOURCE) {
+ return null;
+ }
+
+ // Icons cache resolved resources, use cache if available.
+ Resources res = icon.getResources();
+ if (res != null) {
+ return res;
+ }
+
+ String resPackage = icon.getResPackage();
+ // No package means we try to use current context.
+ if (TextUtils.isEmpty(resPackage) || context.getPackageName().equals(resPackage)) {
+ return context.getResources();
+ }
+
+ if ("android".equals(resPackage)) {
+ return Resources.getSystem();
+ }
+
+ final PackageManager pm = context.getPackageManager();
+ try {
+ ApplicationInfo ai = pm.getApplicationInfo(resPackage,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.GET_SHARED_LIBRARY_FILES);
+ if (ai != null) {
+ return pm.getResourcesForApplication(ai);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, String.format("Unable to resolve package %s for icon %s", resPackage, icon));
+ return null;
+ }
+
+ return null;
+ }
}
diff --git a/core/java/com/android/internal/widget/LockscreenCredential.java b/core/java/com/android/internal/widget/LockscreenCredential.java
index 9f3f335f3173..03e7fd1c7403 100644
--- a/core/java/com/android/internal/widget/LockscreenCredential.java
+++ b/core/java/com/android/internal/widget/LockscreenCredential.java
@@ -26,7 +26,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
-import android.os.storage.StorageManager;
import android.text.TextUtils;
import com.android.internal.util.ArrayUtils;
@@ -347,7 +346,7 @@ public class LockscreenCredential implements Parcelable, AutoCloseable {
@Override
public int hashCode() {
// Effective Java — Always override hashCode when you override equals
- return (17 + mType) * 31 + mCredential.hashCode();
+ return Objects.hash(mType, Arrays.hashCode(mCredential));
}
@Override
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 7f50204fb842..14699e7097f4 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -95,3 +95,7 @@ per-file android_os_VintfRuntimeInfo* = file:platform/system/libvintf:/OWNERS
# Battery
per-file com_android_internal_os_Kernel* = file:/BATTERY_STATS_OWNERS
per-file com_android_internal_os_*MultiStateCounter* = file:/BATTERY_STATS_OWNERS
+
+# PM
+per-file com_android_internal_content_* = file:/PACKAGE_MANAGER_OWNERS
+
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index be82879c8411..acf4da6a5d07 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -17,28 +17,25 @@
#define LOG_TAG "NativeLibraryHelper"
//#define LOG_NDEBUG 0
-#include "core_jni_helpers.h"
-
-#include <nativehelper/ScopedUtfChars.h>
#include <androidfw/ZipFileRO.h>
#include <androidfw/ZipUtils.h>
-#include <utils/Log.h>
-#include <utils/Vector.h>
-
-#include <zlib.h>
-
#include <errno.h>
#include <fcntl.h>
+#include <inttypes.h>
+#include <nativehelper/ScopedUtfChars.h>
#include <stdlib.h>
#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <inttypes.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+#include <utils/Log.h>
+#include <zlib.h>
#include <memory>
+#include "core_jni_helpers.h"
+
#define APK_LIB "lib/"
#define APK_LIB_LEN (sizeof(APK_LIB) - 1)
@@ -156,7 +153,7 @@ sumFiles(JNIEnv*, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntry, const char
size_t* total = (size_t*) arg;
uint32_t uncompLen;
- if (!zipFile->getEntryInfo(zipEntry, NULL, &uncompLen, NULL, NULL, NULL, NULL)) {
+ if (!zipFile->getEntryInfo(zipEntry, nullptr, &uncompLen, nullptr, nullptr, nullptr, nullptr)) {
return INSTALL_FAILED_INVALID_APK;
}
@@ -186,7 +183,7 @@ copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntr
uint16_t method;
off64_t offset;
- if (!zipFile->getEntryInfo(zipEntry, &method, &uncompLen, NULL, &offset, &when, &crc)) {
+ if (!zipFile->getEntryInfo(zipEntry, &method, &uncompLen, nullptr, &offset, &when, &crc)) {
ALOGE("Couldn't read zip entry info\n");
return INSTALL_FAILED_INVALID_APK;
}
@@ -307,24 +304,24 @@ copyFileIfChanged(JNIEnv *env, void* arg, ZipFileRO* zipFile, ZipEntryRO zipEntr
class NativeLibrariesIterator {
private:
NativeLibrariesIterator(ZipFileRO* zipFile, bool debuggable, void* cookie)
- : mZipFile(zipFile), mDebuggable(debuggable), mCookie(cookie), mLastSlash(NULL) {
+ : mZipFile(zipFile), mDebuggable(debuggable), mCookie(cookie), mLastSlash(nullptr) {
fileName[0] = '\0';
}
public:
static NativeLibrariesIterator* create(ZipFileRO* zipFile, bool debuggable) {
- void* cookie = NULL;
+ void* cookie = nullptr;
// Do not specify a suffix to find both .so files and gdbserver.
- if (!zipFile->startIteration(&cookie, APK_LIB, NULL /* suffix */)) {
- return NULL;
+ if (!zipFile->startIteration(&cookie, APK_LIB, nullptr /* suffix */)) {
+ return nullptr;
}
return new NativeLibrariesIterator(zipFile, debuggable, cookie);
}
ZipEntryRO next() {
- ZipEntryRO next = NULL;
- while ((next = mZipFile->nextEntry(mCookie)) != NULL) {
+ ZipEntryRO next = nullptr;
+ while ((next = mZipFile->nextEntry(mCookie)) != nullptr) {
// Make sure this entry has a filename.
if (mZipFile->getEntryFileName(next, fileName, sizeof(fileName))) {
continue;
@@ -338,7 +335,7 @@ public:
}
const char* lastSlash = strrchr(fileName, '/');
- ALOG_ASSERT(lastSlash != NULL, "last slash was null somehow for %s\n", fileName);
+ ALOG_ASSERT(lastSlash != nullptr, "last slash was null somehow for %s\n", fileName);
// Skip directories.
if (*(lastSlash + 1) == 0) {
@@ -389,24 +386,23 @@ static install_status_t
iterateOverNativeFiles(JNIEnv *env, jlong apkHandle, jstring javaCpuAbi,
jboolean debuggable, iterFunc callFunc, void* callArg) {
ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
- if (zipFile == NULL) {
+ if (zipFile == nullptr) {
return INSTALL_FAILED_INVALID_APK;
}
std::unique_ptr<NativeLibrariesIterator> it(
NativeLibrariesIterator::create(zipFile, debuggable));
- if (it.get() == NULL) {
+ if (it.get() == nullptr) {
return INSTALL_FAILED_INVALID_APK;
}
const ScopedUtfChars cpuAbi(env, javaCpuAbi);
- if (cpuAbi.c_str() == NULL) {
- // This would've thrown, so this return code isn't observable by
- // Java.
+ if (cpuAbi.c_str() == nullptr) {
+ // This would've thrown, so this return code isn't observable by Java.
return INSTALL_FAILED_INVALID_APK;
}
- ZipEntryRO entry = NULL;
- while ((entry = it->next()) != NULL) {
+ ZipEntryRO entry = nullptr;
+ while ((entry = it->next()) != nullptr) {
const char* fileName = it->currentEntry();
const char* lastSlash = it->lastSlash();
@@ -427,31 +423,30 @@ iterateOverNativeFiles(JNIEnv *env, jlong apkHandle, jstring javaCpuAbi,
return INSTALL_SUCCEEDED;
}
-
-static int findSupportedAbi(JNIEnv *env, jlong apkHandle, jobjectArray supportedAbisArray,
- jboolean debuggable) {
- const int numAbis = env->GetArrayLength(supportedAbisArray);
- Vector<ScopedUtfChars*> supportedAbis;
-
- for (int i = 0; i < numAbis; ++i) {
- supportedAbis.add(new ScopedUtfChars(env,
- (jstring) env->GetObjectArrayElement(supportedAbisArray, i)));
- }
-
+static int findSupportedAbi(JNIEnv* env, jlong apkHandle, jobjectArray supportedAbisArray,
+ jboolean debuggable) {
ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
- if (zipFile == NULL) {
+ if (zipFile == nullptr) {
return INSTALL_FAILED_INVALID_APK;
}
std::unique_ptr<NativeLibrariesIterator> it(
NativeLibrariesIterator::create(zipFile, debuggable));
- if (it.get() == NULL) {
+ if (it.get() == nullptr) {
return INSTALL_FAILED_INVALID_APK;
}
- ZipEntryRO entry = NULL;
+ const int numAbis = env->GetArrayLength(supportedAbisArray);
+
+ std::vector<ScopedUtfChars> supportedAbis;
+ supportedAbis.reserve(numAbis);
+ for (int i = 0; i < numAbis; ++i) {
+ supportedAbis.emplace_back(env, (jstring)env->GetObjectArrayElement(supportedAbisArray, i));
+ }
+
+ ZipEntryRO entry = nullptr;
int status = NO_NATIVE_LIBRARIES;
- while ((entry = it->next()) != NULL) {
+ while ((entry = it->next()) != nullptr) {
// We're currently in the lib/ directory of the APK, so it does have some native
// code. We should return INSTALL_FAILED_NO_MATCHING_ABIS if none of the
// libraries match.
@@ -466,8 +461,8 @@ static int findSupportedAbi(JNIEnv *env, jlong apkHandle, jobjectArray supported
const char* abiOffset = fileName + APK_LIB_LEN;
const size_t abiSize = lastSlash - abiOffset;
for (int i = 0; i < numAbis; i++) {
- const ScopedUtfChars* abi = supportedAbis[i];
- if (abi->size() == abiSize && !strncmp(abiOffset, abi->c_str(), abiSize)) {
+ const ScopedUtfChars& abi = supportedAbis[i];
+ if (abi.size() == abiSize && !strncmp(abiOffset, abi.c_str(), abiSize)) {
// The entry that comes in first (i.e. with a lower index) has the higher priority.
if (((i < status) && (status >= 0)) || (status < 0) ) {
status = i;
@@ -476,10 +471,6 @@ static int findSupportedAbi(JNIEnv *env, jlong apkHandle, jobjectArray supported
}
}
- for (int i = 0; i < numAbis; ++i) {
- delete supportedAbis[i];
- }
-
return status;
}
@@ -521,19 +512,19 @@ static jint
com_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode(JNIEnv *env, jclass clazz,
jlong apkHandle) {
ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
- void* cookie = NULL;
- if (!zipFile->startIteration(&cookie, NULL /* prefix */, RS_BITCODE_SUFFIX)) {
+ void* cookie = nullptr;
+ if (!zipFile->startIteration(&cookie, nullptr /* prefix */, RS_BITCODE_SUFFIX)) {
return APK_SCAN_ERROR;
}
char fileName[PATH_MAX];
- ZipEntryRO next = NULL;
- while ((next = zipFile->nextEntry(cookie)) != NULL) {
+ ZipEntryRO next = nullptr;
+ while ((next = zipFile->nextEntry(cookie)) != nullptr) {
if (zipFile->getEntryFileName(next, fileName, sizeof(fileName))) {
continue;
}
const char* lastSlash = strrchr(fileName, '/');
- const char* baseName = (lastSlash == NULL) ? fileName : fileName + 1;
+ const char* baseName = (lastSlash == nullptr) ? fileName : fileName + 1;
if (isFilenameSafe(baseName)) {
zipFile->endIteration(cookie);
return BITCODE_PRESENT;
diff --git a/core/jni/com_android_internal_security_VerityUtils.cpp b/core/jni/com_android_internal_security_VerityUtils.cpp
index c5b3d8ae936c..8305bd087bfd 100644
--- a/core/jni/com_android_internal_security_VerityUtils.cpp
+++ b/core/jni/com_android_internal_security_VerityUtils.cpp
@@ -111,10 +111,10 @@ int measureFsverity(JNIEnv *env, jobject /* clazz */, jstring filePath, jbyteArr
ScopedUtfChars path(env, filePath);
::android::base::unique_fd rfd(open(path.c_str(), O_RDONLY | O_CLOEXEC));
if (rfd.get() < 0) {
- return rfd.get();
+ return -errno;
}
- if (auto err = ioctl(rfd.get(), FS_IOC_MEASURE_VERITY, data); err < 0) {
- return err;
+ if (::ioctl(rfd.get(), FS_IOC_MEASURE_VERITY, data) < 0) {
+ return -errno;
}
if (data->digest_algorithm != FS_VERITY_HASH_ALG_SHA256) {
diff --git a/core/proto/android/app/notificationmanager.proto b/core/proto/android/app/notificationmanager.proto
index b88315e2dbee..3342c79b7d3f 100644
--- a/core/proto/android/app/notificationmanager.proto
+++ b/core/proto/android/app/notificationmanager.proto
@@ -45,6 +45,8 @@ message PolicyProto {
MEDIA = 7;
// System (catch-all for non-never suppressible sounds) are prioritized.
SYSTEM = 8;
+ // Priority conversations are prioritized
+ CONVERSATIONS = 9;
}
repeated Category priority_categories = 1;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5b4fc56bc8ba..4d41c3091786 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -923,7 +923,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.SEND_SMS"
@@ -937,7 +937,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.RECEIVE_SMS"
@@ -951,7 +951,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.READ_SMS"
@@ -965,7 +965,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.RECEIVE_WAP_PUSH"
@@ -979,7 +979,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.RECEIVE_MMS"
@@ -1014,7 +1014,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
@hide Pending API council approval -->
@@ -1059,7 +1059,7 @@
targetSdkVersion}</a> is 4 or higher.
<p> This is a soft restricted permission which cannot be held by an app it its
- full form until the installer on record whitelists the permission.
+ full form until the installer on record allowlists the permission.
Specifically, if the permission is allowlisted the holder app can access
external storage and the visual and aural media collections while if the
permission is not allowlisted the holder app can only access to the visual
@@ -1239,7 +1239,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"
@@ -1301,7 +1301,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.READ_CALL_LOG"
@@ -1325,7 +1325,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
-->
<permission android:name="android.permission.WRITE_CALL_LOG"
@@ -1341,7 +1341,7 @@
<p>Protection level: dangerous
<p> This is a hard restricted permission which cannot be held by an app until
- the installer on record whitelists the permission. For more details see
+ the installer on record allowlists the permission. For more details see
{@link android.content.pm.PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(Set)}.
@deprecated Applications should use {@link android.telecom.CallRedirectionService} instead
@@ -4771,7 +4771,7 @@
android:protectionLevel="signature" />
<!-- @SystemApi Allows an application to allowlist restricted permissions
- on any of the whitelists.
+ on any of the allowlists.
@hide -->
<permission android:name="android.permission.WHITELIST_RESTRICTED_PERMISSIONS"
android:protectionLevel="signature|installer" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 6a52ec91fa32..418da66c267e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1565,7 +1565,8 @@
<bool name="config_enableIdleScreenBrightnessMode">false</bool>
<!-- Array of desired screen brightness in nits corresponding to the lux values
- in the config_autoBrightnessLevels array. The display brightness is defined as the measured
+ in the config_autoBrightnessLevels array. As with config_screenBrightnessMinimumNits and
+ config_screenBrightnessMaximumNits, the display brightness is defined as the measured
brightness of an all-white image.
If this is defined then:
@@ -1586,7 +1587,7 @@
<array name="config_autoBrightnessDisplayValuesNitsIdle">
</array>
- <!-- Array of output values for button backlight corresponding to the lux values
+ <!-- Array of output values for button backlight corresponding to the luX values
in the config_autoBrightnessLevels array. This array should have size one greater
than the size of the config_autoBrightnessLevels array.
The brightness values must be between 0 and 255 and be non-decreasing.
@@ -4858,6 +4859,14 @@
<item>0.875</item>
</string-array>
+ <!-- When each intermediate SFPS enroll stage ends, as a fraction of total progress. -->
+ <string-array name="config_sfps_enroll_stage_thresholds" translatable="false">
+ <item>0</item> <!-- [-1 // <0/25] No animation 1x -->
+ <item>0.36</item> <!-- [0 to 8 // <9/25] Pad center 9x -->
+ <item>0.52</item> <!-- [9 to 12 // <13/25] Tip 4x -->
+ <item>0.76</item> <!-- [13 to 18 // <19/25] Left 6x -->
+ </string-array> <!-- [19 to 24 // <25/25] Right 6x -->
+
<!-- Messages that should not be shown to the user during face auth enrollment. This should be
used to hide messages that may be too chatty or messages that the user can't do much about.
Entries are defined in android.hardware.biometrics.face@1.0 types.hal -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e5b1cf9be748..8488b6865440 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1733,7 +1733,7 @@
<!-- Generic error message shown when the fingerprint operation fails because too many attempts have been made. -->
<string name="fingerprint_error_lockout">Too many attempts. Try again later.</string>
<!-- Generic error message shown when the fingerprint operation fails because strong authentication is required -->
- <string name="fingerprint_error_lockout_permanent">Too many attempts. Fingerprint sensor disabled.</string>
+ <string name="fingerprint_error_lockout_permanent">Too many attempts. Use screen lock instead.</string>
<!-- Generic error message shown when the fingerprint hardware can't recognize the fingerprint -->
<string name="fingerprint_error_unable_to_process">Try again.</string>
<!-- Generic error message shown when the user has no enrolled fingerprints -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index aa0bae656da6..0a13c8b28de4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2701,7 +2701,7 @@
<java-symbol type="integer" name="config_udfps_illumination_transition_ms" />
<java-symbol type="bool" name="config_is_powerbutton_fps" />
<java-symbol type="array" name="config_udfps_enroll_stage_thresholds" />
-
+ <java-symbol type="array" name="config_sfps_enroll_stage_thresholds" />
<java-symbol type="array" name="config_face_acquire_enroll_ignorelist" />
<java-symbol type="array" name="config_face_acquire_vendor_enroll_ignorelist" />
<java-symbol type="array" name="config_face_acquire_keyguard_ignorelist" />
diff --git a/core/tests/coretests/src/android/provider/FontsContractTest.java b/core/tests/coretests/src/android/provider/FontsContractTest.java
index c5d6f7fad3e8..21a22057d7c8 100644
--- a/core/tests/coretests/src/android/provider/FontsContractTest.java
+++ b/core/tests/coretests/src/android/provider/FontsContractTest.java
@@ -42,6 +42,7 @@ import androidx.test.filters.SmallTest;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
/**
@@ -282,9 +283,10 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> {
setupPackageManager();
byte[] wrongCert = Base64.decode("this is a wrong cert", Base64.DEFAULT);
- List<byte[]> certList = Arrays.asList(wrongCert);
+ List<byte[]> certList = Collections.singletonList(wrongCert);
FontRequest requestWrongCerts = new FontRequest(
- TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
+ TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query",
+ Collections.singletonList(certList));
assertNull(FontsContract.getProvider(mPackageManager, requestWrongCerts));
}
@@ -293,9 +295,10 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> {
throws PackageManager.NameNotFoundException {
ProviderInfo info = setupPackageManager();
- List<byte[]> certList = Arrays.asList(BYTE_ARRAY);
+ List<byte[]> certList = Collections.singletonList(BYTE_ARRAY);
FontRequest requestRightCerts = new FontRequest(
- TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
+ TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query",
+ Collections.singletonList(certList));
ProviderInfo result = FontsContract.getProvider(
mPackageManager, requestRightCerts);
@@ -309,7 +312,8 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> {
byte[] wrongCert = Base64.decode("this is a wrong cert", Base64.DEFAULT);
List<byte[]> certList = Arrays.asList(wrongCert, BYTE_ARRAY);
FontRequest requestRightCerts = new FontRequest(
- TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
+ TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query",
+ Collections.singletonList(certList));
assertNull(FontsContract.getProvider(mPackageManager, requestRightCerts));
}
@@ -332,7 +336,8 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> {
// {BYTE_ARRAY_2, BYTE_ARRAY_COPY}.
List<byte[]> certList = Arrays.asList(BYTE_ARRAY_2, BYTE_ARRAY_COPY);
FontRequest requestRightCerts = new FontRequest(
- TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", Arrays.asList(certList));
+ TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query",
+ Collections.singletonList(certList));
assertNull(FontsContract.getProvider(mPackageManager, requestRightCerts));
}
@@ -341,9 +346,9 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> {
ProviderInfo info = setupPackageManager();
List<List<byte[]>> certList = new ArrayList<>();
- byte[] wrongCert = Base64.decode("this is a wrong cert", Base64.DEFAULT);
- certList.add(Arrays.asList(wrongCert));
- certList.add(Arrays.asList(BYTE_ARRAY));
+ certList.add(Collections.singletonList(
+ Base64.decode("this is a wrong cert", Base64.DEFAULT)));
+ certList.add(Collections.singletonList(BYTE_ARRAY));
FontRequest requestRightCerts = new FontRequest(
TestFontsProvider.AUTHORITY, PACKAGE_NAME, "query", certList);
ProviderInfo result = FontsContract.getProvider(mPackageManager, requestRightCerts);
@@ -356,7 +361,7 @@ public class FontsContractTest extends ProviderTestCase2<TestFontsProvider> {
setupPackageManager();
List<List<byte[]>> certList = new ArrayList<>();
- certList.add(Arrays.asList(BYTE_ARRAY));
+ certList.add(Collections.singletonList(BYTE_ARRAY));
FontRequest requestRightCerts = new FontRequest(
TestFontsProvider.AUTHORITY, "com.wrong.package.name", "query", certList);
try {
diff --git a/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java b/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java
index 0cee526651a6..271a20b71106 100644
--- a/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/LocalImageResolverTest.java
@@ -17,6 +17,8 @@
package com.android.internal.widget;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.graphics.BitmapFactory;
import android.graphics.drawable.AdaptiveIconDrawable;
import android.graphics.drawable.BitmapDrawable;
@@ -279,4 +281,49 @@ public class LocalImageResolverTest {
// This drawable must not be loaded - if it was, the code ignored the package specification.
assertThat(d).isNull();
}
+
+ @Test
+ public void resolveResourcesForIcon_notAResourceIcon_returnsNull() {
+ Icon icon = Icon.createWithContentUri(Uri.parse("some_uri"));
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon)).isNull();
+ }
+
+ @Test
+ public void resolveResourcesForIcon_localPackageIcon_returnsPackageResources() {
+ Icon icon = Icon.createWithResource(mContext, R.drawable.test32x24);
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon))
+ .isSameInstanceAs(mContext.getResources());
+ }
+
+ @Test
+ public void resolveResourcesForIcon_iconWithoutPackageSpecificed_returnsPackageResources() {
+ Icon icon = Icon.createWithResource("", R.drawable.test32x24);
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon))
+ .isSameInstanceAs(mContext.getResources());
+ }
+
+ @Test
+ public void resolveResourcesForIcon_systemPackageSpecified_returnsSystemPackage() {
+ Icon icon = Icon.createWithResource("android", R.drawable.test32x24);
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon)).isSameInstanceAs(
+ Resources.getSystem());
+ }
+
+ @Test
+ public void resolveResourcesForIcon_differentPackageSpecified_returnsPackageResources() throws
+ PackageManager.NameNotFoundException {
+ String pkg = "com.android.settings";
+ Resources res = mContext.getPackageManager().getResourcesForApplication(pkg);
+ int resId = res.getIdentifier("ic_android", "drawable", pkg);
+ Icon icon = Icon.createWithResource(pkg, resId);
+
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon).getDrawable(resId,
+ mContext.getTheme())).isNotNull();
+ }
+
+ @Test
+ public void resolveResourcesForIcon_invalidPackageSpecified_returnsNull() {
+ Icon icon = Icon.createWithResource("invalid.package", R.drawable.test32x24);
+ assertThat(LocalImageResolver.resolveResourcesForIcon(mContext, icon)).isNull();
+ }
}
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 3170177b819c..68d2a4045905 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1,12 +1,6 @@
{
"version": "1.0.0",
"messages": {
- "-2146181682": {
- "message": "Releasing screen wakelock, obscured by %s",
- "level": "DEBUG",
- "group": "WM_DEBUG_KEEP_SCREEN_ON",
- "at": "com\/android\/server\/wm\/WindowManagerService.java"
- },
"-2127842445": {
"message": "Clearing startingData for token=%s",
"level": "VERBOSE",
@@ -1783,6 +1777,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "-384639879": {
+ "message": "Acquiring screen wakelock due to %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_KEEP_SCREEN_ON",
+ "at": "com\/android\/server\/wm\/DisplayContent.java"
+ },
"-381522987": {
"message": "Display %d state is now (%d), so update recording?",
"level": "VERBOSE",
@@ -2389,6 +2389,12 @@
"group": "WM_DEBUG_STATES",
"at": "com\/android\/server\/wm\/ActivityRecord.java"
},
+ "191486492": {
+ "message": "handleNotObscuredLocked: %s was holding screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by%s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_KEEP_SCREEN_ON",
+ "at": "com\/android\/server\/wm\/DisplayContent.java"
+ },
"200829729": {
"message": "ScreenRotationAnimation onAnimationEnd",
"level": "DEBUG",
@@ -3055,6 +3061,12 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
+ "782864973": {
+ "message": "Releasing screen wakelock, obscured by %s",
+ "level": "DEBUG",
+ "group": "WM_DEBUG_KEEP_SCREEN_ON",
+ "at": "com\/android\/server\/wm\/DisplayContent.java"
+ },
"791468751": {
"message": "Pausing rotation during re-position",
"level": "DEBUG",
@@ -4303,18 +4315,6 @@
"group": "WM_ERROR",
"at": "com\/android\/server\/wm\/WindowManagerService.java"
},
- "2088592090": {
- "message": "handleNotObscuredLocked: %s was holding screen wakelock but no longer has FLAG_KEEP_SCREEN_ON!!! called by%s",
- "level": "DEBUG",
- "group": "WM_DEBUG_KEEP_SCREEN_ON",
- "at": "com\/android\/server\/wm\/RootWindowContainer.java"
- },
- "2096635066": {
- "message": "Acquiring screen wakelock due to %s",
- "level": "DEBUG",
- "group": "WM_DEBUG_KEEP_SCREEN_ON",
- "at": "com\/android\/server\/wm\/WindowManagerService.java"
- },
"2100457473": {
"message": "Task=%d contains embedded TaskFragment. Disabled all input during TaskFragment remote animation.",
"level": "DEBUG",
diff --git a/graphics/java/android/graphics/ColorSpace.java b/graphics/java/android/graphics/ColorSpace.java
index 582488ff8de3..ca3c84729388 100644
--- a/graphics/java/android/graphics/ColorSpace.java
+++ b/graphics/java/android/graphics/ColorSpace.java
@@ -2796,7 +2796,8 @@ public abstract class ColorSpace {
if (mWhitePoint == null || mTransform == null) {
throw new IllegalStateException(
"ColorSpace (" + this + ") cannot create native object! mWhitePoint: "
- + mWhitePoint + " mTransform: " + mTransform);
+ + Arrays.toString(mWhitePoint) + " mTransform: "
+ + Arrays.toString(mTransform));
}
// This mimics the old code that was in native.
diff --git a/ktfmt_includes.txt b/ktfmt_includes.txt
deleted file mode 100644
index c7062e093135..000000000000
--- a/ktfmt_includes.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-packages/SystemUI/compose/
-packages/SystemUI/screenshot/
-packages/SystemUI/src/com/android/systemui/people/data
-packages/SystemUI/src/com/android/systemui/people/ui
-packages/SystemUI/src/com/android/systemui/keyguard/data
-packages/SystemUI/src/com/android/systemui/keyguard/dagger
-packages/SystemUI/src/com/android/systemui/keyguard/domain
-packages/SystemUI/src/com/android/systemui/keyguard/shared
-packages/SystemUI/src/com/android/systemui/keyguard/ui
-packages/SystemUI/src/com/android/systemui/qs/footer
-packages/SystemUI/src/com/android/systemui/security
-packages/SystemUI/src/com/android/systemui/common/
-packages/SystemUI/tests/utils/src/com/android/systemui/qs/
-packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeSecurityController.kt
-packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeUserInfoController.kt
-packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/MockUserSwitcherControllerWrapper.kt
-packages/SystemUI/tests/src/com/android/systemui/qs/footer/ \ No newline at end of file
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 02af9160301c..4102732fd80e 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -792,6 +792,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
* Checks if there is a rule to split the two activities. If there is one, puts them into split
* and returns {@code true}. Otherwise, returns {@code false}.
*/
+ // Suppress GuardedBy warning because lint ask to mark this method as
+ // @GuardedBy(mPresenter.mController.mLock), which is mLock itself
+ @SuppressWarnings("GuardedBy")
@GuardedBy("mLock")
private boolean putActivitiesIntoSplitIfNecessary(@NonNull WindowContainerTransaction wct,
@NonNull Activity primaryActivity, @NonNull Activity secondaryActivity) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index 2b069d72e46f..2ef8e4c64855 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -38,6 +38,7 @@ import android.view.WindowInsets;
import android.view.WindowMetrics;
import android.window.WindowContainerTransaction;
+import androidx.annotation.GuardedBy;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -171,6 +172,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
* created and the activity will be re-parented to it.
* @param rule The split rule to be applied to the container.
*/
+ @GuardedBy("mController.mLock")
void createNewSplitContainer(@NonNull WindowContainerTransaction wct,
@NonNull Activity primaryActivity, @NonNull Activity secondaryActivity,
@NonNull SplitPairRule rule) {
@@ -187,8 +189,10 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
final TaskFragmentContainer curSecondaryContainer = mController.getContainerWithActivity(
secondaryActivity);
TaskFragmentContainer containerToAvoid = primaryContainer;
- if (rule.shouldClearTop() && curSecondaryContainer != null) {
- // Do not reuse the current TaskFragment if the rule is to clear top.
+ if (curSecondaryContainer != null
+ && (rule.shouldClearTop() || primaryContainer.isAbove(curSecondaryContainer))) {
+ // Do not reuse the current TaskFragment if the rule is to clear top, or if it is below
+ // the primary TaskFragment.
containerToAvoid = curSecondaryContainer;
}
final TaskFragmentContainer secondaryContainer = prepareContainerForActivity(wct,
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index 77e26c07f304..45645b2018c3 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -162,4 +162,8 @@ class TaskContainer {
}
return null;
}
+
+ int indexOf(@NonNull TaskFragmentContainer child) {
+ return mContainers.indexOf(child);
+ }
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
index 11c0db320646..344ffc759c46 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java
@@ -501,6 +501,18 @@ class TaskFragmentContainer {
return new Size(maxMinWidth, maxMinHeight);
}
+ /** Whether the current TaskFragment is above the {@code other} TaskFragment. */
+ boolean isAbove(@NonNull TaskFragmentContainer other) {
+ if (mTaskContainer != other.mTaskContainer) {
+ throw new IllegalArgumentException(
+ "Trying to compare two TaskFragments in different Task.");
+ }
+ if (this == other) {
+ throw new IllegalArgumentException("Trying to compare a TaskFragment with itself.");
+ }
+ return mTaskContainer.indexOf(this) > mTaskContainer.indexOf(other);
+ }
+
@Override
public String toString() {
return toString(true /* includeContainersToFinishOnExit */);
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
index da724d9d9311..25f0e25eec75 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
@@ -39,6 +39,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -247,6 +248,26 @@ public class SplitPresenterTest {
verify(mPresenter).expandTaskFragment(mTransaction, secondaryTf.getTaskFragmentToken());
}
+ @Test
+ public void testCreateNewSplitContainer_secondaryAbovePrimary() {
+ final Activity secondaryActivity = createMockActivity();
+ final TaskFragmentContainer bottomTf = mController.newContainer(secondaryActivity, TASK_ID);
+ final TaskFragmentContainer primaryTf = mController.newContainer(mActivity, TASK_ID);
+ final SplitPairRule rule = new SplitPairRule.Builder(pair ->
+ pair.first == mActivity && pair.second == secondaryActivity, pair -> false,
+ metrics -> true)
+ .setShouldClearTop(false)
+ .build();
+
+ mPresenter.createNewSplitContainer(mTransaction, mActivity, secondaryActivity, rule);
+
+ assertEquals(primaryTf, mController.getContainerWithActivity(mActivity));
+ final TaskFragmentContainer secondaryTf = mController.getContainerWithActivity(
+ secondaryActivity);
+ assertNotEquals(bottomTf, secondaryTf);
+ assertTrue(secondaryTf.isAbove(primaryTf));
+ }
+
private Activity createMockActivity() {
final Activity activity = mock(Activity.class);
final Configuration activityConfig = new Configuration();
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
index 6cbecff81be5..1bc81ee3dcc7 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskFragmentContainerTest.java
@@ -288,6 +288,18 @@ public class TaskFragmentContainerTest {
}
@Test
+ public void testIsAbove() {
+ final TaskContainer taskContainer = new TaskContainer(TASK_ID);
+ final TaskFragmentContainer container0 = new TaskFragmentContainer(null /* activity */,
+ mIntent, taskContainer, mController);
+ final TaskFragmentContainer container1 = new TaskFragmentContainer(null /* activity */,
+ mIntent, taskContainer, mController);
+
+ assertTrue(container1.isAbove(container0));
+ assertFalse(container0.isAbove(container1));
+ }
+
+ @Test
public void testGetBottomMostActivity() {
final TaskContainer taskContainer = new TaskContainer(TASK_ID);
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_letterboxed_app.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_light_bulb.xml
index 6fcd1de892a3..ddfb5c27e701 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_letterboxed_app.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_light_bulb.xml
@@ -15,15 +15,12 @@
~ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/letterbox_education_dialog_icon_size"
- android:height="@dimen/letterbox_education_dialog_icon_size"
- android:viewportWidth="48"
- android:viewportHeight="48">
+ android:width="@dimen/letterbox_education_dialog_title_icon_width"
+ android:height="@dimen/letterbox_education_dialog_title_icon_height"
+ android:viewportWidth="45"
+ android:viewportHeight="44">
+
<path
android:fillColor="@color/letterbox_education_accent_primary"
- android:fillType="evenOdd"
- android:pathData="M2 8C0.895431 8 0 8.89543 0 10V38C0 39.1046 0.895431 40 2 40H46C47.1046 40 48 39.1046 48 38V10C48 8.89543 47.1046 8 46 8H2ZM44 12H4V36H44V12Z" />
- <path
- android:fillColor="@color/letterbox_education_accent_primary"
- android:pathData="M 17 14 L 31 14 Q 32 14 32 15 L 32 33 Q 32 34 31 34 L 17 34 Q 16 34 16 33 L 16 15 Q 16 14 17 14 Z" />
+ android:pathData="M11 40H19C19 42.2 17.2 44 15 44C12.8 44 11 42.2 11 40ZM7 38L23 38V34L7 34L7 38ZM30 19C30 26.64 24.68 30.72 22.46 32L7.54 32C5.32 30.72 0 26.64 0 19C0 10.72 6.72 4 15 4C23.28 4 30 10.72 30 19ZM26 19C26 12.94 21.06 8 15 8C8.94 8 4 12.94 4 19C4 23.94 6.98 26.78 8.7 28L21.3 28C23.02 26.78 26 23.94 26 19ZM39.74 14.74L37 16L39.74 17.26L41 20L42.26 17.26L45 16L42.26 14.74L41 12L39.74 14.74ZM35 12L36.88 7.88L41 6L36.88 4.12L35 0L33.12 4.12L29 6L33.12 7.88L35 12Z" />
</vector> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml
index cbfcfd06e3b7..22a8f39ca687 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_reposition.xml
@@ -15,18 +15,16 @@
~ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/letterbox_education_dialog_icon_size"
- android:height="@dimen/letterbox_education_dialog_icon_size"
- android:viewportWidth="48"
- android:viewportHeight="48">
+ android:width="@dimen/letterbox_education_dialog_icon_width"
+ android:height="@dimen/letterbox_education_dialog_icon_height"
+ android:viewportWidth="40"
+ android:viewportHeight="32">
+
<path
android:fillColor="@color/letterbox_education_text_secondary"
android:fillType="evenOdd"
- android:pathData="M2 8C0.895431 8 0 8.89543 0 10V38C0 39.1046 0.895431 40 2 40H46C47.1046 40 48 39.1046 48 38V10C48 8.89543 47.1046 8 46 8H2ZM44 12H4V36H44V12Z" />
+ android:pathData="M4 0C1.79086 0 0 1.79086 0 4V28C0 30.2091 1.79086 32 4 32H36C38.2091 32 40 30.2091 40 28V4C40 1.79086 38.2091 0 36 0H4ZM36 4H4V28H36V4Z" />
<path
android:fillColor="@color/letterbox_education_text_secondary"
- android:pathData="M 14 22 H 30 V 26 H 14 V 22 Z" />
- <path
- android:fillColor="@color/letterbox_education_text_secondary"
- android:pathData="M26 16L34 24L26 32V16Z" />
+ android:pathData="M19.98 8L17.16 10.82L20.32 14L12 14V18H20.32L17.14 21.18L19.98 24L28 16.02L19.98 8Z" />
</vector>
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_screen_rotation.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_screen_rotation.xml
deleted file mode 100644
index 469eb1e14849..000000000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_screen_rotation.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2022 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/letterbox_education_dialog_icon_size"
- android:height="@dimen/letterbox_education_dialog_icon_size"
- android:viewportWidth="48"
- android:viewportHeight="48">
- <path
- android:fillColor="@color/letterbox_education_text_secondary"
- android:fillType="evenOdd"
- android:pathData="M22.56 2H26C37.02 2 46 10.98 46 22H42C42 14.44 36.74 8.1 29.7 6.42L31.74 10L28.26 12L22.56 2ZM22 46H25.44L19.74 36L16.26 38L18.3 41.58C11.26 39.9 6 33.56 6 26H2C2 37.02 10.98 46 22 46ZM20.46 12L36 27.52L27.54 36L12 20.48L20.46 12ZM17.64 9.18C18.42 8.4 19.44 8 20.46 8C21.5 8 22.52 8.4 23.3 9.16L38.84 24.7C40.4 26.26 40.4 28.78 38.84 30.34L30.36 38.82C29.58 39.6 28.56 40 27.54 40C26.52 40 25.5 39.6 24.72 38.82L9.18 23.28C7.62 21.72 7.62 19.2 9.18 17.64L17.64 9.18Z" />
-</vector>
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml
index dcb8aed05c9c..15e65f716b20 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_ic_split_screen.xml
@@ -15,18 +15,12 @@
~ limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="@dimen/letterbox_education_dialog_icon_size"
- android:height="@dimen/letterbox_education_dialog_icon_size"
- android:viewportWidth="48"
- android:viewportHeight="48">
+ android:width="@dimen/letterbox_education_dialog_icon_width"
+ android:height="@dimen/letterbox_education_dialog_icon_height"
+ android:viewportWidth="40"
+ android:viewportHeight="32">
+
<path
android:fillColor="@color/letterbox_education_text_secondary"
- android:fillType="evenOdd"
- android:pathData="M2 8C0.895431 8 0 8.89543 0 10V38C0 39.1046 0.895431 40 2 40H46C47.1046 40 48 39.1046 48 38V10C48 8.89543 47.1046 8 46 8H2ZM44 12H4V36H44V12Z" />
- <path
- android:fillColor="@color/letterbox_education_text_secondary"
- android:pathData="M6 16C6 14.8954 6.89543 14 8 14H21C22.1046 14 23 14.8954 23 16V32C23 33.1046 22.1046 34 21 34H8C6.89543 34 6 33.1046 6 32V16Z" />
- <path
- android:fillColor="@color/letterbox_education_text_secondary"
- android:pathData="M25 16C25 14.8954 25.8954 14 27 14H40C41.1046 14 42 14.8954 42 16V32C42 33.1046 41.1046 34 40 34H27C25.8954 34 25 33.1046 25 32V16Z" />
+ android:pathData="M40 28L40 4C40 1.8 38.2 -7.86805e-08 36 -1.74846e-07L26 -6.11959e-07C23.8 -7.08124e-07 22 1.8 22 4L22 28C22 30.2 23.8 32 26 32L36 32C38.2 32 40 30.2 40 28ZM14 28L4 28L4 4L14 4L14 28ZM18 28L18 4C18 1.8 16.2 -1.04033e-06 14 -1.1365e-06L4 -1.57361e-06C1.8 -1.66978e-06 -7.86805e-08 1.8 -1.74846e-07 4L-1.22392e-06 28C-1.32008e-06 30.2 1.8 32 4 32L14 32C16.2 32 18 30.2 18 28Z" />
</vector> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
index cd1d99ae58b0..c65f24d84e37 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
@@ -26,7 +26,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
- android:layout_marginBottom="12dp"/>
+ android:layout_marginBottom="20dp"/>
<TextView
android:id="@+id/letterbox_education_dialog_action_text"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
index 95923763d889..3a44eb9089dd 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
@@ -50,13 +50,16 @@
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
- android:padding="24dp">
+ android:paddingTop="32dp"
+ android:paddingBottom="32dp"
+ android:paddingLeft="56dp"
+ android:paddingRight="56dp">
<ImageView
- android:layout_width="@dimen/letterbox_education_dialog_icon_size"
- android:layout_height="@dimen/letterbox_education_dialog_icon_size"
- android:layout_marginBottom="12dp"
- android:src="@drawable/letterbox_education_ic_letterboxed_app"/>
+ android:layout_width="@dimen/letterbox_education_dialog_title_icon_width"
+ android:layout_height="@dimen/letterbox_education_dialog_title_icon_height"
+ android:layout_marginBottom="17dp"
+ android:src="@drawable/letterbox_education_ic_light_bulb"/>
<TextView
android:id="@+id/letterbox_education_dialog_title"
@@ -68,16 +71,6 @@
android:textColor="@color/compat_controls_text"
android:textSize="24sp"/>
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:lineSpacingExtra="4sp"
- android:text="@string/letterbox_education_dialog_subtext"
- android:textAlignment="center"
- android:textColor="@color/letterbox_education_text_secondary"
- android:textSize="14sp"/>
-
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -88,16 +81,16 @@
<com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogActionLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- app:icon="@drawable/letterbox_education_ic_screen_rotation"
- app:text="@string/letterbox_education_screen_rotation_text"/>
+ app:icon="@drawable/letterbox_education_ic_reposition"
+ app:text="@string/letterbox_education_reposition_text"/>
<com.android.wm.shell.compatui.letterboxedu.LetterboxEduDialogActionLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart=
"@dimen/letterbox_education_dialog_space_between_actions"
- app:icon="@drawable/letterbox_education_ic_reposition"
- app:text="@string/letterbox_education_reposition_text"/>
+ app:icon="@drawable/letterbox_education_ic_split_screen"
+ app:text="@string/letterbox_education_split_screen_text"/>
</LinearLayout>
@@ -105,7 +98,7 @@
android:id="@+id/letterbox_education_dialog_dismiss_button"
android:layout_width="match_parent"
android:layout_height="56dp"
- android:layout_marginTop="48dp"
+ android:layout_marginTop="40dp"
android:background=
"@drawable/letterbox_education_dismiss_button_background_ripple"
android:text="@string/letterbox_education_got_it"
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 1dac9caba01e..d2dd8d6b56a9 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -246,8 +246,17 @@
<!-- The corner radius of the letterbox education dialog. -->
<dimen name="letterbox_education_dialog_corner_radius">28dp</dimen>
- <!-- The size of an icon in the letterbox education dialog. -->
- <dimen name="letterbox_education_dialog_icon_size">48dp</dimen>
+ <!-- The width of the top icon in the letterbox education dialog. -->
+ <dimen name="letterbox_education_dialog_title_icon_width">45dp</dimen>
+
+ <!-- The height of the top icon in the letterbox education dialog. -->
+ <dimen name="letterbox_education_dialog_title_icon_height">44dp</dimen>
+
+ <!-- The width of an icon in the letterbox education dialog. -->
+ <dimen name="letterbox_education_dialog_icon_width">40dp</dimen>
+
+ <!-- The height of an icon in the letterbox education dialog. -->
+ <dimen name="letterbox_education_dialog_icon_height">32dp</dimen>
<!-- The fixed width of the dialog if there is enough space in the parent. -->
<dimen name="letterbox_education_dialog_width">472dp</dimen>
diff --git a/libs/WindowManager/Shell/res/values/strings.xml b/libs/WindowManager/Shell/res/values/strings.xml
index 679bfb9d5187..b48a508fddb8 100644
--- a/libs/WindowManager/Shell/res/values/strings.xml
+++ b/libs/WindowManager/Shell/res/values/strings.xml
@@ -177,16 +177,13 @@
<string name="camera_compat_dismiss_button_description">No camera issues? Tap to dismiss.</string>
<!-- The title of the letterbox education dialog. [CHAR LIMIT=NONE] -->
- <string name="letterbox_education_dialog_title">Some apps work best in portrait</string>
+ <string name="letterbox_education_dialog_title">See and do more</string>
- <!-- The subtext of the letterbox education dialog. [CHAR LIMIT=NONE] -->
- <string name="letterbox_education_dialog_subtext">Try one of these options to make the most of your space</string>
-
- <!-- Description of the rotate screen action. [CHAR LIMIT=NONE] -->
- <string name="letterbox_education_screen_rotation_text">Rotate your device to go full screen</string>
+ <!-- Description of the split screen action. [CHAR LIMIT=NONE] -->
+ <string name="letterbox_education_split_screen_text">Drag in another app for split-screen</string>
<!-- Description of the reposition app action. [CHAR LIMIT=NONE] -->
- <string name="letterbox_education_reposition_text">Double-tap next to an app to reposition it</string>
+ <string name="letterbox_education_reposition_text">Double-tap outside an app to reposition it</string>
<!-- Button text for dismissing the letterbox education dialog. [CHAR LIMIT=20] -->
<string name="letterbox_education_got_it">Got it</string>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index b7959eb629c1..4c85d2090ec5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -80,7 +80,10 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
public static final int PARALLAX_DISMISSING = 1;
public static final int PARALLAX_ALIGN_CENTER = 2;
- private static final int FLING_ANIMATION_DURATION = 250;
+ private static final int FLING_RESIZE_DURATION = 250;
+ private static final int FLING_SWITCH_DURATION = 350;
+ private static final int FLING_ENTER_DURATION = 350;
+ private static final int FLING_EXIT_DURATION = 350;
private final int mDividerWindowWidth;
private final int mDividerInsets;
@@ -93,6 +96,9 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
private final Rect mBounds1 = new Rect();
// Bounds2 final position should be always at bottom or right
private final Rect mBounds2 = new Rect();
+ // The temp bounds outside of display bounds for side stage when split screen inactive to avoid
+ // flicker next time active split screen.
+ private final Rect mInvisibleBounds = new Rect();
private final Rect mWinBounds1 = new Rect();
private final Rect mWinBounds2 = new Rect();
private final SplitLayoutHandler mSplitLayoutHandler;
@@ -141,6 +147,8 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
resetDividerPosition();
mDimNonImeSide = resources.getBoolean(R.bool.config_dimNonImeAttachedSide);
+
+ updateInvisibleRect();
}
private int getDividerInsets(Resources resources, Display display) {
@@ -239,6 +247,12 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
rect.offset(-mRootBounds.left, -mRootBounds.top);
}
+ /** Gets bounds size equal to root bounds but outside of screen, used for position side stage
+ * when split inactive to avoid flicker when next time active. */
+ public void getInvisibleBounds(Rect rect) {
+ rect.set(mInvisibleBounds);
+ }
+
/** Returns leash of the current divider bar. */
@Nullable
public SurfaceControl getDividerLeash() {
@@ -258,6 +272,14 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
: (float) ((mBounds1.bottom + mBounds2.top) / 2f) / mBounds2.bottom));
}
+ private void updateInvisibleRect() {
+ mInvisibleBounds.set(mRootBounds.left, mRootBounds.top,
+ isLandscape() ? mRootBounds.right / 2 : mRootBounds.right,
+ isLandscape() ? mRootBounds.bottom : mRootBounds.bottom / 2);
+ mInvisibleBounds.offset(isLandscape() ? mRootBounds.right : 0,
+ isLandscape() ? 0 : mRootBounds.bottom);
+ }
+
/** Applies new configuration, returns {@code false} if there's no effect to the layout. */
public boolean updateConfiguration(Configuration configuration) {
// Update the split bounds when necessary. Besides root bounds changed, split bounds need to
@@ -283,6 +305,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
mRotation = rotation;
mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds, null);
initDividerPosition(mTempRect);
+ updateInvisibleRect();
return true;
}
@@ -405,6 +428,13 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
mFreezeDividerWindow = freezeDividerWindow;
}
+ /** Update current layout as divider put on start or end position. */
+ public void setDividerAtBorder(boolean start) {
+ final int pos = start ? mDividerSnapAlgorithm.getDismissStartTarget().position
+ : mDividerSnapAlgorithm.getDismissEndTarget().position;
+ setDividePosition(pos, false /* applyLayoutChange */);
+ }
+
/**
* Updates bounds with the passing position. Usually used to update recording bounds while
* performing animation or dragging divider bar to resize the splits.
@@ -449,17 +479,17 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
public void snapToTarget(int currentPosition, DividerSnapAlgorithm.SnapTarget snapTarget) {
switch (snapTarget.flag) {
case FLAG_DISMISS_START:
- flingDividePosition(currentPosition, snapTarget.position,
+ flingDividePosition(currentPosition, snapTarget.position, FLING_RESIZE_DURATION,
() -> mSplitLayoutHandler.onSnappedToDismiss(false /* bottomOrRight */,
EXIT_REASON_DRAG_DIVIDER));
break;
case FLAG_DISMISS_END:
- flingDividePosition(currentPosition, snapTarget.position,
+ flingDividePosition(currentPosition, snapTarget.position, FLING_RESIZE_DURATION,
() -> mSplitLayoutHandler.onSnappedToDismiss(true /* bottomOrRight */,
EXIT_REASON_DRAG_DIVIDER));
break;
default:
- flingDividePosition(currentPosition, snapTarget.position,
+ flingDividePosition(currentPosition, snapTarget.position, FLING_RESIZE_DURATION,
() -> setDividePosition(snapTarget.position, true /* applyLayoutChange */));
break;
}
@@ -514,12 +544,20 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
public void flingDividerToDismiss(boolean toEnd, int reason) {
final int target = toEnd ? mDividerSnapAlgorithm.getDismissEndTarget().position
: mDividerSnapAlgorithm.getDismissStartTarget().position;
- flingDividePosition(getDividePosition(), target,
+ flingDividePosition(getDividePosition(), target, FLING_EXIT_DURATION,
() -> mSplitLayoutHandler.onSnappedToDismiss(toEnd, reason));
}
+ /** Fling divider from current position to center position. */
+ public void flingDividerToCenter() {
+ final int pos = mDividerSnapAlgorithm.getMiddleTarget().position;
+ flingDividePosition(getDividePosition(), pos, FLING_ENTER_DURATION,
+ () -> setDividePosition(pos, true /* applyLayoutChange */));
+ }
+
@VisibleForTesting
- void flingDividePosition(int from, int to, @Nullable Runnable flingFinishedCallback) {
+ void flingDividePosition(int from, int to, int duration,
+ @Nullable Runnable flingFinishedCallback) {
if (from == to) {
// No animation run, still callback to stop resizing.
mSplitLayoutHandler.onLayoutSizeChanged(this);
@@ -529,7 +567,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
}
ValueAnimator animator = ValueAnimator
.ofInt(from, to)
- .setDuration(FLING_ANIMATION_DURATION);
+ .setDuration(duration);
animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
animator.addUpdateListener(
animation -> updateDivideBounds((int) animation.getAnimatedValue()));
@@ -586,7 +624,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange
AnimatorSet set = new AnimatorSet();
set.playTogether(animator1, animator2, animator3);
- set.setDuration(FLING_ANIMATION_DURATION);
+ set.setDuration(FLING_SWITCH_DURATION);
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
index dd50fa0817c2..fd4c85fad77f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
@@ -92,6 +92,12 @@ public class FreeformTaskTransitionHandler
@Override
+ public void startRemoveTransition(WindowContainerTransaction wct) {
+ final int type = WindowManager.TRANSIT_CLOSE;
+ mPendingTransitionTokens.add(mTransitions.startTransition(type, wct, this));
+ }
+
+ @Override
public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startT,
@NonNull SurfaceControl.Transaction finishT,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java
index c947cf1b8cd1..8da4c6ab4b36 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java
@@ -40,4 +40,12 @@ public interface FreeformTaskTransitionStarter {
*
*/
void startMinimizedModeTransition(WindowContainerTransaction wct);
+
+ /**
+ * Starts close window transition
+ *
+ * @param wct the {@link WindowContainerTransaction} that closes the task
+ *
+ */
+ void startRemoveTransition(WindowContainerTransaction wct);
} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
index f1465f421c5b..e9f9bb5d7327 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java
@@ -287,6 +287,9 @@ public class FullscreenTaskListener<T extends AutoCloseable>
}
private void releaseWindowDecor(T windowDecor) {
+ if (windowDecor == null) {
+ return;
+ }
try {
windowDecor.close();
} catch (Exception e) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 7e83d2fa0a0b..c08aa5a6f208 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -25,6 +25,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
+import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
@@ -488,13 +489,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final WindowContainerTransaction wct = new WindowContainerTransaction();
options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, wct);
- // If split still not active, apply windows bounds first to avoid surface reset to
- // wrong pos by SurfaceAnimator from wms.
- // TODO(b/223325631): check is it still necessary after improve enter transition done.
- if (!mMainStage.isActive()) {
- updateWindowBounds(mSplitLayout, wct);
- }
-
wct.sendPendingIntent(intent, fillInIntent, options);
mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
}
@@ -519,6 +513,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSplitLayout.setDivideRatio(splitRatio);
updateWindowBounds(mSplitLayout, wct);
wct.reorder(mRootTaskInfo.token, true);
+ wct.setForceTranslucent(mRootTaskInfo.token, false);
// Make sure the launch options will put tasks in the corresponding split roots
addActivityOptions(mainOptions, mMainStage);
@@ -628,6 +623,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
updateWindowBounds(mSplitLayout, wct);
wct.reorder(mRootTaskInfo.token, true);
+ wct.setForceTranslucent(mRootTaskInfo.token, false);
// Make sure the launch options will put tasks in the corresponding split roots
addActivityOptions(mainOptions, mMainStage);
@@ -640,8 +636,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
} else {
wct.startTask(sideTaskId, sideOptions);
}
- // Using legacy transitions, so we can't use blast sync since it conflicts.
- mTaskOrganizer.applyTransaction(wct);
+
+ mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> {
setDividerVisibility(true, t);
updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
@@ -893,10 +889,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mShouldUpdateRecents = false;
mIsDividerRemoteAnimating = false;
+ mSplitLayout.getInvisibleBounds(mTempRect1);
if (childrenToTop == null) {
mSideStage.removeAllTasks(wct, false /* toTop */);
mMainStage.deactivate(wct, false /* toTop */);
wct.reorder(mRootTaskInfo.token, false /* onTop */);
+ wct.setForceTranslucent(mRootTaskInfo.token, true);
+ wct.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
onTransitionAnimationComplete();
} else {
// Expand to top side split as full screen for fading out decor animation and dismiss
@@ -907,27 +906,32 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
? mSideStage : mMainStage;
tempFullStage.resetBounds(wct);
wct.setSmallestScreenWidthDp(tempFullStage.mRootTaskInfo.token,
- mRootTaskInfo.configuration.smallestScreenWidthDp);
+ SMALLEST_SCREEN_WIDTH_DP_UNDEFINED);
dismissStage.dismiss(wct, false /* toTop */);
}
mSyncQueue.queue(wct);
mSyncQueue.runInSync(t -> {
t.setWindowCrop(mMainStage.mRootLeash, null)
.setWindowCrop(mSideStage.mRootLeash, null);
- t.setPosition(mMainStage.mRootLeash, 0, 0)
- .setPosition(mSideStage.mRootLeash, 0, 0);
t.hide(mMainStage.mDimLayer).hide(mSideStage.mDimLayer);
setDividerVisibility(false, t);
- // In this case, exit still under progress, fade out the split decor after first WCT
- // done and do remaining WCT after animation finished.
- if (childrenToTop != null) {
+ if (childrenToTop == null) {
+ t.setPosition(mSideStage.mRootLeash, mTempRect1.left, mTempRect1.right);
+ } else {
+ // In this case, exit still under progress, fade out the split decor after first WCT
+ // done and do remaining WCT after animation finished.
childrenToTop.fadeOutDecor(() -> {
WindowContainerTransaction finishedWCT = new WindowContainerTransaction();
mIsExiting = false;
childrenToTop.dismiss(finishedWCT, true /* toTop */);
finishedWCT.reorder(mRootTaskInfo.token, false /* toTop */);
- mTaskOrganizer.applyTransaction(finishedWCT);
+ finishedWCT.setForceTranslucent(mRootTaskInfo.token, true);
+ finishedWCT.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
+ mSyncQueue.queue(finishedWCT);
+ mSyncQueue.runInSync(at -> {
+ at.setPosition(mSideStage.mRootLeash, mTempRect1.left, mTempRect1.right);
+ });
onTransitionAnimationComplete();
});
}
@@ -996,6 +1000,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mMainStage.activate(wct, true /* includingTopTask */);
updateWindowBounds(mSplitLayout, wct);
wct.reorder(mRootTaskInfo.token, true);
+ wct.setForceTranslucent(mRootTaskInfo.token, false);
}
void finishEnterSplitScreen(SurfaceControl.Transaction t) {
@@ -1221,7 +1226,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// Make the stages adjacent to each other so they occlude what's behind them.
wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token);
wct.setLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token);
- mTaskOrganizer.applyTransaction(wct);
+ wct.setForceTranslucent(mRootTaskInfo.token, true);
+ mSplitLayout.getInvisibleBounds(mTempRect1);
+ wct.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
+ mSyncQueue.queue(wct);
+ mSyncQueue.runInSync(t -> {
+ t.setPosition(mSideStage.mRootLeash, mTempRect1.left, mTempRect1.top);
+ });
}
private void onRootTaskVanished() {
@@ -1377,10 +1388,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// TODO (b/238697912) : Add the validation to prevent entering non-recovered status
final WindowContainerTransaction wct = new WindowContainerTransaction();
mSplitLayout.init();
- prepareEnterSplitScreen(wct);
+ mSplitLayout.setDividerAtBorder(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT);
+ mMainStage.activate(wct, true /* includingTopTask */);
+ updateWindowBounds(mSplitLayout, wct);
+ wct.reorder(mRootTaskInfo.token, true);
+ wct.setForceTranslucent(mRootTaskInfo.token, false);
mSyncQueue.queue(wct);
- mSyncQueue.runInSync(t ->
- updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */));
+ mSyncQueue.runInSync(t -> {
+ mSplitLayout.flingDividerToCenter();
+ });
}
if (mMainStageListener.mHasChildren && mSideStageListener.mHasChildren) {
mShouldUpdateRecents = true;
@@ -1822,6 +1838,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// properly for the animation itself.
mSplitLayout.release();
mSplitLayout.resetDividerPosition();
+ mSideStagePosition = SPLIT_POSITION_BOTTOM_OR_RIGHT;
mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
index ad539568e3eb..83aa539d24d6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java
@@ -148,7 +148,13 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
public void onClick(View v) {
final int id = v.getId();
if (id == R.id.close_window) {
- mActivityTaskManager.removeTask(mTaskId);
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.removeTask(mTaskToken);
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+ mTransitionStarter.startRemoveTransition(wct);
+ } else {
+ mSyncQueue.queue(wct);
+ }
} else if (id == R.id.maximize_window) {
WindowContainerTransaction wct = new WindowContainerTransaction();
RunningTaskInfo taskInfo = mTaskOrganizer.getRunningTaskInfo(mTaskId);
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index cb74315732ab..cc987dc7986c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -151,15 +151,15 @@ fun FlickerTestParameter.splitAppLayerBoundsChanges(
assertLayers {
if (landscapePosLeft) {
this.splitAppLayerBoundsSnapToDivider(
- component, landscapePosLeft, portraitPosTop, endRotation)
+ component, landscapePosLeft, portraitPosTop, endRotation)
+ } else {
+ this.splitAppLayerBoundsSnapToDivider(
+ component, landscapePosLeft, portraitPosTop, endRotation)
.then()
.isInvisible(component)
.then()
.splitAppLayerBoundsSnapToDivider(
component, landscapePosLeft, portraitPosTop, endRotation)
- } else {
- this.splitAppLayerBoundsSnapToDivider(
- component, landscapePosLeft, portraitPosTop, endRotation)
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt
index 293eb7cd5581..47557bcead2f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt
@@ -18,7 +18,6 @@ package com.android.wm.shell.flicker.bubble
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Postsubmit
-import android.platform.test.annotations.Presubmit
import android.view.WindowInsets
import android.view.WindowManager
import androidx.test.filters.RequiresDevice
@@ -92,7 +91,7 @@ class LaunchBubbleFromLockScreen(testSpec: FlickerTestParameter) : BaseBubbleScr
}
}
- @Presubmit
+ @FlakyTest(bugId = 242088970)
@Test
fun testAppIsVisibleAtEnd() {
testSpec.assertLayersEnd {
@@ -125,7 +124,7 @@ class LaunchBubbleFromLockScreen(testSpec: FlickerTestParameter) : BaseBubbleScr
super.navBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @FlakyTest(bugId = 242088970)
@Test
override fun taskBarLayerIsVisibleAtStartAndEnd() =
super.taskBarLayerIsVisibleAtStartAndEnd()
@@ -135,4 +134,28 @@ class LaunchBubbleFromLockScreen(testSpec: FlickerTestParameter) : BaseBubbleScr
@Test
override fun taskBarWindowIsAlwaysVisible() =
super.taskBarWindowIsAlwaysVisible()
+
+ /** {@inheritDoc} */
+ @FlakyTest(bugId = 242088970)
+ @Test
+ override fun statusBarLayerIsVisibleAtStartAndEnd() =
+ super.statusBarLayerIsVisibleAtStartAndEnd()
+
+ /** {@inheritDoc} */
+ @FlakyTest(bugId = 242088970)
+ @Test
+ override fun statusBarLayerPositionAtStartAndEnd() =
+ super.statusBarLayerPositionAtStartAndEnd()
+
+ /** {@inheritDoc} */
+ @FlakyTest(bugId = 242088970)
+ @Test
+ override fun statusBarWindowIsAlwaysVisible() =
+ super.statusBarWindowIsAlwaysVisible()
+
+ /** {@inheritDoc} */
+ @FlakyTest(bugId = 242088970)
+ @Test
+ override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
+ super.visibleWindowsShownMoreThanOneConsecutiveEntry()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/LaunchBubbleHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/LaunchBubbleHelper.kt
index 6695c17ed514..1b8a44bbe78e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/LaunchBubbleHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/LaunchBubbleHelper.kt
@@ -27,7 +27,6 @@ class LaunchBubbleHelper(instrumentation: Instrumentation) : BaseAppHelper(
) {
companion object {
- const val TEST_REPETITIONS = 1
const val TIMEOUT_MS = 3_000L
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
index e7f9d9a9d73d..52e5d7e14ab9 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
@@ -42,7 +42,6 @@ class SplitScreenHelper(
) : BaseAppHelper(instrumentation, activityLabel, componentInfo) {
companion object {
- const val TEST_REPETITIONS = 1
const val TIMEOUT_MS = 3_000L
const val DRAG_DURATION_MS = 1_000L
const val NOTIFICATION_SCROLLER = "notification_stack_scroller"
@@ -98,13 +97,29 @@ class SplitScreenHelper(
secondaryApp: IComponentMatcher,
) {
wmHelper.StateSyncBuilder()
- .withAppTransitionIdle()
.withWindowSurfaceAppeared(primaryApp)
.withWindowSurfaceAppeared(secondaryApp)
.withSplitDividerVisible()
.waitForAndVerify()
}
+ fun enterSplit(
+ wmHelper: WindowManagerStateHelper,
+ tapl: LauncherInstrumentation,
+ primaryApp: SplitScreenHelper,
+ secondaryApp: SplitScreenHelper
+ ) {
+ tapl.workspace.switchToOverview().dismissAllTasks()
+ primaryApp.launchViaIntent(wmHelper)
+ secondaryApp.launchViaIntent(wmHelper)
+ tapl.goHome()
+ wmHelper.StateSyncBuilder()
+ .withHomeActivityVisible()
+ .waitForAndVerify()
+ splitFromOverview(tapl)
+ waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
+ }
+
fun splitFromOverview(tapl: LauncherInstrumentation) {
// Note: The initial split position in landscape is different between tablet and phone.
// In landscape, tablet will let the first app split to right side, and phone will
@@ -268,24 +283,35 @@ class SplitScreenHelper(
?.layerStackSpace
?: error("Display not found")
val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
- dividerBar.drag(Point(displayBounds.width * 2 / 3, displayBounds.height * 2 / 3))
+ dividerBar.drag(Point(displayBounds.width * 1 / 3, displayBounds.height * 2 / 3))
wmHelper.StateSyncBuilder()
- .withAppTransitionIdle()
.withWindowSurfaceDisappeared(SPLIT_DECOR_MANAGER)
.waitForAndVerify()
}
fun dragDividerToDismissSplit(
device: UiDevice,
- wmHelper: WindowManagerStateHelper
+ wmHelper: WindowManagerStateHelper,
+ dragToRight: Boolean,
+ dragToBottom: Boolean
) {
val displayBounds = wmHelper.currentState.layerState
.displays.firstOrNull { !it.isVirtual }
?.layerStackSpace
?: error("Display not found")
val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
- dividerBar.drag(Point(displayBounds.width * 4 / 5, displayBounds.height * 4 / 5))
+ dividerBar.drag(Point(
+ if (dragToRight) {
+ displayBounds.width * 4 / 5
+ } else {
+ displayBounds.width * 1 / 5
+ },
+ if (dragToBottom) {
+ displayBounds.height * 4 / 5
+ } else {
+ displayBounds.height * 1 / 5
+ }))
}
fun doubleTapDividerToSwitch(device: UiDevice) {
@@ -297,7 +323,7 @@ class SplitScreenHelper(
dividerBar.click()
}
- fun copyContentFromLeftToRight(
+ fun copyContentInSplit(
instrumentation: Instrumentation,
device: UiDevice,
sourceApp: IComponentNameMatcher,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
index 6cbb685850fa..102a78ba16ab 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
@@ -30,8 +30,6 @@ import com.android.wm.shell.flicker.appWindowKeepVisible
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerKeepVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsKeepVisible
-import org.junit.Assume
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -49,30 +47,18 @@ import org.junit.runners.Parameterized
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Group1
class CopyContentInSplit(testSpec: FlickerTestParameter) : SplitScreenBase(testSpec) {
- protected val textEditApp = SplitScreenHelper.getIme(instrumentation)
-
- // TODO(b/231399940): Remove this once we can use recent shortcut to enter split.
- @Before
- open fun before() {
- Assume.assumeTrue(tapl.isTablet)
- }
+ private val textEditApp = SplitScreenHelper.getIme(instrumentation)
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
setup {
eachRun {
- textEditApp.launchViaIntent(wmHelper)
- // TODO(b/231399940): Use recent shortcut to enter split.
- tapl.launchedAppState.taskbar
- .openAllApps()
- .getAppIcon(primaryApp.appName)
- .dragToSplitscreen(primaryApp.`package`, textEditApp.`package`)
- SplitScreenHelper.waitForSplitComplete(wmHelper, textEditApp, primaryApp)
+ SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, textEditApp)
}
}
transitions {
- SplitScreenHelper.copyContentFromLeftToRight(
+ SplitScreenHelper.copyContentInSplit(
instrumentation, device, primaryApp, textEditApp)
}
}
@@ -92,12 +78,12 @@ class CopyContentInSplit(testSpec: FlickerTestParameter) : SplitScreenBase(testS
@Presubmit
@Test
fun primaryAppBoundsKeepVisible() = testSpec.splitAppLayerBoundsKeepVisible(
- primaryApp, landscapePosLeft = true, portraitPosTop = true)
+ primaryApp, landscapePosLeft = tapl.isTablet, portraitPosTop = false)
@Presubmit
@Test
fun textEditAppBoundsKeepVisible() = testSpec.splitAppLayerBoundsKeepVisible(
- textEditApp, landscapePosLeft = false, portraitPosTop = false)
+ textEditApp, landscapePosLeft = !tapl.isTablet, portraitPosTop = true)
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt
index 581826ef889f..bf91292811e8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByDivider.kt
@@ -26,6 +26,7 @@ import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.wm.shell.flicker.SPLIT_SCREEN_DIVIDER_COMPONENT
import com.android.wm.shell.flicker.appWindowBecomesInvisible
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
@@ -33,14 +34,11 @@ import com.android.wm.shell.flicker.layerBecomesInvisible
import com.android.wm.shell.flicker.layerIsVisibleAtEnd
import com.android.wm.shell.flicker.splitAppLayerBoundsBecomesInvisible
import com.android.wm.shell.flicker.splitScreenDividerBecomesInvisible
-import org.junit.Assume
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
-
/**
* Test dismiss split screen by dragging the divider bar.
*
@@ -53,31 +51,23 @@ import org.junit.runners.Parameterized
@Group1
class DismissSplitScreenByDivider (testSpec: FlickerTestParameter) : SplitScreenBase(testSpec) {
- // TODO(b/231399940): Remove this once we can use recent shortcut to enter split.
- @Before
- open fun before() {
- Assume.assumeTrue(tapl.isTablet)
- }
-
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
setup {
eachRun {
- tapl.goHome()
- primaryApp.launchViaIntent(wmHelper)
- // TODO(b/231399940): Use recent shortcut to enter split.
- tapl.launchedAppState.taskbar
- .openAllApps()
- .getAppIcon(secondaryApp.appName)
- .dragToSplitscreen(secondaryApp.`package`, primaryApp.`package`)
- SplitScreenHelper.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
+ SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
}
}
transitions {
- SplitScreenHelper.dragDividerToDismissSplit(device, wmHelper)
+ if (tapl.isTablet) {
+ SplitScreenHelper.dragDividerToDismissSplit(device, wmHelper,
+ dragToRight = false, dragToBottom = true)
+ } else {
+ SplitScreenHelper.dragDividerToDismissSplit(device, wmHelper,
+ dragToRight = true, dragToBottom = true)
+ }
wmHelper.StateSyncBuilder()
- .withAppTransitionIdle()
.withFullScreenApp(secondaryApp)
.waitForAndVerify()
}
@@ -98,17 +88,23 @@ class DismissSplitScreenByDivider (testSpec: FlickerTestParameter) : SplitScreen
@Presubmit
@Test
fun primaryAppBoundsBecomesInvisible() = testSpec.splitAppLayerBoundsBecomesInvisible(
- primaryApp, landscapePosLeft = false, portraitPosTop = false)
+ primaryApp, landscapePosLeft = tapl.isTablet, portraitPosTop = false)
@Presubmit
@Test
fun secondaryAppBoundsIsFullscreenAtEnd() {
testSpec.assertLayers {
this.isVisible(secondaryApp)
+ .isVisible(SPLIT_SCREEN_DIVIDER_COMPONENT)
.then()
.isInvisible(secondaryApp)
+ .isVisible(SPLIT_SCREEN_DIVIDER_COMPONENT)
+ .then()
+ .isVisible(secondaryApp, isOptional = true)
+ .isVisible(SPLIT_SCREEN_DIVIDER_COMPONENT, isOptional = true)
+ .then()
+ .contains(SPLIT_SCREEN_DIVIDER_COMPONENT)
.then()
- .isVisible(secondaryApp)
.invoke("secondaryAppBoundsIsFullscreenAtEnd") {
val displayBounds = WindowUtils.getDisplayBounds(testSpec.endRotation)
it.visibleRegion(secondaryApp).coversExactly(displayBounds)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt
index 5c051e859d59..20a7423be681 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt
@@ -30,8 +30,6 @@ import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerBecomesInvisible
import com.android.wm.shell.flicker.splitAppLayerBoundsBecomesInvisible
import com.android.wm.shell.flicker.splitScreenDividerBecomesInvisible
-import org.junit.Assume
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -52,30 +50,17 @@ class DismissSplitScreenByGoHome(
testSpec: FlickerTestParameter
) : SplitScreenBase(testSpec) {
- // TODO(b/231399940): Remove this once we can use recent shortcut to enter split.
- @Before
- open fun before() {
- Assume.assumeTrue(tapl.isTablet)
- }
-
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
setup {
eachRun {
- primaryApp.launchViaIntent(wmHelper)
- // TODO(b/231399940): Use recent shortcut to enter split.
- tapl.launchedAppState.taskbar
- .openAllApps()
- .getAppIcon(secondaryApp.appName)
- .dragToSplitscreen(secondaryApp.`package`, primaryApp.`package`)
- SplitScreenHelper.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
+ SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
}
}
transitions {
tapl.goHome()
wmHelper.StateSyncBuilder()
- .withAppTransitionIdle()
.withHomeActivityVisible()
.waitForAndVerify()
}
@@ -96,12 +81,12 @@ class DismissSplitScreenByGoHome(
@Presubmit
@Test
fun primaryAppBoundsBecomesInvisible() = testSpec.splitAppLayerBoundsBecomesInvisible(
- primaryApp, landscapePosLeft = false, portraitPosTop = false)
+ primaryApp, landscapePosLeft = tapl.isTablet, portraitPosTop = false)
@Presubmit
@Test
fun secondaryAppBoundsBecomesInvisible() = testSpec.splitAppLayerBoundsBecomesInvisible(
- secondaryApp, landscapePosLeft = true, portraitPosTop = true)
+ secondaryApp, landscapePosLeft = !tapl.isTablet, portraitPosTop = true)
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt
index 9ca9ab01fd7b..8f7673b77429 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DragDividerToResize.kt
@@ -31,8 +31,6 @@ import com.android.wm.shell.flicker.appWindowKeepVisible
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerKeepVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsChanges
-import org.junit.Assume
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -51,25 +49,12 @@ import org.junit.runners.Parameterized
@Group1
class DragDividerToResize (testSpec: FlickerTestParameter) : SplitScreenBase(testSpec) {
- // TODO(b/231399940): Remove this once we can use recent shortcut to enter split.
- @Before
- open fun before() {
- Assume.assumeTrue(tapl.isTablet)
- }
-
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
setup {
eachRun {
- tapl.goHome()
- primaryApp.launchViaIntent(wmHelper)
- // TODO(b/231399940): Use recent shortcut to enter split.
- tapl.launchedAppState.taskbar
- .openAllApps()
- .getAppIcon(secondaryApp.appName)
- .dragToSplitscreen(secondaryApp.`package`, primaryApp.`package`)
- SplitScreenHelper.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
+ SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
}
}
transitions {
@@ -108,12 +93,12 @@ class DragDividerToResize (testSpec: FlickerTestParameter) : SplitScreenBase(tes
@Presubmit
@Test
fun primaryAppBoundsChanges() = testSpec.splitAppLayerBoundsChanges(
- primaryApp, landscapePosLeft = false, portraitPosTop = false)
+ primaryApp, landscapePosLeft = true, portraitPosTop = false)
@Presubmit
@Test
fun secondaryAppBoundsChanges() = testSpec.splitAppLayerBoundsChanges(
- secondaryApp, landscapePosLeft = true, portraitPosTop = true)
+ secondaryApp, landscapePosLeft = false, portraitPosTop = true)
/** {@inheritDoc} */
@Postsubmit
@@ -189,7 +174,7 @@ class DragDividerToResize (testSpec: FlickerTestParameter) : SplitScreenBase(tes
supportedRotations = listOf(Surface.ROTATION_0),
// TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
supportedNavigationModes =
- listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY))
+ listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY))
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt
index 8cb5d7c24ced..7ce23c5f9a4e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt
@@ -170,8 +170,7 @@ class EnterSplitScreenFromOverview(testSpec: FlickerTestParameter) : SplitScreen
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
- repetitions = SplitScreenHelper.TEST_REPETITIONS)
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
index 525e09a19d2f..58f7b048bc70 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchAppByDoubleTapDivider.kt
@@ -31,8 +31,6 @@ import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerIsVisibleAtEnd
import com.android.wm.shell.flicker.layerKeepVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
-import org.junit.Assume
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -51,24 +49,12 @@ import org.junit.runners.Parameterized
@Group1
class SwitchAppByDoubleTapDivider (testSpec: FlickerTestParameter) : SplitScreenBase(testSpec) {
- // TODO(b/231399940): Remove this once we can use recent shortcut to enter split.
- @Before
- open fun before() {
- Assume.assumeTrue(tapl.isTablet)
- }
-
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
setup {
eachRun {
- primaryApp.launchViaIntent(wmHelper)
- // TODO(b/231399940): Use recent shortcut to enter split.
- tapl.launchedAppState.taskbar
- .openAllApps()
- .getAppIcon(secondaryApp.appName)
- .dragToSplitscreen(secondaryApp.`package`, primaryApp.`package`)
- SplitScreenHelper.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
+ SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
}
}
transitions {
@@ -94,12 +80,12 @@ class SwitchAppByDoubleTapDivider (testSpec: FlickerTestParameter) : SplitScreen
@Presubmit
@Test
fun primaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
- primaryApp, landscapePosLeft = true, portraitPosTop = true)
+ primaryApp, landscapePosLeft = !tapl.isTablet, portraitPosTop = true)
@Presubmit
@Test
fun secondaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
- secondaryApp, landscapePosLeft = false, portraitPosTop = false)
+ secondaryApp, landscapePosLeft = tapl.isTablet, portraitPosTop = false)
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt
index c030603a6b55..0dd6706fb00e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt
@@ -30,8 +30,6 @@ import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.splitScreenDividerBecomesVisible
-import org.junit.Assume
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -51,28 +49,15 @@ import org.junit.runners.Parameterized
class SwitchBackToSplitFromAnotherApp(testSpec: FlickerTestParameter) : SplitScreenBase(testSpec) {
val thirdApp = SplitScreenHelper.getNonResizeable(instrumentation)
- // TODO(b/231399940): Remove this once we can use recent shortcut to enter split.
- @Before
- open fun before() {
- Assume.assumeTrue(tapl.isTablet)
- }
-
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
setup {
eachRun {
- primaryApp.launchViaIntent(wmHelper)
- // TODO(b/231399940): Use recent shortcut to enter split.
- tapl.launchedAppState.taskbar
- .openAllApps()
- .getAppIcon(secondaryApp.appName)
- .dragToSplitscreen(secondaryApp.`package`, primaryApp.`package`)
- SplitScreenHelper.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
+ SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
thirdApp.launchViaIntent(wmHelper)
wmHelper.StateSyncBuilder()
- .withAppTransitionIdle()
.withWindowSurfaceAppeared(thirdApp)
.waitForAndVerify()
}
@@ -98,12 +83,12 @@ class SwitchBackToSplitFromAnotherApp(testSpec: FlickerTestParameter) : SplitScr
@Presubmit
@Test
fun primaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
- primaryApp, landscapePosLeft = false, portraitPosTop = false)
+ primaryApp, landscapePosLeft = tapl.isTablet, portraitPosTop = false)
@Presubmit
@Test
fun secondaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
- secondaryApp, landscapePosLeft = true, portraitPosTop = true)
+ secondaryApp, landscapePosLeft = !tapl.isTablet, portraitPosTop = true)
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt
index b8565f3e89b2..dc8ba0caa4e4 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt
@@ -30,8 +30,6 @@ import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.splitScreenDividerBecomesVisible
-import org.junit.Assume
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -50,28 +48,15 @@ import org.junit.runners.Parameterized
@Group1
class SwitchBackToSplitFromHome(testSpec: FlickerTestParameter) : SplitScreenBase(testSpec) {
- // TODO(b/231399940): Remove this once we can use recent shortcut to enter split.
- @Before
- open fun before() {
- Assume.assumeTrue(tapl.isTablet)
- }
-
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
setup {
eachRun {
- primaryApp.launchViaIntent(wmHelper)
- // TODO(b/231399940): Use recent shortcut to enter split.
- tapl.launchedAppState.taskbar
- .openAllApps()
- .getAppIcon(secondaryApp.appName)
- .dragToSplitscreen(secondaryApp.`package`, primaryApp.`package`)
- SplitScreenHelper.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
+ SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
tapl.goHome()
wmHelper.StateSyncBuilder()
- .withAppTransitionIdle()
.withHomeActivityVisible()
.waitForAndVerify()
}
@@ -97,12 +82,12 @@ class SwitchBackToSplitFromHome(testSpec: FlickerTestParameter) : SplitScreenBas
@Presubmit
@Test
fun primaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
- primaryApp, landscapePosLeft = false, portraitPosTop = false)
+ primaryApp, landscapePosLeft = tapl.isTablet, portraitPosTop = false)
@Presubmit
@Test
fun secondaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
- secondaryApp, landscapePosLeft = true, portraitPosTop = true)
+ secondaryApp, landscapePosLeft = !tapl.isTablet, portraitPosTop = true)
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt
index 20d7f2cf57e8..e5924c563e5b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt
@@ -30,8 +30,6 @@ import com.android.wm.shell.flicker.helpers.SplitScreenHelper
import com.android.wm.shell.flicker.layerBecomesVisible
import com.android.wm.shell.flicker.splitAppLayerBoundsIsVisibleAtEnd
import com.android.wm.shell.flicker.splitScreenDividerBecomesVisible
-import org.junit.Assume
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -50,28 +48,15 @@ import org.junit.runners.Parameterized
@Group1
class SwitchBackToSplitFromRecent(testSpec: FlickerTestParameter) : SplitScreenBase(testSpec) {
- // TODO(b/231399940): Remove this once we can use recent shortcut to enter split.
- @Before
- open fun before() {
- Assume.assumeTrue(tapl.isTablet)
- }
-
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
setup {
eachRun {
- primaryApp.launchViaIntent(wmHelper)
- // TODO(b/231399940): Use recent shortcut to enter split.
- tapl.launchedAppState.taskbar
- .openAllApps()
- .getAppIcon(secondaryApp.appName)
- .dragToSplitscreen(secondaryApp.`package`, primaryApp.`package`)
- SplitScreenHelper.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
+ SplitScreenHelper.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
tapl.goHome()
wmHelper.StateSyncBuilder()
- .withAppTransitionIdle()
.withHomeActivityVisible()
.waitForAndVerify()
}
@@ -99,12 +84,12 @@ class SwitchBackToSplitFromRecent(testSpec: FlickerTestParameter) : SplitScreenB
@Presubmit
@Test
fun primaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
- primaryApp, landscapePosLeft = false, portraitPosTop = false)
+ primaryApp, landscapePosLeft = tapl.isTablet, portraitPosTop = false)
@Presubmit
@Test
fun secondaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
- secondaryApp, landscapePosLeft = true, portraitPosTop = true)
+ secondaryApp, landscapePosLeft = !tapl.isTablet, portraitPosTop = true)
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index 95725bbfd855..695550dd8fa5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -159,7 +159,8 @@ public class SplitLayoutTests extends ShellTestCase {
}
private void waitDividerFlingFinished() {
- verify(mSplitLayout).flingDividePosition(anyInt(), anyInt(), mRunnableCaptor.capture());
+ verify(mSplitLayout).flingDividePosition(anyInt(), anyInt(), anyInt(),
+ mRunnableCaptor.capture());
mRunnableCaptor.getValue().run();
}
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 88f73d6cf251..b11e542472da 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -93,6 +93,10 @@ cc_defaults {
cc_defaults {
name: "hwui_static_deps",
+ defaults: [
+ "android.hardware.graphics.common-ndk_shared",
+ "android.hardware.graphics.composer3-ndk_shared",
+ ],
shared_libs: [
"libbase",
"libharfbuzz_ng",
@@ -106,9 +110,7 @@ cc_defaults {
target: {
android: {
shared_libs: [
- "android.hardware.graphics.common-V3-ndk",
"android.hardware.graphics.common@1.2",
- "android.hardware.graphics.composer3-V1-ndk",
"liblog",
"libcutils",
"libutils",
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 023d6bf0b673..397975dcb78f 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -57,6 +57,49 @@ namespace android {
using uirenderer::PaintUtils;
+class SkiaCanvas::Clip {
+public:
+ Clip(const SkRect& rect, SkClipOp op, const SkMatrix& m)
+ : mType(Type::Rect), mOp(op), mMatrix(m), mRRect(SkRRect::MakeRect(rect)) {}
+ Clip(const SkRRect& rrect, SkClipOp op, const SkMatrix& m)
+ : mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {}
+ Clip(const SkPath& path, SkClipOp op, const SkMatrix& m)
+ : mType(Type::Path), mOp(op), mMatrix(m), mPath(std::in_place, path) {}
+
+ void apply(SkCanvas* canvas) const {
+ canvas->setMatrix(mMatrix);
+ switch (mType) {
+ case Type::Rect:
+ // Don't anti-alias rectangular clips
+ canvas->clipRect(mRRect.rect(), mOp, false);
+ break;
+ case Type::RRect:
+ // Ensure rounded rectangular clips are anti-aliased
+ canvas->clipRRect(mRRect, mOp, true);
+ break;
+ case Type::Path:
+ // Ensure path clips are anti-aliased
+ canvas->clipPath(mPath.value(), mOp, true);
+ break;
+ }
+ }
+
+private:
+ enum class Type {
+ Rect,
+ RRect,
+ Path,
+ };
+
+ Type mType;
+ SkClipOp mOp;
+ SkMatrix mMatrix;
+
+ // These are logically a union (tracked separately due to non-POD path).
+ std::optional<SkPath> mPath;
+ SkRRect mRRect;
+};
+
Canvas* Canvas::create_canvas(const SkBitmap& bitmap) {
return new SkiaCanvas(bitmap);
}
@@ -200,49 +243,6 @@ void SkiaCanvas::restoreUnclippedLayer(int restoreCount, const Paint& paint) {
}
}
-class SkiaCanvas::Clip {
-public:
- Clip(const SkRect& rect, SkClipOp op, const SkMatrix& m)
- : mType(Type::Rect), mOp(op), mMatrix(m), mRRect(SkRRect::MakeRect(rect)) {}
- Clip(const SkRRect& rrect, SkClipOp op, const SkMatrix& m)
- : mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {}
- Clip(const SkPath& path, SkClipOp op, const SkMatrix& m)
- : mType(Type::Path), mOp(op), mMatrix(m), mPath(std::in_place, path) {}
-
- void apply(SkCanvas* canvas) const {
- canvas->setMatrix(mMatrix);
- switch (mType) {
- case Type::Rect:
- // Don't anti-alias rectangular clips
- canvas->clipRect(mRRect.rect(), mOp, false);
- break;
- case Type::RRect:
- // Ensure rounded rectangular clips are anti-aliased
- canvas->clipRRect(mRRect, mOp, true);
- break;
- case Type::Path:
- // Ensure path clips are anti-aliased
- canvas->clipPath(mPath.value(), mOp, true);
- break;
- }
- }
-
-private:
- enum class Type {
- Rect,
- RRect,
- Path,
- };
-
- Type mType;
- SkClipOp mOp;
- SkMatrix mMatrix;
-
- // These are logically a union (tracked separately due to non-POD path).
- std::optional<SkPath> mPath;
- SkRRect mRRect;
-};
-
const SkiaCanvas::SaveRec* SkiaCanvas::currentSaveRec() const {
const SaveRec* rec = mSaveStack ? static_cast<const SaveRec*>(mSaveStack->back()) : nullptr;
int currentSaveCount = mCanvas->getSaveCount();
diff --git a/media/Android.bp b/media/Android.bp
index 7118afad975a..e97f077b347a 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -35,8 +35,8 @@ aidl_interface {
"aidl/android/media/soundtrigger_middleware/SoundTriggerModuleDescriptor.aidl",
],
imports: [
- "android.media.audio.common.types",
- "android.media.soundtrigger.types",
+ "android.media.audio.common.types-V2",
+ "android.media.soundtrigger.types-V1",
"media_permission-aidl",
],
}
@@ -232,12 +232,12 @@ aidl_interface {
},
},
imports: [
- "android.media.audio.common.types",
+ "android.media.audio.common.types-V2",
],
versions_with_info: [
{
version: "1",
- imports: ["android.media.audio.common.types-V1"],
+ imports: ["android.media.audio.common.types-V2"],
},
],
diff --git a/media/java/android/media/AudioDeviceVolumeManager.java b/media/java/android/media/AudioDeviceVolumeManager.java
index c70887672f9e..40f6dc541f86 100644
--- a/media/java/android/media/AudioDeviceVolumeManager.java
+++ b/media/java/android/media/AudioDeviceVolumeManager.java
@@ -21,6 +21,8 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
import android.content.Context;
import android.os.IBinder;
import android.os.RemoteException;
@@ -39,23 +41,29 @@ import java.util.concurrent.Executor;
* @hide
* AudioDeviceVolumeManager provides access to audio device volume control.
*/
+@SystemApi
public class AudioDeviceVolumeManager {
// define when using Log.*
//private static final String TAG = "AudioDeviceVolumeManager";
- /** Indicates no special treatment in the handling of the volume adjustment */
+ /** @hide
+ * Indicates no special treatment in the handling of the volume adjustment */
public static final int ADJUST_MODE_NORMAL = 0;
- /** Indicates the start of a volume adjustment */
+ /** @hide
+ * Indicates the start of a volume adjustment */
public static final int ADJUST_MODE_START = 1;
- /** Indicates the end of a volume adjustment */
+ /** @hide
+ * Indicates the end of a volume adjustment */
public static final int ADJUST_MODE_END = 2;
+ /** @hide */
@IntDef(flag = false, prefix = "ADJUST_MODE", value = {
ADJUST_MODE_NORMAL,
ADJUST_MODE_START,
ADJUST_MODE_END}
)
+ /** @hide */
@Retention(RetentionPolicy.SOURCE)
public @interface VolumeAdjustmentMode {}
@@ -64,7 +72,16 @@ public class AudioDeviceVolumeManager {
private final @NonNull String mPackageName;
private final @Nullable String mAttributionTag;
- public AudioDeviceVolumeManager(Context context) {
+ /**
+ * Constructor
+ * @param context the Context for the device volume operations
+ */
+ @SuppressLint("ManagerConstructor")
+ // reason for suppression: even though the functionality handled by this class is implemented in
+ // AudioService, we want to avoid bloating android.media.AudioManager
+ // with @SystemApi functionality
+ public AudioDeviceVolumeManager(@NonNull Context context) {
+ Objects.requireNonNull(context);
mPackageName = context.getApplicationContext().getOpPackageName();
mAttributionTag = context.getApplicationContext().getAttributionTag();
}
@@ -101,6 +118,7 @@ public class AudioDeviceVolumeManager {
@VolumeAdjustmentMode int mode);
}
+ /** @hide */
static class ListenerInfo {
final @NonNull OnAudioDeviceVolumeChangedListener mListener;
final @NonNull Executor mExecutor;
@@ -127,6 +145,7 @@ public class AudioDeviceVolumeManager {
@GuardedBy("mDeviceVolumeListenerLock")
private DeviceVolumeDispatcherStub mDeviceVolumeDispatcherStub;
+ /** @hide */
final class DeviceVolumeDispatcherStub extends IAudioDeviceVolumeDispatcher.Stub {
/**
* Register / unregister the stub
@@ -305,6 +324,7 @@ public class AudioDeviceVolumeManager {
* @param vi the volume information, only stream-based volumes are supported
* @param ada the device for which volume is to be modified
*/
+ @SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
public void setDeviceVolume(@NonNull VolumeInfo vi, @NonNull AudioDeviceAttributes ada) {
try {
@@ -315,6 +335,7 @@ public class AudioDeviceVolumeManager {
}
/**
+ * @hide
* Return human-readable name for volume behavior
* @param behavior one of the volume behaviors defined in AudioManager
* @return a string for the given behavior
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 650f36059495..72190e370129 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -65,8 +65,6 @@ public class AudioSystem
private static final String TAG = "AudioSystem";
- private static final int SOURCE_CODEC_TYPE_OPUS = 6; // TODO remove in U
-
// private constructor to prevent instantiating AudioSystem
private AudioSystem() {
throw new UnsupportedOperationException("Trying to instantiate AudioSystem");
@@ -293,7 +291,7 @@ public class AudioSystem
case AUDIO_FORMAT_APTX_HD: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD;
case AUDIO_FORMAT_LDAC: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC;
case AUDIO_FORMAT_LC3: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3;
- case AUDIO_FORMAT_OPUS: return SOURCE_CODEC_TYPE_OPUS; // TODO update in U
+ case AUDIO_FORMAT_OPUS: return BluetoothCodecConfig.SOURCE_CODEC_TYPE_OPUS;
default:
Log.e(TAG, "Unknown audio format 0x" + Integer.toHexString(audioFormat)
+ " for conversion to BT codec");
@@ -336,7 +334,7 @@ public class AudioSystem
return AudioSystem.AUDIO_FORMAT_LDAC;
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3:
return AudioSystem.AUDIO_FORMAT_LC3;
- case SOURCE_CODEC_TYPE_OPUS: // TODO update in U
+ case BluetoothCodecConfig.SOURCE_CODEC_TYPE_OPUS:
return AudioSystem.AUDIO_FORMAT_OPUS;
default:
Log.e(TAG, "Unknown BT codec 0x" + Integer.toHexString(btCodec)
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index ee2e448bfdac..63173207ec17 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -5092,9 +5092,12 @@ public class MediaPlayer extends PlayerBase
@Nullable Map<String, String> optionalParameters)
throws NoDrmSchemeException
{
- Log.v(TAG, "getKeyRequest: " +
- " keySetId: " + keySetId + " initData:" + initData + " mimeType: " + mimeType +
- " keyType: " + keyType + " optionalParameters: " + optionalParameters);
+ Log.v(TAG, "getKeyRequest: "
+ + " keySetId: " + Arrays.toString(keySetId)
+ + " initData:" + Arrays.toString(initData)
+ + " mimeType: " + mimeType
+ + " keyType: " + keyType
+ + " optionalParameters: " + optionalParameters);
synchronized (mDrmLock) {
if (!mActiveDrmScheme) {
@@ -5153,7 +5156,8 @@ public class MediaPlayer extends PlayerBase
public byte[] provideKeyResponse(@Nullable byte[] keySetId, @NonNull byte[] response)
throws NoDrmSchemeException, DeniedByServerException
{
- Log.v(TAG, "provideKeyResponse: keySetId: " + keySetId + " response: " + response);
+ Log.v(TAG, "provideKeyResponse: keySetId: " + Arrays.toString(keySetId)
+ + " response: " + Arrays.toString(response));
synchronized (mDrmLock) {
@@ -5169,8 +5173,9 @@ public class MediaPlayer extends PlayerBase
byte[] keySetResult = mDrmObj.provideKeyResponse(scope, response);
- Log.v(TAG, "provideKeyResponse: keySetId: " + keySetId + " response: " + response +
- " --> " + keySetResult);
+ Log.v(TAG, "provideKeyResponse: keySetId: " + Arrays.toString(keySetId)
+ + " response: " + Arrays.toString(response)
+ + " --> " + Arrays.toString(keySetResult));
return keySetResult;
@@ -5197,7 +5202,7 @@ public class MediaPlayer extends PlayerBase
public void restoreKeys(@NonNull byte[] keySetId)
throws NoDrmSchemeException
{
- Log.v(TAG, "restoreKeys: keySetId: " + keySetId);
+ Log.v(TAG, "restoreKeys: keySetId: " + Arrays.toString(keySetId));
synchronized (mDrmLock) {
@@ -5484,7 +5489,8 @@ public class MediaPlayer extends PlayerBase
// at prepareDrm/openSession rather than getKeyRequest/provideKeyResponse
try {
mDrmSessionId = mDrmObj.openSession();
- Log.v(TAG, "prepareDrm_openSessionStep: mDrmSessionId=" + mDrmSessionId);
+ Log.v(TAG, "prepareDrm_openSessionStep: mDrmSessionId="
+ + Arrays.toString(mDrmSessionId));
// Sending it down to native/mediaserver to create the crypto object
// This call could simply fail due to bad player state, e.g., after start().
@@ -5547,7 +5553,7 @@ public class MediaPlayer extends PlayerBase
response = Streams.readFully(connection.getInputStream());
Log.v(TAG, "HandleProvisioninig: Thread run: response " +
- response.length + " " + response);
+ response.length + " " + Arrays.toString(response));
} catch (Exception e) {
status = PREPARE_DRM_STATUS_PROVISIONING_NETWORK_ERROR;
Log.w(TAG, "HandleProvisioninig: Thread run: connect " + e + " url: " + url);
@@ -5631,8 +5637,9 @@ public class MediaPlayer extends PlayerBase
return PREPARE_DRM_STATUS_PREPARATION_ERROR;
}
- Log.v(TAG, "HandleProvisioninig provReq " +
- " data: " + provReq.getData() + " url: " + provReq.getDefaultUrl());
+ Log.v(TAG, "HandleProvisioninig provReq "
+ + " data: " + Arrays.toString(provReq.getData())
+ + " url: " + provReq.getDefaultUrl());
// networking in a background thread
mDrmProvisioningInProgress = true;
@@ -5715,7 +5722,8 @@ public class MediaPlayer extends PlayerBase
private void cleanDrmObj()
{
// the caller holds mDrmLock
- Log.v(TAG, "cleanDrmObj: mDrmObj=" + mDrmObj + " mDrmSessionId=" + mDrmSessionId);
+ Log.v(TAG, "cleanDrmObj: mDrmObj=" + mDrmObj
+ + " mDrmSessionId=" + Arrays.toString(mDrmSessionId));
if (mDrmSessionId != null) {
mDrmObj.closeSession(mDrmSessionId);
diff --git a/media/java/android/media/VolumeInfo.java b/media/java/android/media/VolumeInfo.java
index c61b0e57db1a..6b4f604025e2 100644
--- a/media/java/android/media/VolumeInfo.java
+++ b/media/java/android/media/VolumeInfo.java
@@ -18,6 +18,7 @@ package android.media;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.content.Context;
import android.media.audiopolicy.AudioVolumeGroup;
import android.os.IBinder;
@@ -32,16 +33,13 @@ import java.util.Objects;
/**
* @hide
- * A class to represent type of volume information.
+ * A class to represent volume information.
* Can be used to represent volume associated with a stream type or {@link AudioVolumeGroup}.
* Volume index is optional when used to represent a category of volume.
* Index ranges are supported too, making the representation of volume changes agnostic to the
* range (e.g. can be used to map BT A2DP absolute volume range to internal range).
- *
- * Note: this class is not yet part of the SystemApi but is intended to be gradually introduced
- * particularly in parts of the audio framework that suffer from code ambiguity when
- * dealing with different volume ranges / units.
*/
+@SystemApi
public final class VolumeInfo implements Parcelable {
private static final String TAG = "VolumeInfo";
diff --git a/media/java/android/media/audiopolicy/AudioProductStrategy.java b/media/java/android/media/audiopolicy/AudioProductStrategy.java
index 31d596765bcc..f957498237a8 100644
--- a/media/java/android/media/audiopolicy/AudioProductStrategy.java
+++ b/media/java/android/media/audiopolicy/AudioProductStrategy.java
@@ -32,6 +32,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
@@ -182,7 +183,7 @@ public final class AudioProductStrategy implements Parcelable {
AudioProductStrategy thatStrategy = (AudioProductStrategy) o;
return mName == thatStrategy.mName && mId == thatStrategy.mId
- && mAudioAttributesGroups.equals(thatStrategy.mAudioAttributesGroups);
+ && Arrays.equals(mAudioAttributesGroups, thatStrategy.mAudioAttributesGroups);
}
/**
@@ -415,7 +416,7 @@ public final class AudioProductStrategy implements Parcelable {
return mVolumeGroupId == thatAag.mVolumeGroupId
&& mLegacyStreamType == thatAag.mLegacyStreamType
- && mAudioAttributes.equals(thatAag.mAudioAttributes);
+ && Arrays.equals(mAudioAttributes, thatAag.mAudioAttributes);
}
public int getStreamType() {
diff --git a/media/java/android/media/audiopolicy/AudioVolumeGroup.java b/media/java/android/media/audiopolicy/AudioVolumeGroup.java
index 79be92214455..d58111d1e9a7 100644
--- a/media/java/android/media/audiopolicy/AudioVolumeGroup.java
+++ b/media/java/android/media/audiopolicy/AudioVolumeGroup.java
@@ -114,7 +114,7 @@ public final class AudioVolumeGroup implements Parcelable {
AudioVolumeGroup thatAvg = (AudioVolumeGroup) o;
return mName == thatAvg.mName && mId == thatAvg.mId
- && mAudioAttributes.equals(thatAvg.mAudioAttributes);
+ && Arrays.equals(mAudioAttributes, thatAvg.mAudioAttributes);
}
/**
diff --git a/media/java/android/media/metrics/PlaybackMetrics.java b/media/java/android/media/metrics/PlaybackMetrics.java
index e71ee204f564..51a2c9d9b50e 100644
--- a/media/java/android/media/metrics/PlaybackMetrics.java
+++ b/media/java/android/media/metrics/PlaybackMetrics.java
@@ -402,9 +402,10 @@ public final class PlaybackMetrics implements Parcelable {
@Override
public int hashCode() {
return Objects.hash(mMediaDurationMillis, mStreamSource, mStreamType, mPlaybackType,
- mDrmType, mContentType, mPlayerName, mPlayerVersion, mExperimentIds,
- mVideoFramesPlayed, mVideoFramesDropped, mAudioUnderrunCount, mNetworkBytesRead,
- mLocalBytesRead, mNetworkTransferDurationMillis, mDrmSessionId);
+ mDrmType, mContentType, mPlayerName, mPlayerVersion,
+ Arrays.hashCode(mExperimentIds), mVideoFramesPlayed, mVideoFramesDropped,
+ mAudioUnderrunCount, mNetworkBytesRead, mLocalBytesRead,
+ mNetworkTransferDurationMillis, Arrays.hashCode(mDrmSessionId));
}
@Override
diff --git a/media/java/android/media/session/ISession.aidl b/media/java/android/media/session/ISession.aidl
index 31fb8d03c4a0..9bf126b7a875 100644
--- a/media/java/android/media/session/ISession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -35,7 +35,7 @@ interface ISession {
ISessionController getController();
void setFlags(int flags);
void setActive(boolean active);
- void setMediaButtonReceiver(in PendingIntent mbr);
+ void setMediaButtonReceiver(in PendingIntent mbr, String sessionPackageName);
void setMediaButtonBroadcastReceiver(in ComponentName broadcastReceiver);
void setLaunchPendingIntent(in PendingIntent pi);
void destroySession();
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 1bd12afdc026..9e265d8339dd 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -286,7 +286,7 @@ public final class MediaSession {
@Deprecated
public void setMediaButtonReceiver(@Nullable PendingIntent mbr) {
try {
- mBinder.setMediaButtonReceiver(mbr);
+ mBinder.setMediaButtonReceiver(mbr, mContext.getPackageName());
} catch (RemoteException e) {
Log.wtf(TAG, "Failure in setMediaButtonReceiver.", e);
}
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 41914b887b2b..ebf1a75a58a4 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraErrorCollector.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraErrorCollector.java
@@ -16,10 +16,6 @@
package com.android.mediaframeworktest.helpers;
-import org.hamcrest.CoreMatchers;
-import org.hamcrest.Matcher;
-import org.junit.rules.ErrorCollector;
-
import android.graphics.Rect;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
@@ -30,6 +26,10 @@ import android.media.Image;
import android.util.Log;
import android.util.Size;
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.Matcher;
+import org.junit.rules.ErrorCollector;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@@ -903,7 +903,7 @@ public class CameraErrorCollector extends ErrorCollector {
if ((value = expectKeyValueNotNull(characteristics, key)) == null) {
return;
}
- String reason = "Key " + key.getName() + " value " + value
+ String reason = "Key " + key.getName() + " value " + Arrays.toString(value)
+ " doesn't contain the expected value " + expected;
expectContains(reason, value, expected);
}
@@ -921,7 +921,7 @@ public class CameraErrorCollector extends ErrorCollector {
if ((value = expectKeyValueNotNull(characteristics, key)) == null) {
return;
}
- String reason = "Key " + key.getName() + " value " + value
+ String reason = "Key " + key.getName() + " value " + Arrays.toString(value)
+ " doesn't contain the expected value " + expected;
expectContains(reason, value, expected);
}
@@ -939,7 +939,7 @@ public class CameraErrorCollector extends ErrorCollector {
if ((value = expectKeyValueNotNull(characteristics, key)) == null) {
return;
}
- String reason = "Key " + key.getName() + " value " + value
+ String reason = "Key " + key.getName() + " value " + Arrays.toString(value)
+ " doesn't contain the expected value " + expected;
expectContains(reason, value, expected);
}
@@ -960,7 +960,7 @@ public class CameraErrorCollector extends ErrorCollector {
public <T> void expectContains(T[] values, T expected) {
String reason = "Expected value " + expected
- + " is not contained in the given values " + values;
+ + " is not contained in the given values " + Arrays.toString(values);
expectContains(reason, values, expected);
}
@@ -996,7 +996,7 @@ public class CameraErrorCollector extends ErrorCollector {
public void expectContains(int[] values, int expected) {
String reason = "Expected value " + expected
- + " is not contained in the given values " + values;
+ + " is not contained in the given values " + Arrays.toString(values);
expectContains(reason, values, expected);
}
@@ -1040,7 +1040,7 @@ public class CameraErrorCollector extends ErrorCollector {
*/
public void expectContains(boolean[] values, boolean expected) {
String reason = "Expected value " + expected
- + " is not contained in the given values " + values;
+ + " is not contained in the given values " + Arrays.toString(values);
expectContains(reason, values, expected);
}
diff --git a/opengl/java/android/opengl/GLLogWrapper.java b/opengl/java/android/opengl/GLLogWrapper.java
index bff739636b3e..e645afa1df5a 100644
--- a/opengl/java/android/opengl/GLLogWrapper.java
+++ b/opengl/java/android/opengl/GLLogWrapper.java
@@ -2812,7 +2812,7 @@ class GLLogWrapper extends GLWrapperBase {
public void glDeleteBuffers(int n, int[] buffers, int offset) {
begin("glDeleteBuffers");
arg("n", n);
- arg("buffers", buffers.toString());
+ arg("buffers", Arrays.toString(buffers));
arg("offset", offset);
end();
mgl11.glDeleteBuffers(n, buffers, offset);
@@ -2831,7 +2831,7 @@ class GLLogWrapper extends GLWrapperBase {
public void glGenBuffers(int n, int[] buffers, int offset) {
begin("glGenBuffers");
arg("n", n);
- arg("buffers", buffers.toString());
+ arg("buffers", Arrays.toString(buffers));
arg("offset", offset);
end();
mgl11.glGenBuffers(n, buffers, offset);
@@ -2850,7 +2850,7 @@ class GLLogWrapper extends GLWrapperBase {
public void glGetBooleanv(int pname, boolean[] params, int offset) {
begin("glGetBooleanv");
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glGetBooleanv(pname, params, offset);
@@ -2871,7 +2871,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glGetBufferParameteriv");
arg("target", target);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glGetBufferParameteriv(target, pname, params, offset);
@@ -2891,7 +2891,7 @@ class GLLogWrapper extends GLWrapperBase {
public void glGetClipPlanef(int pname, float[] eqn, int offset) {
begin("glGetClipPlanef");
arg("pname", pname);
- arg("eqn", eqn.toString());
+ arg("eqn", Arrays.toString(eqn));
arg("offset", offset);
end();
mgl11.glGetClipPlanef(pname, eqn, offset);
@@ -2910,7 +2910,7 @@ class GLLogWrapper extends GLWrapperBase {
public void glGetClipPlanex(int pname, int[] eqn, int offset) {
begin("glGetClipPlanex");
arg("pname", pname);
- arg("eqn", eqn.toString());
+ arg("eqn", Arrays.toString(eqn));
arg("offset", offset);
end();
mgl11.glGetClipPlanex(pname, eqn, offset);
@@ -2928,7 +2928,7 @@ class GLLogWrapper extends GLWrapperBase {
public void glGetFixedv(int pname, int[] params, int offset) {
begin("glGetFixedv");
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glGetFixedv(pname, params, offset);
@@ -2946,7 +2946,7 @@ class GLLogWrapper extends GLWrapperBase {
public void glGetFloatv(int pname, float[] params, int offset) {
begin("glGetFloatv");
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glGetFloatv(pname, params, offset);
@@ -2965,7 +2965,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glGetLightfv");
arg("light", light);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glGetLightfv(light, pname, params, offset);
@@ -2986,7 +2986,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glGetLightxv");
arg("light", light);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glGetLightxv(light, pname, params, offset);
@@ -3008,7 +3008,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glGetMaterialfv");
arg("face", face);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glGetMaterialfv(face, pname, params, offset);
@@ -3029,7 +3029,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glGetMaterialxv");
arg("face", face);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glGetMaterialxv(face, pname, params, offset);
@@ -3050,7 +3050,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glGetTexEnviv");
arg("env", env);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glGetTexEnviv(env, pname, params, offset);
@@ -3071,7 +3071,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glGetTexEnviv");
arg("env", env);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glGetTexEnviv(env, pname, params, offset);
@@ -3092,7 +3092,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glGetTexParameterfv");
arg("target", target);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glGetTexParameterfv(target, pname, params, offset);
@@ -3113,7 +3113,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glGetTexParameteriv");
arg("target", target);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glGetTexEnviv(target, pname, params, offset);
@@ -3135,7 +3135,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glGetTexParameterxv");
arg("target", target);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glGetTexParameterxv(target, pname, params, offset);
@@ -3191,7 +3191,7 @@ class GLLogWrapper extends GLWrapperBase {
public void glPointParameterfv(int pname, float[] params, int offset) {
begin("glPointParameterfv");
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glPointParameterfv(pname, params, offset);
@@ -3219,7 +3219,7 @@ class GLLogWrapper extends GLWrapperBase {
public void glPointParameterxv(int pname, int[] params, int offset) {
begin("glPointParameterxv");
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glPointParameterxv(pname, params, offset);
@@ -3259,7 +3259,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glTexEnviv");
arg("target", target);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glTexEnviv(target, pname, params, offset);
@@ -3281,7 +3281,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glTexParameterfv");
arg("target", target);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glTexParameterfv( target, pname, params, offset);
@@ -3313,7 +3313,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glTexParameterxv");
arg("target", target);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11.glTexParameterxv(target, pname, params, offset);
@@ -3356,7 +3356,7 @@ class GLLogWrapper extends GLWrapperBase {
public void glGetPointerv(int pname, Buffer[] params) {
begin("glGetPointerv");
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
end();
mgl11.glGetPointerv(pname, params);
checkError();
@@ -3513,7 +3513,7 @@ class GLLogWrapper extends GLWrapperBase {
public void glDeleteFramebuffersOES(int n, int[] framebuffers, int offset) {
begin("glDeleteFramebuffersOES");
arg("n", n);
- arg("framebuffers", framebuffers.toString());
+ arg("framebuffers", Arrays.toString(framebuffers));
arg("offset", offset);
end();
mgl11ExtensionPack.glDeleteFramebuffersOES(n, framebuffers, offset);
@@ -3534,7 +3534,7 @@ class GLLogWrapper extends GLWrapperBase {
public void glDeleteRenderbuffersOES(int n, int[] renderbuffers, int offset) {
begin("glDeleteRenderbuffersOES");
arg("n", n);
- arg("renderbuffers", renderbuffers.toString());
+ arg("renderbuffers", Arrays.toString(renderbuffers));
arg("offset", offset);
end();
mgl11ExtensionPack.glDeleteRenderbuffersOES(n, renderbuffers, offset);
@@ -3591,7 +3591,7 @@ class GLLogWrapper extends GLWrapperBase {
public void glGenFramebuffersOES(int n, int[] framebuffers, int offset) {
begin("glGenFramebuffersOES");
arg("n", n);
- arg("framebuffers", framebuffers.toString());
+ arg("framebuffers", Arrays.toString(framebuffers));
arg("offset", offset);
end();
mgl11ExtensionPack.glGenFramebuffersOES(n, framebuffers, offset);
@@ -3612,7 +3612,7 @@ class GLLogWrapper extends GLWrapperBase {
public void glGenRenderbuffersOES(int n, int[] renderbuffers, int offset) {
begin("glGenRenderbuffersOES");
arg("n", n);
- arg("renderbuffers", renderbuffers.toString());
+ arg("renderbuffers", Arrays.toString(renderbuffers));
arg("offset", offset);
end();
mgl11ExtensionPack.glGenRenderbuffersOES(n, renderbuffers, offset);
@@ -3636,7 +3636,7 @@ class GLLogWrapper extends GLWrapperBase {
arg("target", target);
arg("attachment", attachment);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11ExtensionPack.glGetFramebufferAttachmentParameterivOES(target, attachment, pname, params, offset);
@@ -3662,7 +3662,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glGetRenderbufferParameterivOES");
arg("target", target);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11ExtensionPack.glGetRenderbufferParameterivOES(target, pname, params, offset);
@@ -3686,7 +3686,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glGetTexGenfv");
arg("coord", coord);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11ExtensionPack.glGetTexGenfv(coord, pname, params, offset);
@@ -3709,7 +3709,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glGetTexGeniv");
arg("coord", coord);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11ExtensionPack.glGetTexGeniv(coord, pname, params, offset);
@@ -3732,7 +3732,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glGetTexGenxv");
arg("coord", coord);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11ExtensionPack.glGetTexGenxv(coord, pname, params, offset);
@@ -3799,7 +3799,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glTexGenfv");
arg("coord", coord);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11ExtensionPack.glTexGenfv(coord, pname, params, offset);
@@ -3833,7 +3833,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glTexGeniv");
arg("coord", coord);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11ExtensionPack.glTexGeniv(coord, pname, params, offset);
@@ -3867,7 +3867,7 @@ class GLLogWrapper extends GLWrapperBase {
begin("glTexGenxv");
arg("coord", coord);
arg("pname", pname);
- arg("params", params.toString());
+ arg("params", Arrays.toString(params));
arg("offset", offset);
end();
mgl11ExtensionPack.glTexGenxv(coord, pname, params, offset);
diff --git a/packages/SettingsLib/Spa/build.gradle b/packages/SettingsLib/Spa/build.gradle
index d38013679ad4..5dc2aa0d61cb 100644
--- a/packages/SettingsLib/Spa/build.gradle
+++ b/packages/SettingsLib/Spa/build.gradle
@@ -22,7 +22,7 @@ buildscript {
}
}
plugins {
- id 'com.android.application' version '7.3.0-beta04' apply false
- id 'com.android.library' version '7.3.0-beta04' apply false
+ id 'com.android.application' version '7.3.0-rc01' apply false
+ id 'com.android.library' version '7.3.0-rc01' apply false
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/SpaEnvironment.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/SpaEnvironment.kt
index 3f375345f30f..3233d4d75631 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/SpaEnvironment.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/SpaEnvironment.kt
@@ -20,15 +20,17 @@ import com.android.settingslib.spa.framework.common.SettingsPageProviderReposito
import com.android.settingslib.spa.gallery.home.HomePageProvider
import com.android.settingslib.spa.gallery.page.ArgumentPageProvider
import com.android.settingslib.spa.gallery.page.FooterPageProvider
-import com.android.settingslib.spa.gallery.page.PreferencePageProvider
import com.android.settingslib.spa.gallery.page.SettingsPagerPageProvider
import com.android.settingslib.spa.gallery.page.SliderPageProvider
-import com.android.settingslib.spa.gallery.page.SwitchPreferencePageProvider
+import com.android.settingslib.spa.gallery.preference.PreferenceMainPageProvider
+import com.android.settingslib.spa.gallery.preference.PreferencePageProvider
+import com.android.settingslib.spa.gallery.preference.SwitchPreferencePageProvider
import com.android.settingslib.spa.gallery.ui.SpinnerPageProvider
val galleryPageProviders = SettingsPageProviderRepository(
allPagesList = listOf(
HomePageProvider,
+ PreferenceMainPageProvider,
PreferencePageProvider,
SwitchPreferencePageProvider,
ArgumentPageProvider,
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt
index 089920c8e8cf..fdcb1c2a5853 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/home/HomePage.kt
@@ -25,10 +25,9 @@ import com.android.settingslib.spa.framework.theme.SettingsTheme
import com.android.settingslib.spa.gallery.R
import com.android.settingslib.spa.gallery.page.ArgumentPageProvider
import com.android.settingslib.spa.gallery.page.FooterPageProvider
-import com.android.settingslib.spa.gallery.page.PreferencePageProvider
import com.android.settingslib.spa.gallery.page.SettingsPagerPageProvider
import com.android.settingslib.spa.gallery.page.SliderPageProvider
-import com.android.settingslib.spa.gallery.page.SwitchPreferencePageProvider
+import com.android.settingslib.spa.gallery.preference.PreferenceMainPageProvider
import com.android.settingslib.spa.gallery.ui.SpinnerPageProvider
import com.android.settingslib.spa.widget.scaffold.HomeScaffold
@@ -44,8 +43,7 @@ object HomePageProvider : SettingsPageProvider {
@Composable
private fun HomePage() {
HomeScaffold(title = stringResource(R.string.app_name)) {
- PreferencePageProvider.EntryItem()
- SwitchPreferencePageProvider.EntryItem()
+ PreferenceMainPageProvider.EntryItem()
ArgumentPageProvider.EntryItem(stringParam = "foo", intParam = 0)
SliderPageProvider.EntryItem()
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferenceMain.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferenceMain.kt
new file mode 100644
index 000000000000..d3ca1d3f347e
--- /dev/null
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferenceMain.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.spa.gallery.preference
+
+import android.os.Bundle
+import androidx.compose.runtime.Composable
+import com.android.settingslib.spa.framework.common.SettingsPageProvider
+import com.android.settingslib.spa.framework.compose.navigator
+import com.android.settingslib.spa.widget.preference.Preference
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.scaffold.RegularScaffold
+
+private const val TITLE = "Category: Preference"
+
+object PreferenceMainPageProvider : SettingsPageProvider {
+ override val name = "PreferenceMain"
+
+ @Composable
+ override fun Page(arguments: Bundle?) {
+ PreferenceMain()
+ }
+
+ @Composable
+ fun EntryItem() {
+ Preference(object : PreferenceModel {
+ override val title = TITLE
+ override val onClick = navigator(name)
+ })
+ }
+}
+
+@Composable
+private fun PreferenceMain() {
+ RegularScaffold(title = TITLE) {
+ PreferencePageProvider.EntryItem()
+ SwitchPreferencePageProvider.EntryItem()
+ }
+}
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePage.kt
index 90dacdbe5087..36c619f79f5a 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/PreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/PreferencePage.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settingslib.spa.gallery.page
+package com.android.settingslib.spa.gallery.preference
import android.os.Bundle
import androidx.compose.material.icons.Icons
diff --git a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SwitchPreferencePage.kt b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt
index 6d5d4483ab5f..8be6a895f3a4 100644
--- a/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/page/SwitchPreferencePage.kt
+++ b/packages/SettingsLib/Spa/gallery/src/com/android/settingslib/spa/gallery/preference/SwitchPreferencePage.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settingslib.spa.gallery.page
+package com.android.settingslib.spa.gallery.preference
import android.os.Bundle
import androidx.compose.runtime.Composable
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
index dac79a0fbb16..eb9ce5e77c93 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppInfoPage.kt
@@ -30,7 +30,6 @@ import androidx.navigation.NavType
import androidx.navigation.navArgument
import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator
-import com.android.settingslib.spa.framework.compose.rememberContext
import com.android.settingslib.spa.widget.preference.SwitchPreference
import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
import com.android.settingslib.spaprivileged.model.app.AppRecord
@@ -44,7 +43,7 @@ private const val PACKAGE_NAME = "packageName"
private const val USER_ID = "userId"
internal class TogglePermissionAppInfoPageProvider(
- private val factory: TogglePermissionAppListModelFactory,
+ private val appListTemplate: TogglePermissionAppListTemplate,
) : SettingsPageProvider {
override val name = NAME
@@ -57,10 +56,10 @@ internal class TogglePermissionAppInfoPageProvider(
@Composable
override fun Page(arguments: Bundle?) {
checkNotNull(arguments)
- val permission = checkNotNull(arguments.getString(PERMISSION))
+ val permissionType = checkNotNull(arguments.getString(PERMISSION))
val packageName = checkNotNull(arguments.getString(PACKAGE_NAME))
val userId = arguments.getInt(USER_ID)
- val listModel = rememberContext { context -> factory.createModel(permission, context) }
+ val listModel = appListTemplate.rememberModel(permissionType)
TogglePermissionAppInfoPage(listModel, packageName, userId)
}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListModel.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
index a2848392a2f0..3cc5854b95e4 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListModel.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppList.kt
@@ -47,20 +47,14 @@ interface TogglePermissionAppListModel<T : AppRecord> {
fun setAllowed(record: T, newAllowed: Boolean)
}
-interface TogglePermissionAppListModelFactory {
- fun createModel(
- permission: String,
- context: Context,
- ): TogglePermissionAppListModel<out AppRecord>
+interface TogglePermissionAppListProvider {
+ val permissionType: String
- fun createPageProviders(): List<SettingsPageProvider> = listOf(
- TogglePermissionAppListPageProvider(this),
- TogglePermissionAppInfoPageProvider(this),
- )
+ fun createModel(context: Context): TogglePermissionAppListModel<out AppRecord>
@Composable
- fun EntryItem(permissionType: String) {
- val listModel = rememberModel(permissionType)
+ fun EntryItem() {
+ val listModel = rememberContext(::createModel)
Preference(
object : PreferenceModel {
override val title = stringResource(listModel.pageTitleResId)
@@ -74,10 +68,22 @@ interface TogglePermissionAppListModelFactory {
*
* Expose route to enable enter from non-SPA pages.
*/
- fun getRoute(permissionType: String): String =
+ fun getRoute(): String =
TogglePermissionAppListPageProvider.getRoute(permissionType)
}
-@Composable
-internal fun TogglePermissionAppListModelFactory.rememberModel(permission: String) =
- rememberContext { context -> createModel(permission, context) }
+class TogglePermissionAppListTemplate(
+ allProviders: List<TogglePermissionAppListProvider>,
+) {
+ private val listModelProviderMap = allProviders.associateBy { it.permissionType }
+
+ fun createPageProviders(): List<SettingsPageProvider> = listOf(
+ TogglePermissionAppListPageProvider(this),
+ TogglePermissionAppInfoPageProvider(this),
+ )
+
+ @Composable
+ internal fun rememberModel(permissionType: String) = rememberContext { context ->
+ listModelProviderMap.getValue(permissionType).createModel(context)
+ }
+}
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt
index a4d9058fde4d..f2eb96277b9b 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/TogglePermissionAppListPage.kt
@@ -38,7 +38,7 @@ private const val NAME = "TogglePermissionAppList"
private const val PERMISSION = "permission"
internal class TogglePermissionAppListPageProvider(
- private val factory: TogglePermissionAppListModelFactory,
+ private val appListTemplate: TogglePermissionAppListTemplate,
) : SettingsPageProvider {
override val name = NAME
@@ -55,7 +55,7 @@ internal class TogglePermissionAppListPageProvider(
@Composable
private fun TogglePermissionAppList(permissionType: String) {
- val listModel = factory.rememberModel(permissionType)
+ val listModel = appListTemplate.rememberModel(permissionType)
val context = LocalContext.current
val internalListModel = remember {
TogglePermissionInternalAppListModel(context, listModel)
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
index 19409865284c..b64dcca63ac9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/A2dpProfile.java
@@ -43,8 +43,6 @@ import java.util.List;
public class A2dpProfile implements LocalBluetoothProfile {
private static final String TAG = "A2dpProfile";
- private static final int SOURCE_CODEC_TYPE_OPUS = 6; // TODO remove in U
-
private Context mContext;
private BluetoothA2dp mService;
@@ -333,7 +331,7 @@ public class A2dpProfile implements LocalBluetoothProfile {
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LC3:
index = 6;
break;
- case SOURCE_CODEC_TYPE_OPUS: // TODO update in U
+ case BluetoothCodecConfig.SOURCE_CODEC_TYPE_OPUS:
index = 7;
break;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 62c83cf04a4f..51812f043908 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -367,8 +367,14 @@ public class BluetoothEventManager {
if (bondState == BluetoothDevice.BOND_NONE) {
// Check if we need to remove other Coordinated set member devices / Hearing Aid
// devices
+ if (DEBUG) {
+ Log.d(TAG, "BondStateChangedHandler: cachedDevice.getGroupId() = "
+ + cachedDevice.getGroupId() + ", cachedDevice.getHiSyncId()= "
+ + cachedDevice.getHiSyncId());
+ }
if (cachedDevice.getGroupId() != BluetoothCsipSetCoordinator.GROUP_ID_INVALID
|| cachedDevice.getHiSyncId() != BluetoothHearingAid.HI_SYNC_ID_INVALID) {
+ Log.d(TAG, "BondStateChangedHandler: Start onDeviceUnpaired");
mDeviceManager.onDeviceUnpaired(cachedDevice);
}
int reason = intent.getIntExtra(BluetoothDevice.EXTRA_UNBOND_REASON,
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 32d5b787489a..3ca94dba027e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -1431,11 +1431,10 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
* first connected device in the coordinated set, and then switch the content of the main
* device and member devices.
*
- * @param prevMainDevice the previous Main device, it will be added into the member device set.
- * @param newMainDevice the new Main device, it will be removed from the member device set.
+ * @param newMainDevice the new Main device which is from the previous main device's member
+ * list.
*/
- public void switchMemberDeviceContent(CachedBluetoothDevice prevMainDevice,
- CachedBluetoothDevice newMainDevice) {
+ public void switchMemberDeviceContent(CachedBluetoothDevice newMainDevice) {
// Backup from main device
final BluetoothDevice tmpDevice = mDevice;
final short tmpRssi = mRssi;
@@ -1444,8 +1443,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice>
mDevice = newMainDevice.mDevice;
mRssi = newMainDevice.mRssi;
mJustDiscovered = newMainDevice.mJustDiscovered;
- addMemberDevice(prevMainDevice);
- mMemberDevices.remove(newMainDevice);
+
// Set sub device from backup
newMainDevice.mDevice = tmpDevice;
newMainDevice.mRssi = tmpRssi;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index cd3242a9f7c2..26a208026411 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -17,6 +17,7 @@
package com.android.settingslib.bluetooth;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
@@ -317,12 +318,14 @@ public class CachedBluetoothDeviceManager {
}
public synchronized void onDeviceUnpaired(CachedBluetoothDevice device) {
+ device.setGroupId(BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
CachedBluetoothDevice mainDevice = mCsipDeviceManager.findMainDevice(device);
final Set<CachedBluetoothDevice> memberDevices = device.getMemberDevice();
if (!memberDevices.isEmpty()) {
// Main device is unpaired, to unpair the member device
for (CachedBluetoothDevice memberDevice : memberDevices) {
memberDevice.unpair();
+ memberDevice.setGroupId(BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
device.removeMemberDevice(memberDevice);
}
} else if (mainDevice != null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
index fc70ba40fb47..9b38238ca8b8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java
@@ -231,7 +231,7 @@ public class CsipDeviceManager {
// When both LE Audio devices are disconnected, receiving member device
// connection. To switch content and dispatch to notify UI change
mBtManager.getEventManager().dispatchDeviceRemoved(mainDevice);
- mainDevice.switchMemberDeviceContent(mainDevice, cachedDevice);
+ mainDevice.switchMemberDeviceContent(cachedDevice);
mainDevice.refresh();
// It is necessary to do remove and add for updating the mapping on
// preference and device
@@ -255,10 +255,11 @@ public class CsipDeviceManager {
for (CachedBluetoothDevice device: memberSet) {
if (device.isConnected()) {
+ log("set device: " + device + " as the main device");
// Main device is disconnected and sub device is connected
// To copy data from sub device to main device
mBtManager.getEventManager().dispatchDeviceRemoved(cachedDevice);
- cachedDevice.switchMemberDeviceContent(device, cachedDevice);
+ cachedDevice.switchMemberDeviceContent(device);
cachedDevice.refresh();
// It is necessary to do remove and add for updating the mapping on
// preference and device
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
index bef1d9cbcde1..62552f914459 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothCsipSetCoordinator;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothUuid;
import android.content.Context;
@@ -518,7 +519,8 @@ public class CachedBluetoothDeviceManagerTest {
*/
@Test
public void onDeviceUnpaired_unpairCsipMainDevice() {
- when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+ when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
cachedDevice1.setGroupId(1);
@@ -527,7 +529,12 @@ public class CachedBluetoothDeviceManagerTest {
// Call onDeviceUnpaired for the one in mCachedDevices.
mCachedDeviceManager.onDeviceUnpaired(cachedDevice1);
+
verify(mDevice2).removeBond();
+ assertThat(cachedDevice1.getGroupId()).isEqualTo(
+ BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
+ assertThat(cachedDevice2.getGroupId()).isEqualTo(
+ BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
}
/**
@@ -536,6 +543,7 @@ public class CachedBluetoothDeviceManagerTest {
@Test
public void onDeviceUnpaired_unpairCsipSubDevice() {
when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+ when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mDevice1);
CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mDevice2);
cachedDevice1.setGroupId(1);
@@ -544,7 +552,10 @@ public class CachedBluetoothDeviceManagerTest {
// Call onDeviceUnpaired for the one in mCachedDevices.
mCachedDeviceManager.onDeviceUnpaired(cachedDevice2);
+
verify(mDevice1).removeBond();
+ assertThat(cachedDevice2.getGroupId()).isEqualTo(
+ BluetoothCsipSetCoordinator.GROUP_ID_INVALID);
}
/**
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 76c066cd029e..79e99387b2fa 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -1050,4 +1050,23 @@ public class CachedBluetoothDeviceTest {
assertThat(mCachedDevice.mDrawableCache.size()).isEqualTo(0);
}
+
+ @Test
+ public void switchMemberDeviceContent_switchMainDevice_switchesSuccessful() {
+ mCachedDevice.mRssi = RSSI_1;
+ mCachedDevice.mJustDiscovered = JUSTDISCOVERED_1;
+ mSubCachedDevice.mRssi = RSSI_2;
+ mSubCachedDevice.mJustDiscovered = JUSTDISCOVERED_2;
+ mCachedDevice.addMemberDevice(mSubCachedDevice);
+
+ mCachedDevice.switchMemberDeviceContent(mSubCachedDevice);
+
+ assertThat(mCachedDevice.mRssi).isEqualTo(RSSI_2);
+ assertThat(mCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_2);
+ assertThat(mCachedDevice.mDevice).isEqualTo(mSubDevice);
+ assertThat(mSubCachedDevice.mRssi).isEqualTo(RSSI_1);
+ assertThat(mSubCachedDevice.mJustDiscovered).isEqualTo(JUSTDISCOVERED_1);
+ assertThat(mSubCachedDevice.mDevice).isEqualTo(mDevice);
+ assertThat(mCachedDevice.getMemberDevice().contains(mSubCachedDevice)).isTrue();
+ }
}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 62def4875594..7649de649cf8 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -85,7 +85,6 @@
<uses-permission android:name="android.permission.CONTROL_VPN" />
<uses-permission android:name="android.permission.PEERS_MAC_ADDRESS"/>
<uses-permission android:name="android.permission.READ_WIFI_CREDENTIAL"/>
- <uses-permission android:name="android.permission.NETWORK_STACK"/>
<!-- Physical hardware -->
<uses-permission android:name="android.permission.MANAGE_USB" />
<uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS" />
@@ -95,6 +94,7 @@
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" />
<uses-permission android:name="android.permission.OBSERVE_SENSOR_PRIVACY" />
+ <uses-permission android:name="android.permission.ACCESS_AMBIENT_CONTEXT_EVENT" />
<!-- ActivityManager -->
<uses-permission android:name="android.permission.REAL_GET_TASKS" />
diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt
new file mode 100644
index 000000000000..3ca8dfe4fd38
--- /dev/null
+++ b/packages/SystemUI/ktfmt_includes.txt
@@ -0,0 +1,870 @@
++packages/SystemUI
+-packages/SystemUI/animation/src/com/android/systemui/animation/FontInterpolator.kt
+-packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
+-packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
+-packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
+-packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/BindServiceViaContextDetector.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/BroadcastSentViaContextDetector.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/GetMainLooperViaContextDetector.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/RegisterReceiverViaContextDetector.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/SoftwareBitmapDetector.kt
+-packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt
+-packages/SystemUI/checks/tests/com/android/systemui/lint/BindServiceViaContextDetectorTest.kt
+-packages/SystemUI/checks/tests/com/android/systemui/lint/BroadcastSentViaContextDetectorTest.kt
+-packages/SystemUI/checks/tests/com/android/systemui/lint/GetMainLooperViaContextDetectorTest.kt
+-packages/SystemUI/checks/tests/com/android/systemui/lint/RegisterReceiverViaContextDetectorTest.kt
+-packages/SystemUI/checks/tests/com/android/systemui/lint/SoftwareBitmapDetectorTest.kt
+-packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
+-packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+-packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainerController.kt
+-packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
+-packages/SystemUI/shared/src/com/android/systemui/flags/FlagListenable.kt
+-packages/SystemUI/shared/src/com/android/systemui/flags/FlagManager.kt
+-packages/SystemUI/shared/src/com/android/systemui/flags/FlagSerializer.kt
+-packages/SystemUI/shared/src/com/android/systemui/flags/FlagSettingsHelper.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimator.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionDarkness.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/regionsampling/RegionSamplingInstance.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonPositionCalculator.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerManager.kt
+-packages/SystemUI/shared/src/com/android/systemui/shared/system/smartspace/SmartspaceState.kt
+-packages/SystemUI/shared/src/com/android/systemui/unfold/system/ActivityManagerActivityTypeProvider.kt
+-packages/SystemUI/shared/src/com/android/systemui/unfold/system/DeviceStateManagerFoldProvider.kt
+-packages/SystemUI/shared/src/com/android/systemui/unfold/system/SystemUnfoldSharedModule.kt
+-packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
+-packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
+-packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt
+-packages/SystemUI/src/com/android/keyguard/BouncerPanelExpansionCalculator.kt
+-packages/SystemUI/src/com/android/keyguard/KeyguardBiometricLockoutLogger.kt
+-packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
+-packages/SystemUI/src/com/android/keyguard/KeyguardListenQueue.kt
+-packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt
+-packages/SystemUI/src/com/android/keyguard/KeyguardUserSwitcherAnchor.kt
+-packages/SystemUI/src/com/android/keyguard/clock/ClockPalette.kt
+-packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+-packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/BootCompleteCache.kt
+-packages/SystemUI/src/com/android/systemui/BootCompleteCacheImpl.kt
+-packages/SystemUI/src/com/android/systemui/CameraAvailabilityListener.kt
+-packages/SystemUI/src/com/android/systemui/ChooserSelector.kt
+-packages/SystemUI/src/com/android/systemui/DarkReceiverImpl.kt
+-packages/SystemUI/src/com/android/systemui/DisplayCutoutBaseView.kt
+-packages/SystemUI/src/com/android/systemui/DualToneHandler.kt
+-packages/SystemUI/src/com/android/systemui/FaceScanningOverlay.kt
+-packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
+-packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.kt
+-packages/SystemUI/src/com/android/systemui/SystemUIInitializerFactory.kt
+-packages/SystemUI/src/com/android/systemui/SystemUIInitializerImpl.kt
+-packages/SystemUI/src/com/android/systemui/assist/AssistLogger.kt
+-packages/SystemUI/src/com/android/systemui/assist/AssistantInvocationEvent.kt
+-packages/SystemUI/src/com/android/systemui/assist/AssistantSessionEvent.kt
+-packages/SystemUI/src/com/android/systemui/backup/BackupHelper.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AlternateUdfpsTouchProvider.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceIconController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFaceView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricIconController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/DwellRippleShader.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/SidefpsController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsDrawable.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpDrawable.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherViewController.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsHapticsSimulator.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsOverlayParams.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsShell.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
+-packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/ActionReceiver.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcherStartable.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/BroadcastSender.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/PendingRemovalStore.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
+-packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
+-packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
+-packages/SystemUI/src/com/android/systemui/camera/CameraIntents.kt
+-packages/SystemUI/src/com/android/systemui/camera/CameraIntentsWrapper.kt
+-packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
+-packages/SystemUI/src/com/android/systemui/controls/ControlStatus.kt
+-packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLogger.kt
+-packages/SystemUI/src/com/android/systemui/controls/ControlsMetricsLoggerImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/ControlsServiceInfo.kt
+-packages/SystemUI/src/com/android/systemui/controls/CustomIconCache.kt
+-packages/SystemUI/src/com/android/systemui/controls/TooltipManager.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapper.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlInfo.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingController.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsController.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfiguration.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
+-packages/SystemUI/src/com/android/systemui/controls/controller/StatefulControlSubscriber.kt
+-packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
+-packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsFeatureEnabled.kt
+-packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsModule.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/AllModel.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsAnimations.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsEditingActivity.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsModel.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsProviderSelectorActivity.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestDialog.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ControlsRequestReceiver.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/FavoritesModel.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/ManagementPageIndicator.kt
+-packages/SystemUI/src/com/android/systemui/controls/management/StructureAdapter.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/Behavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ChallengeDialogs.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlViewHolder.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlWithState.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/CornerDrawable.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/RenderInfo.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/StatusBehavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/TemperatureControlBehavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ThumbnailBehavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ToggleBehavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
+-packages/SystemUI/src/com/android/systemui/controls/ui/TouchBehavior.kt
+-packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+-packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
+-packages/SystemUI/src/com/android/systemui/decor/DecorProviderFactory.kt
+-packages/SystemUI/src/com/android/systemui/decor/FaceScanningProviderFactory.kt
+-packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
+-packages/SystemUI/src/com/android/systemui/decor/PrivacyDotDecorProviderFactory.kt
+-packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderFactory.kt
+-packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
+-packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
+-packages/SystemUI/src/com/android/systemui/demomode/DemoModeAvailabilityTracker.kt
+-packages/SystemUI/src/com/android/systemui/demomode/DemoModeController.kt
+-packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
+-packages/SystemUI/src/com/android/systemui/doze/util/BurnInHelper.kt
+-packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
+-packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt
+-packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
+-packages/SystemUI/src/com/android/systemui/dump/DumpsysTableLogger.kt
+-packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
+-packages/SystemUI/src/com/android/systemui/dump/LogBufferFreezer.kt
+-packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.kt
+-packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
+-packages/SystemUI/src/com/android/systemui/flags/SystemPropertiesHelper.kt
+-packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt
+-packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt
+-packages/SystemUI/src/com/android/systemui/log/LogLevel.kt
+-packages/SystemUI/src/com/android/systemui/log/LogMessage.kt
+-packages/SystemUI/src/com/android/systemui/log/LogMessageImpl.kt
+-packages/SystemUI/src/com/android/systemui/log/LogcatEchoTracker.kt
+-packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt
+-packages/SystemUI/src/com/android/systemui/log/LogcatEchoTrackerProd.kt
+-packages/SystemUI/src/com/android/systemui/media/AnimationBindHandler.kt
+-packages/SystemUI/src/com/android/systemui/media/ColorSchemeTransition.kt
+-packages/SystemUI/src/com/android/systemui/media/GutsViewHolder.kt
+-packages/SystemUI/src/com/android/systemui/media/IlluminationDrawable.kt
+-packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt
+-packages/SystemUI/src/com/android/systemui/media/LightSourceDrawable.kt
+-packages/SystemUI/src/com/android/systemui/media/LocalMediaManagerFactory.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaCarouselControllerLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaData.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaFeatureFlag.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaFlags.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaHostStatesManager.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaProjectionCaptureTarget.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaScrollView.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaTimeoutLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaUiEventLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaViewHolder.kt
+-packages/SystemUI/src/com/android/systemui/media/MediaViewLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/MetadataAnimationHandler.kt
+-packages/SystemUI/src/com/android/systemui/media/RecommendationViewHolder.kt
+-packages/SystemUI/src/com/android/systemui/media/ResumeMediaBrowserLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/SeekBarObserver.kt
+-packages/SystemUI/src/com/android/systemui/media/SeekBarViewModel.kt
+-packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaData.kt
+-packages/SystemUI/src/com/android/systemui/media/SmartspaceMediaDataProvider.kt
+-packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt
+-packages/SystemUI/src/com/android/systemui/media/dagger/MediaProjectionModule.kt
+-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBroadcastDialogFactory.kt
+-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
+-packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogReceiver.kt
+-packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionCli.kt
+-packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManager.kt
+-packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerFactory.kt
+-packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesManager.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/ChipInfoCommon.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogger.kt
+-packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLogger.kt
+-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanel.kt
+-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
+-packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgePanelParams.kt
+-packages/SystemUI/src/com/android/systemui/power/BatteryStateSnapshot.kt
+-packages/SystemUI/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitor.kt
+-packages/SystemUI/src/com/android/systemui/privacy/MediaProjectionPrivacyItemMonitor.kt
+-packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipEvent.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyConfig.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogController.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogEvent.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
+-packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+-packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt
+-packages/SystemUI/src/com/android/systemui/qs/AutoAddTracker.kt
+-packages/SystemUI/src/com/android/systemui/qs/FgsManagerController.kt
+-packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
+-packages/SystemUI/src/com/android/systemui/qs/FooterActionsView.kt
+-packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt
+-packages/SystemUI/src/com/android/systemui/qs/QSEvents.kt
+-packages/SystemUI/src/com/android/systemui/qs/QSExpansionPathInterpolator.kt
+-packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt
+-packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt
+-packages/SystemUI/src/com/android/systemui/qs/QSUtils.kt
+-packages/SystemUI/src/com/android/systemui/qs/SideLabelTileLayout.kt
+-packages/SystemUI/src/com/android/systemui/qs/VisibilityChangedDispatcher.kt
+-packages/SystemUI/src/com/android/systemui/qs/carrier/CellSignalState.kt
+-packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.kt
+-packages/SystemUI/src/com/android/systemui/qs/external/CustomTileStatePersister.kt
+-packages/SystemUI/src/com/android/systemui/qs/external/QSExternalModule.kt
+-packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialog.kt
+-packages/SystemUI/src/com/android/systemui/qs/external/TileRequestDialogEventLogger.kt
+-packages/SystemUI/src/com/android/systemui/qs/external/TileServiceRequestController.kt
+-packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
+-packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt
+-packages/SystemUI/src/com/android/systemui/qs/tileimpl/IgnorableChildLinearLayout.kt
+-packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+-packages/SystemUI/src/com/android/systemui/qs/tiles/AlarmTile.kt
+-packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
+-packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
+-packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
+-packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
+-packages/SystemUI/src/com/android/systemui/ripple/RippleShaderUtilLibrary.kt
+-packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
+-packages/SystemUI/src/com/android/systemui/ripple/SdfShaderLibrary.kt
+-packages/SystemUI/src/com/android/systemui/screenshot/ImageCaptureImpl.kt
+-packages/SystemUI/src/com/android/systemui/screenshot/RequestProcessor.kt
+-packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt
+-packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicyImpl.kt
+-packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotProxyService.kt
+-packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseDialog.kt
+-packages/SystemUI/src/com/android/systemui/sensorprivacy/SensorUseStartedActivity.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserContentResolverProvider.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserContextProvider.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserFileManager.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserFileManagerImpl.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserTracker.kt
+-packages/SystemUI/src/com/android/systemui/settings/UserTrackerImpl.kt
+-packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessMirrorHandler.kt
+-packages/SystemUI/src/com/android/systemui/settings/brightness/MirroredBrightnessController.kt
+-packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManager.kt
+-packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
+-packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt
+-packages/SystemUI/src/com/android/systemui/shade/NPVCDownEventState.kt
+-packages/SystemUI/src/com/android/systemui/shade/NotifPanelEvents.kt
+-packages/SystemUI/src/com/android/systemui/shade/NotificationPanelUnfoldAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt
+-packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt
+-packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+-packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/SmartspacePrecondition.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/SmartspaceTargetFilter.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceModule.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/dagger/SmartspaceViewComponent.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/filters/LockscreenAndDreamTargetFilter.kt
+-packages/SystemUI/src/com/android/systemui/smartspace/preconditions/LockscreenPrecondition.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/AbstractLockscreenShadeTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBarWifiView.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/DisableFlagsLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/LightRevealScrim.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/LockScreenShadeOverScroller.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeKeyguardTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeScrimTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/NotificationClickNotifier.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/PulseExpansionHandler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScroller.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScroller.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/commandline/CommandRegistry.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/AccessPointController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/ConnectivityState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalControllerFactory.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileStatusTrackerFactory.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/SignalCallback.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiStatusTrackerFactory.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/core/StatusBarInitializer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/gesture/GenericGestureDetector.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureHandler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeStatusBarAwayGestureLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/gesture/TapGestureDetector.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/ConversationNotifications.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/FeedbackIcon.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/LaunchAnimationParameters.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManagerLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/ViewGroupFadeHelper.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListAttachState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipelineChoreographer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/PipelineDumper.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/SuppressedAttachState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolver.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DebugModeCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/dagger/CoordinatorsModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/BindEventManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/BindEventManagerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifStabilityManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTracker.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifEvent.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtender.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/DebugModeFilterProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/NotificationVisibilityProviderImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionHeaderVisibilityProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/provider/SectionStyleProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/MediaContainerController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGroupController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGutsViewListener.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGutsViewManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifRowController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifShadeEventSource.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewBarn.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotificationVisibilityProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderExtensions.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RootNodeController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDiffer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationSectionHeadersModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconBuilder.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/icon/IconManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/KeyguardNotificationVisibilityProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/NotificationPersonExtractor.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/people/ViewPipeline.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/dagger/RemoteInputViewModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/MediaContainerView.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationPriorityBucket.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ScreenOffAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHideIconsForBouncerManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLocationPublisher.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemBarAttributesListener.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarIconBlocklist.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallFlags.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelStateListener.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserInfoTracker.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherFeatureController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/ConnectivityInfoProcessor.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiActivityModel.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiNetworkModel.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiConstants.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryStateNotifier.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplyState.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/InflatedSmartReplyViewHolder.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisabler.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/VariableDateView.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/VariableDateViewController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/WalletController.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/WalletControllerImpl.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/RemoteInput.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/SmartRepliesInflationModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt
+-packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt
+-packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt
+-packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt
+-packages/SystemUI/src/com/android/systemui/tv/TVSystemUICoreStartableModule.kt
+-packages/SystemUI/src/com/android/systemui/unfold/FoldStateLogger.kt
+-packages/SystemUI/src/com/android/systemui/unfold/SysUIUnfoldModule.kt
+-packages/SystemUI/src/com/android/systemui/unfold/UnfoldLatencyTracker.kt
+-packages/SystemUI/src/com/android/systemui/unfold/UnfoldLightRevealOverlayAnimation.kt
+-packages/SystemUI/src/com/android/systemui/unfold/UnfoldProgressProvider.kt
+-packages/SystemUI/src/com/android/systemui/user/UserCreator.kt
+-packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
+-packages/SystemUI/src/com/android/systemui/user/UserSwitcherPopupMenu.kt
+-packages/SystemUI/src/com/android/systemui/user/UserSwitcherRootView.kt
+-packages/SystemUI/src/com/android/systemui/util/AsyncActivityLauncher.kt
+-packages/SystemUI/src/com/android/systemui/util/ColorUtil.kt
+-packages/SystemUI/src/com/android/systemui/util/ConvenienceExtensions.kt
+-packages/SystemUI/src/com/android/systemui/util/DelayableMarqueeTextView.kt
+-packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt
+-packages/SystemUI/src/com/android/systemui/util/InitializationChecker.kt
+-packages/SystemUI/src/com/android/systemui/util/LargeScreenUtils.kt
+-packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt
+-packages/SystemUI/src/com/android/systemui/util/NeverExactlyLinearLayout.kt
+-packages/SystemUI/src/com/android/systemui/util/NoRemeasureMotionLayout.kt
+-packages/SystemUI/src/com/android/systemui/util/PluralMessageFormater.kt
+-packages/SystemUI/src/com/android/systemui/util/RingerModeTracker.kt
+-packages/SystemUI/src/com/android/systemui/util/RingerModeTrackerImpl.kt
+-packages/SystemUI/src/com/android/systemui/util/RoundedCornerProgressDrawable.kt
+-packages/SystemUI/src/com/android/systemui/util/SafeMarqueeTextView.kt
+-packages/SystemUI/src/com/android/systemui/util/SparseArrayUtils.kt
+-packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt
+-packages/SystemUI/src/com/android/systemui/util/UserAwareController.kt
+-packages/SystemUI/src/com/android/systemui/util/WallpaperController.kt
+-packages/SystemUI/src/com/android/systemui/util/animation/AnimationUtil.kt
+-packages/SystemUI/src/com/android/systemui/util/animation/MeasurementInput.kt
+-packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayout.kt
+-packages/SystemUI/src/com/android/systemui/util/animation/TransitionLayoutController.kt
+-packages/SystemUI/src/com/android/systemui/util/animation/UniqueObjectHostView.kt
+-packages/SystemUI/src/com/android/systemui/util/collection/RingBuffer.kt
+-packages/SystemUI/src/com/android/systemui/util/concurrency/Execution.kt
+-packages/SystemUI/src/com/android/systemui/util/concurrency/PendingTasksContainer.kt
+-packages/SystemUI/src/com/android/systemui/util/drawable/DrawableSize.kt
+-packages/SystemUI/src/com/android/systemui/util/kotlin/CoroutinesModule.kt
+-packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt
+-packages/SystemUI/src/com/android/systemui/util/kotlin/IpcSerializer.kt
+-packages/SystemUI/src/com/android/systemui/util/kotlin/nullability.kt
+-packages/SystemUI/src/com/android/systemui/util/view/ViewUtil.kt
+-packages/SystemUI/src/com/android/systemui/util/wrapper/RotationPolicyWrapper.kt
+-packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialogReceiver.kt
+-packages/SystemUI/src/com/android/systemui/volume/VolumePanelFactory.kt
+-packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/BouncerPanelExpansionCalculatorTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardBiometricLockoutLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/KeyguardUserSwitcherAnchorTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/clock/ClockPaletteTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/clock/ViewPreviewerTest.kt
+-packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/BootCompleteCacheTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/ChooserSelectorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/DisplayCutoutBaseViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/InstanceIdSequenceFake.kt
+-packages/SystemUI/tests/src/com/android/systemui/ScreenDecorHwcLayerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/FontInterpolatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/GhostedViewLaunchAnimatorControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/battery/BatteryMeterViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthBiometricFingerprintViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricTestExtensions.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/SidefpsControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/broadcast/ActionReceiverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastSenderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/broadcast/PendingRemovalStoreTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/camera/CameraGestureHelperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/camera/CameraIntentsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/CustomIconCacheTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/AuxiliaryPersistenceWrapperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlActionCoordinatorImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsTileResourceConfigurationImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/DeletionJobServiceTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/controller/StatefulControlSubscriberTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/dagger/ControlsComponentTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/AllModelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/AppAdapterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsListingControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestDialogTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/ControlsRequestReceiverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/FavoritesModelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/management/TestControlsRequestDialog.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/ui/ControlViewHolderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/decor/OverlayWindowTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/decor/PrivacyDotDecorProviderFactoryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerDecorProviderFactoryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/dump/DumpsysTableLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferFreezerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt
+-packages/SystemUI/tests/src/com/android/systemui/dump/LogEulogizerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsDebugTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/flags/FlagManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/lifecycle/InstantTaskExecutorRule.kt
+-packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/AnimationBindHandlerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/ColorSchemeTransitionTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaTestUtils.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MediaTimeoutListenerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/MetadataAnimationHandlerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/ResumeMediaBrowserTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/SeekBarObserverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/SeekBarViewModelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/SmartspaceMediaDataTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderUiEventLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/FloatingRotationButtonPositionCalculatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/AppOpsPrivacyItemMonitorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyChipBuilderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyConfigFlagsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/HeaderPrivacyIconsControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSContainerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentDisableFlagsLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelSwitchToParentTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/SettingObserverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/carrier/CellSignalStateTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileStatePersisterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/external/CustomTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/external/TileRequestDialogEventLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/external/TileRequestDialogTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServiceRequestControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileViewImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/ResourceIconTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/TilesStatesTextTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AirplaneModeTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/AlarmTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BatterySaverTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/BluetoothTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/CameraToggleTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/LocationTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/MicrophoneToggleTileTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/ripple/RippleViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/screenrecord/ScreenRecordDialogTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/screenshot/ImageCaptureImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/screenshot/RequestProcessorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/settings/UserFileManagerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/settings/UserTrackerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/CombinedShadeHeaderConstraintsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldConstantTranslateAnimatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/animation/UnfoldMoveFromCenterAnimatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/navigationbar/RegionSamplingHelperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/regionsampling/RegionSamplingInstanceTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/rotation/RotationButtonControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/shared/system/UncaughtExceptionPreHandlerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenAndDreamTargetFilterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/smartspace/LockscreenPreconditionTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/DisableFlagsLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/LightRevealScrimTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/SingleShadeLockScreenOverScrollerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/SplitShadeLockScreenOverScrollerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarStateEventTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/VibratorHelperTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/AccessPointControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/gesture/GenericGestureDetectorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifLiveDataStoreImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineChoreographerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/DataStoreCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SmartspaceDedupingCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionInconsistencyTrackerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/notifcollection/SelfTrackingLifetimeExtenderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/provider/VisualStabilityProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/IconManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/MediaContainerViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ConfigurationControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/FoldStateListenerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxAppearanceCalculatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LetterboxBackgroundProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SystemBarAttributesListenerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallChronometerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManagerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ClockTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceControlsControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FlashlightControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputQuickSettingsDisablerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SafetyControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/WalletControllerImplTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfigTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/updates/DeviceFoldStateProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/util/FoldableTestUtils.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/util/ScaleAwareUnfoldProgressProviderTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/unfold/util/TestFoldStateProvider.kt
+-packages/SystemUI/tests/src/com/android/systemui/usb/UsbPermissionActivityTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/user/UserCreatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/user/UserSwitcherActivityTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/FakeSharedPreferencesTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/FloatingContentCoordinatorTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/ListenerSetTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/RingerModeLiveDataTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/WallpaperControllerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/animation/AnimationUtilTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/collection/RingBufferTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/drawable/DrawableSizeTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/kotlin/IpcSerializerTest.kt
+-packages/SystemUI/tests/src/com/android/systemui/util/view/ViewUtilTest.kt
+-packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt
+-packages/SystemUI/tests/utils/src/com/android/systemui/flags/FakeFeatureFlags.kt
+-packages/SystemUI/tests/utils/src/com/android/systemui/util/FakeSharedPreferences.kt
+-packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldSharedModule.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/UnfoldTransitionFactory.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/ScreenSizeFoldProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/compat/SizeScreenStatusProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/config/ResourceUnfoldTransitionConfig.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldBackground.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/dagger/UnfoldMain.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/progress/PhysicsBasedUnfoldTransitionProgressProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/DeviceFoldStateProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/FoldStateProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/hinge/HingeSensorAngleProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/updates/screen/ScreenStatusProvider.kt
+-packages/SystemUI/unfold/src/com/android/systemui/unfold/util/ScaleAwareTransitionProgressProvider.kt
diff --git a/packages/SystemUI/res-keyguard/values/strings.xml b/packages/SystemUI/res-keyguard/values/strings.xml
index 8fa22048cd97..d90156d451c7 100644
--- a/packages/SystemUI/res-keyguard/values/strings.xml
+++ b/packages/SystemUI/res-keyguard/values/strings.xml
@@ -217,7 +217,7 @@
the force lock button. [CHAR LIMIT=80] -->
<string name="kg_prompt_reason_user_request">Device was locked manually</string>
- <!-- Face hint message when finger was not recognized. [CHAR LIMIT=20] -->
+ <!-- Face hint message when face was not recognized. [CHAR LIMIT=20] -->
<string name="kg_face_not_recognized">Not recognized</string>
<!-- Error message indicating that the camera privacy sensor has been turned on [CHAR LIMIT=53] -->
diff --git a/packages/SystemUI/res/layout/dream_overlay_media_entry_chip.xml b/packages/SystemUI/res/layout/dream_overlay_media_entry_chip.xml
new file mode 100644
index 000000000000..50f3ffcaf968
--- /dev/null
+++ b/packages/SystemUI/res/layout/dream_overlay_media_entry_chip.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+-->
+<ImageView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/media_entry_chip"
+ android:layout_height="@dimen/keyguard_affordance_fixed_height"
+ android:layout_width="@dimen/keyguard_affordance_fixed_width"
+ android:layout_gravity="bottom|start"
+ android:scaleType="center"
+ android:tint="?android:attr/textColorPrimary"
+ android:src="@drawable/ic_music_note"
+ android:background="@drawable/keyguard_bottom_affordance_bg"
+ android:layout_marginStart="@dimen/keyguard_affordance_horizontal_offset"
+ android:layout_marginBottom="@dimen/keyguard_affordance_vertical_offset"
+ android:contentDescription="@string/controls_media_title" />
diff --git a/packages/SystemUI/res/layout/media_ttt_chip.xml b/packages/SystemUI/res/layout/media_ttt_chip.xml
index d88680669fe0..ae8e38e2634b 100644
--- a/packages/SystemUI/res/layout/media_ttt_chip.xml
+++ b/packages/SystemUI/res/layout/media_ttt_chip.xml
@@ -16,7 +16,7 @@
<!-- Wrap in a frame layout so that we can update the margins on the inner layout. (Since this view
is the root view of a window, we cannot change the root view's margins.) -->
<!-- Alphas start as 0 because the view will be animated in. -->
-<FrameLayout
+<com.android.systemui.media.taptotransfer.sender.MediaTttChipRootView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:id="@+id/media_ttt_sender_chip"
@@ -97,4 +97,4 @@
/>
</LinearLayout>
-</FrameLayout>
+</com.android.systemui.media.taptotransfer.sender.MediaTttChipRootView>
diff --git a/packages/SystemUI/res/layout/sidefps_view.xml b/packages/SystemUI/res/layout/sidefps_view.xml
index 921f78830981..73050c253d72 100644
--- a/packages/SystemUI/res/layout/sidefps_view.xml
+++ b/packages/SystemUI/res/layout/sidefps_view.xml
@@ -23,4 +23,4 @@
app:lottie_autoPlay="true"
app:lottie_loop="true"
app:lottie_rawRes="@raw/sfps_pulse"
- android:contentDescription="@string/accessibility_fingerprint_label"/>
+ android:importantForAccessibility="no"/> \ No newline at end of file
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index dca5ea836fa4..f88f46f2a3c8 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -131,7 +131,11 @@
<!-- For StatusIconContainer to tag its icon views -->
<item type="id" name="status_bar_view_state_tag" />
+ <!-- Default display cutout on the physical top of screen -->
<item type="id" name="display_cutout" />
+ <item type="id" name="display_cutout_left" />
+ <item type="id" name="display_cutout_right" />
+ <item type="id" name="display_cutout_bottom" />
<item type="id" name="row_tag_for_content_view" />
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c7b2ff34c55f..d5a744bc29d6 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -389,6 +389,10 @@
<string name="fingerprint_dialog_use_fingerprint_instead">Can\u2019t recognize face. Use fingerprint instead.</string>
<!-- Message shown to inform the user a face cannot be recognized and fingerprint should instead be used.[CHAR LIMIT=50] -->
<string name="keyguard_face_failed_use_fp">@string/fingerprint_dialog_use_fingerprint_instead</string>
+ <!-- Message shown to inform the user a face cannot be recognized. [CHAR LIMIT=25] -->
+ <string name="keyguard_face_failed">Can\u2019t recognize face</string>
+ <!-- Message shown to suggest using fingerprint sensor to authenticate after another biometric failed. [CHAR LIMIT=25] -->
+ <string name="keyguard_suggest_fingerprint">Use fingerprint instead</string>
<!-- Content description of the bluetooth icon when connected for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_bluetooth_connected">Bluetooth connected.</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 3517d22ae50d..d0baf3dad79d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -89,7 +89,7 @@ import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.statusbar.policy.UserSwitcherController.BaseUserAdapter;
-import com.android.systemui.statusbar.policy.UserSwitcherController.UserRecord;
+import com.android.systemui.user.data.source.UserRecord;
import com.android.systemui.util.settings.GlobalSettings;
import java.util.ArrayList;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index e1957c09fef5..93175e19a287 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -418,6 +418,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, state);
getCurrentSecurityController().onResume(reason);
+ updateSideFpsVisibility();
}
mView.onResume(
mSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser()),
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 4c400a81024f..2e13903814a5 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -72,6 +72,7 @@ import com.android.settingslib.Utils;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.decor.CutoutDecorProviderFactory;
import com.android.systemui.decor.DecorProvider;
import com.android.systemui.decor.DecorProviderFactory;
import com.android.systemui.decor.DecorProviderKt;
@@ -118,6 +119,13 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
private static final boolean VERBOSE = false;
static final boolean DEBUG_COLOR = DEBUG_SCREENSHOT_ROUNDED_CORNERS;
+ private static final int[] DISPLAY_CUTOUT_IDS = {
+ R.id.display_cutout,
+ R.id.display_cutout_left,
+ R.id.display_cutout_right,
+ R.id.display_cutout_bottom
+ };
+
private DisplayManager mDisplayManager;
@VisibleForTesting
protected boolean mIsRegistered;
@@ -139,13 +147,11 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
protected RoundedCornerResDelegate mRoundedCornerResDelegate;
@VisibleForTesting
protected DecorProviderFactory mRoundedCornerFactory;
+ private CutoutDecorProviderFactory mCutoutFactory;
private int mProviderRefreshToken = 0;
@VisibleForTesting
protected OverlayWindow[] mOverlays = null;
@VisibleForTesting
- @Nullable
- DisplayCutoutView[] mCutoutViews;
- @VisibleForTesting
ViewGroup mScreenDecorHwcWindow;
@VisibleForTesting
ScreenDecorHwcLayer mScreenDecorHwcLayer;
@@ -187,18 +193,19 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
return;
}
- if (mCutoutViews == null) {
- Log.w(TAG, "DisplayCutoutView not initialized onApplyCameraProtection");
- return;
- }
-
- // Show the extra protection around the front facing camera if necessary
- for (DisplayCutoutView dcv : mCutoutViews) {
- // Check Null since not all mCutoutViews[pos] be inflated at the meanwhile
- if (dcv != null) {
- dcv.setProtection(protectionPath, bounds);
- dcv.enableShowProtection(true);
+ int setProtectionCnt = 0;
+ for (int id: DISPLAY_CUTOUT_IDS) {
+ final View view = getOverlayView(id);
+ if (!(view instanceof DisplayCutoutView)) {
+ continue;
}
+ ++setProtectionCnt;
+ final DisplayCutoutView dcv = (DisplayCutoutView) view;
+ dcv.setProtection(protectionPath, bounds);
+ dcv.enableShowProtection(true);
+ }
+ if (setProtectionCnt == 0) {
+ Log.e(TAG, "CutoutView not initialized showCameraProtection");
}
}
@@ -219,16 +226,17 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
return;
}
- if (mCutoutViews == null) {
- Log.w(TAG, "DisplayCutoutView not initialized onHideCameraProtection");
- return;
- }
- // Go back to the regular anti-aliasing
- for (DisplayCutoutView dcv : mCutoutViews) {
- // Check Null since not all mCutoutViews[pos] be inflated at the meanwhile
- if (dcv != null) {
- dcv.enableShowProtection(false);
+ int setProtectionCnt = 0;
+ for (int id: DISPLAY_CUTOUT_IDS) {
+ final View view = getOverlayView(id);
+ if (!(view instanceof DisplayCutoutView)) {
+ continue;
}
+ ++setProtectionCnt;
+ ((DisplayCutoutView) view).enableShowProtection(false);
+ }
+ if (setProtectionCnt == 0) {
+ Log.e(TAG, "CutoutView not initialized hideCameraProtection");
}
}
@@ -335,6 +343,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
decorProviders.addAll(mFaceScanningFactory.getProviders());
if (!hasHwLayer) {
decorProviders.addAll(mRoundedCornerFactory.getProviders());
+ decorProviders.addAll(mCutoutFactory.getProviders());
}
return decorProviders;
}
@@ -379,6 +388,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
mRoundedCornerResDelegate.setPhysicalPixelDisplaySizeRatio(
getPhysicalPixelDisplaySizeRatio());
mRoundedCornerFactory = new RoundedCornerDecorProviderFactory(mRoundedCornerResDelegate);
+ mCutoutFactory = getCutoutFactory();
mHwcScreenDecorationSupport = mContext.getDisplay().getDisplayDecorationSupport();
updateHwLayerRoundedCornerDrawable();
setupDecorations();
@@ -483,18 +493,13 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
if (needToUpdateProviderViews) {
updateOverlayProviderViews(null);
} else {
- updateOverlayProviderViews(new Integer[] { mFaceScanningViewId });
- }
-
- if (mCutoutViews != null) {
- final int size = mCutoutViews.length;
- for (int i = 0; i < size; i++) {
- final DisplayCutoutView cutoutView = mCutoutViews[i];
- if (cutoutView == null) {
- continue;
- }
- cutoutView.onDisplayChanged(newUniqueId);
- }
+ updateOverlayProviderViews(new Integer[] {
+ mFaceScanningViewId,
+ R.id.display_cutout,
+ R.id.display_cutout_left,
+ R.id.display_cutout_right,
+ R.id.display_cutout_bottom,
+ });
}
if (mScreenDecorHwcLayer != null) {
@@ -507,8 +512,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
updateConfiguration();
}
+ @VisibleForTesting
@Nullable
- private View getOverlayView(@IdRes int id) {
+ View getOverlayView(@IdRes int id) {
if (mOverlays == null) {
return null;
}
@@ -565,18 +571,18 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
removeHwcOverlay();
}
- final DisplayCutout cutout = getCutout();
+ boolean[] hasCreatedOverlay = new boolean[BOUNDS_POSITION_LENGTH];
final boolean shouldOptimizeVisibility = shouldOptimizeVisibility();
+ Integer bound;
+ while ((bound = DecorProviderKt.getProperBound(decorProviders)) != null) {
+ hasCreatedOverlay[bound] = true;
+ Pair<List<DecorProvider>, List<DecorProvider>> pair =
+ DecorProviderKt.partitionAlignedBound(decorProviders, bound);
+ decorProviders = pair.getSecond();
+ createOverlay(bound, pair.getFirst(), shouldOptimizeVisibility);
+ }
for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
- if (shouldShowSwLayerCutout(i, cutout)
- || shouldShowSwLayerFaceScan(i, cutout)
- || shouldShowSwLayerRoundedCorner(i, cutout)
- || shouldShowSwLayerPrivacyDot(i, cutout)) {
- Pair<List<DecorProvider>, List<DecorProvider>> pair =
- DecorProviderKt.partitionAlignedBound(decorProviders, i);
- decorProviders = pair.getSecond();
- createOverlay(i, pair.getFirst(), shouldOptimizeVisibility);
- } else {
+ if (!hasCreatedOverlay[i]) {
removeOverlay(i);
}
}
@@ -639,9 +645,10 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
}
}
- @VisibleForTesting
- DisplayCutout getCutout() {
- return mContext.getDisplay().getCutout();
+ // For unit test to override
+ protected CutoutDecorProviderFactory getCutoutFactory() {
+ return new CutoutDecorProviderFactory(mContext.getResources(),
+ mContext.getDisplay());
}
@VisibleForTesting
@@ -731,16 +738,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
overlayView.setAlpha(0);
overlayView.setForceDarkAllowed(false);
- // Only show cutout in mOverlays when hwc doesn't support screen decoration
- if (mHwcScreenDecorationSupport == null) {
- if (mCutoutViews == null) {
- mCutoutViews = new DisplayCutoutView[BOUNDS_POSITION_LENGTH];
- }
- mCutoutViews[pos] = new DisplayCutoutView(mContext, pos);
- overlayView.addView(mCutoutViews[pos]);
- mCutoutViews[pos].updateRotation(mRotation);
- }
-
mWindowManager.addView(overlayView, getWindowLayoutParams(pos));
overlayView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@@ -920,6 +917,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
}
private void setupCameraListener() {
+ // TODO(b/238143614) Support dual screen camera protection
Resources res = mContext.getResources();
boolean enabled = res.getBoolean(R.bool.config_enableDisplayCutoutProtection);
if (enabled) {
@@ -948,27 +946,12 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
mTintColor = Color.RED;
}
- if (mOverlays == null) {
- return;
- }
-
- for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
- if (mOverlays[i] == null) {
- continue;
- }
- final ViewGroup overlayView = mOverlays[i].getRootView();
- final int size = overlayView.getChildCount();
- View child;
- for (int j = 0; j < size; j++) {
- child = overlayView.getChildAt(j);
- if (child instanceof DisplayCutoutView && child.getId() == R.id.display_cutout) {
- ((DisplayCutoutView) child).setColor(mTintColor);
- }
- }
- }
-
updateOverlayProviderViews(new Integer[] {
mFaceScanningViewId,
+ R.id.display_cutout,
+ R.id.display_cutout_left,
+ R.id.display_cutout_right,
+ R.id.display_cutout_bottom,
R.id.rounded_corner_top_left,
R.id.rounded_corner_top_right,
R.id.rounded_corner_bottom_left,
@@ -1093,15 +1076,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
updateHwLayerRoundedCornerDrawable();
}
updateLayoutParams();
- // update cutout view rotation
- if (mCutoutViews != null) {
- for (final DisplayCutoutView cutoutView: mCutoutViews) {
- if (cutoutView == null) {
- continue;
- }
- cutoutView.updateRotation(mRotation);
- }
- }
// update all provider views inside overlay
updateOverlayProviderViews(null);
@@ -1120,46 +1094,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
return mRoundedCornerFactory.getHasProviders();
}
- private boolean isDefaultShownOverlayPos(@BoundsPosition int pos,
- @Nullable DisplayCutout cutout) {
- // for cutout is null or cutout with only waterfall.
- final boolean emptyBoundsOrWaterfall = cutout == null || cutout.isBoundsEmpty();
- // Shows rounded corner on left and right overlays only when there is no top or bottom
- // cutout.
- final int rotatedTop = getBoundPositionFromRotation(BOUNDS_POSITION_TOP, mRotation);
- final int rotatedBottom = getBoundPositionFromRotation(BOUNDS_POSITION_BOTTOM, mRotation);
- if (emptyBoundsOrWaterfall || !cutout.getBoundingRectsAll()[rotatedTop].isEmpty()
- || !cutout.getBoundingRectsAll()[rotatedBottom].isEmpty()) {
- return pos == BOUNDS_POSITION_TOP || pos == BOUNDS_POSITION_BOTTOM;
- } else {
- return pos == BOUNDS_POSITION_LEFT || pos == BOUNDS_POSITION_RIGHT;
- }
- }
-
- private boolean shouldShowSwLayerRoundedCorner(@BoundsPosition int pos,
- @Nullable DisplayCutout cutout) {
- return hasRoundedCorners() && isDefaultShownOverlayPos(pos, cutout)
- && mHwcScreenDecorationSupport == null;
- }
-
- private boolean shouldShowSwLayerPrivacyDot(@BoundsPosition int pos,
- @Nullable DisplayCutout cutout) {
- return isPrivacyDotEnabled() && isDefaultShownOverlayPos(pos, cutout);
- }
-
- private boolean shouldShowSwLayerFaceScan(@BoundsPosition int pos,
- @Nullable DisplayCutout cutout) {
- return mFaceScanningFactory.getHasProviders() && isDefaultShownOverlayPos(pos, cutout);
- }
-
- private boolean shouldShowSwLayerCutout(@BoundsPosition int pos,
- @Nullable DisplayCutout cutout) {
- final Rect[] bounds = cutout == null ? null : cutout.getBoundingRectsAll();
- final int rotatedPos = getBoundPositionFromRotation(pos, mRotation);
- return (bounds != null && !bounds[rotatedPos].isEmpty()
- && mHwcScreenDecorationSupport == null);
- }
-
private boolean shouldOptimizeVisibility() {
return (isPrivacyDotEnabled() || mFaceScanningFactory.getHasProviders())
&& (mHwcScreenDecorationSupport != null
@@ -1168,7 +1102,7 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
}
private boolean shouldDrawCutout() {
- return shouldDrawCutout(mContext);
+ return mCutoutFactory.getHasProviders();
}
static boolean shouldDrawCutout(Context context) {
@@ -1284,7 +1218,6 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
paint.setColor(mColor);
paint.setStyle(Paint.Style.FILL);
- setId(R.id.display_cutout);
if (DEBUG) {
getViewTreeObserver().addOnDrawListener(() -> Log.i(TAG,
getWindowTitleByPos(pos) + " drawn in rot " + mRotation));
@@ -1292,6 +1225,9 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
}
public void setColor(int color) {
+ if (color == mColor) {
+ return;
+ }
mColor = color;
paint.setColor(mColor);
invalidate();
@@ -1299,6 +1235,12 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
@Override
public void updateRotation(int rotation) {
+ // updateRotation() is called inside CutoutDecorProviderImpl::onReloadResAndMeasure()
+ // during onDisplayChanged. In order to prevent reloading cutout info in super class,
+ // check mRotation at first
+ if (rotation == mRotation) {
+ return;
+ }
mRotation = rotation;
super.updateRotation(rotation);
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 84e1c3d4c8f0..436b756ea0cb 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -129,6 +129,8 @@ public class AuthContainerView extends LinearLayout
private final Set<Integer> mFailedModalities = new HashSet<Integer>();
private final @Background DelayableExecutor mBackgroundExecutor;
+ private int mOrientation;
+ private boolean mSkipFirstLostFocus = false;
// Non-null only if the dialog is in the act of dismissing and has not sent the reason yet.
@Nullable @AuthDialogCallback.DismissedReason private Integer mPendingCallbackReason;
@@ -441,6 +443,12 @@ public class AuthContainerView extends LinearLayout
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
if (!hasWindowFocus) {
+ //it's a workaround to avoid closing BP incorrectly
+ //BP gets a onWindowFocusChanged(false) and then gets a onWindowFocusChanged(true)
+ if (mSkipFirstLostFocus) {
+ mSkipFirstLostFocus = false;
+ return;
+ }
Log.v(TAG, "Lost window focus, dismissing the dialog");
animateAway(AuthDialogCallback.DISMISSED_USER_CANCELED);
}
@@ -450,6 +458,9 @@ public class AuthContainerView extends LinearLayout
public void onAttachedToWindow() {
super.onAttachedToWindow();
+ //save the first orientation
+ mOrientation = getResources().getConfiguration().orientation;
+
mWakefulnessLifecycle.addObserver(this);
if (Utils.isBiometricAllowed(mConfig.mPromptInfo)) {
@@ -621,6 +632,12 @@ public class AuthContainerView extends LinearLayout
if (mBiometricView != null) {
mBiometricView.restoreState(savedState);
}
+
+ if (savedState != null) {
+ mSkipFirstLostFocus = savedState.getBoolean(
+ AuthDialog.KEY_BIOMETRIC_ORIENTATION_CHANGED);
+ }
+
wm.addView(this, getLayoutParams(mWindowToken, mConfig.mPromptInfo.getTitle()));
}
@@ -640,30 +657,50 @@ public class AuthContainerView extends LinearLayout
@Override
public void onAuthenticationSucceeded(@Modality int modality) {
- mBiometricView.onAuthenticationSucceeded(modality);
+ if (mBiometricView != null) {
+ mBiometricView.onAuthenticationSucceeded(modality);
+ } else {
+ Log.e(TAG, "onAuthenticationSucceeded(): mBiometricView is null");
+ }
}
@Override
public void onAuthenticationFailed(@Modality int modality, String failureReason) {
- mFailedModalities.add(modality);
- mBiometricView.onAuthenticationFailed(modality, failureReason);
+ if (mBiometricView != null) {
+ mFailedModalities.add(modality);
+ mBiometricView.onAuthenticationFailed(modality, failureReason);
+ } else {
+ Log.e(TAG, "onAuthenticationFailed(): mBiometricView is null");
+ }
}
@Override
public void onHelp(@Modality int modality, String help) {
- mBiometricView.onHelp(modality, help);
+ if (mBiometricView != null) {
+ mBiometricView.onHelp(modality, help);
+ } else {
+ Log.e(TAG, "onHelp(): mBiometricView is null");
+ }
}
@Override
public void onError(@Modality int modality, String error) {
- mBiometricView.onError(modality, error);
+ if (mBiometricView != null) {
+ mBiometricView.onError(modality, error);
+ } else {
+ Log.e(TAG, "onError(): mBiometricView is null");
+ }
}
@Override
public void onPointerDown() {
- if (mBiometricView.onPointerDown(mFailedModalities)) {
- Log.d(TAG, "retrying failed modalities (pointer down)");
- mBiometricCallback.onAction(AuthBiometricView.Callback.ACTION_BUTTON_TRY_AGAIN);
+ if (mBiometricView != null) {
+ if (mBiometricView.onPointerDown(mFailedModalities)) {
+ Log.d(TAG, "retrying failed modalities (pointer down)");
+ mBiometricCallback.onAction(AuthBiometricView.Callback.ACTION_BUTTON_TRY_AGAIN);
+ }
+ } else {
+ Log.e(TAG, "onPointerDown(): mBiometricView is null");
}
}
@@ -677,6 +714,10 @@ public class AuthContainerView extends LinearLayout
mBiometricView != null && mCredentialView == null);
outState.putBoolean(AuthDialog.KEY_CREDENTIAL_SHOWING, mCredentialView != null);
+ if (mOrientation != getResources().getConfiguration().orientation) {
+ outState.putBoolean(AuthDialog.KEY_BIOMETRIC_ORIENTATION_CHANGED, true);
+ }
+
if (mBiometricView != null) {
mBiometricView.onSaveState(outState);
}
@@ -694,7 +735,11 @@ public class AuthContainerView extends LinearLayout
@Override
public void animateToCredentialUI() {
- mBiometricView.startTransitionToCredentialUI();
+ if (mBiometricView != null) {
+ mBiometricView.startTransitionToCredentialUI();
+ } else {
+ Log.e(TAG, "animateToCredentialUI(): mBiometricView is null");
+ }
}
void animateAway(@AuthDialogCallback.DismissedReason int reason) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 282f25104c44..6b3f13452326 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -19,6 +19,9 @@ package com.android.systemui.biometrics;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -599,7 +602,6 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
@Background DelayableExecutor bgExecutor) {
super(context);
mExecution = execution;
- mWakefulnessLifecycle = wakefulnessLifecycle;
mUserManager = userManager;
mLockPatternUtils = lockPatternUtils;
mHandler = handler;
@@ -625,11 +627,24 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
return Unit.INSTANCE;
});
+ mWakefulnessLifecycle = wakefulnessLifecycle;
+ mWakefulnessLifecycle.addObserver(new WakefulnessLifecycle.Observer() {
+ @Override
+ public void onFinishedWakingUp() {
+ notifyDozeChanged(mStatusBarStateController.isDozing(), WAKEFULNESS_AWAKE);
+ }
+
+ @Override
+ public void onStartedGoingToSleep() {
+ notifyDozeChanged(mStatusBarStateController.isDozing(), WAKEFULNESS_GOING_TO_SLEEP);
+ }
+ });
+
mStatusBarStateController = statusBarStateController;
mStatusBarStateController.addCallback(new StatusBarStateController.StateListener() {
@Override
public void onDozingChanged(boolean isDozing) {
- notifyDozeChanged(isDozing);
+ notifyDozeChanged(isDozing, wakefulnessLifecycle.getWakefulness());
}
});
@@ -738,13 +753,16 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
@Override
public void setBiometicContextListener(IBiometricContextListener listener) {
mBiometricContextListener = listener;
- notifyDozeChanged(mStatusBarStateController.isDozing());
+ notifyDozeChanged(mStatusBarStateController.isDozing(),
+ mWakefulnessLifecycle.getWakefulness());
}
- private void notifyDozeChanged(boolean isDozing) {
+ private void notifyDozeChanged(boolean isDozing,
+ @WakefulnessLifecycle.Wakefulness int wakefullness) {
if (mBiometricContextListener != null) {
try {
- mBiometricContextListener.onDozeChanged(isDozing);
+ final boolean isAwake = wakefullness == WAKEFULNESS_AWAKE;
+ mBiometricContextListener.onDozeChanged(isDozing, isAwake);
} catch (RemoteException e) {
Log.w(TAG, "failed to notify initial doze state");
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
index 51f39b358659..cd0fc3737594 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
@@ -48,6 +48,8 @@ public interface AuthDialog extends Dumpable {
String KEY_BIOMETRIC_SENSOR_TYPE = "sensor_type";
String KEY_BIOMETRIC_SENSOR_PROPS = "sensor_props";
+ String KEY_BIOMETRIC_ORIENTATION_CHANGED = "orientation_changed";
+
int SIZE_UNKNOWN = 0;
/**
* Minimal UI, showing only biometric icon.
diff --git a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
index 4fe2dd810a08..e2ef2477c836 100644
--- a/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/camera/CameraGestureHelper.kt
@@ -33,7 +33,6 @@ import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.ActivityIntentHelper
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.shade.NotificationPanelViewController
import com.android.systemui.shared.system.ActivityManagerKt.isInForeground
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.phone.CentralSurfaces
@@ -117,7 +116,7 @@ class CameraGestureHelper @Inject constructor(
)
} catch (e: RemoteException) {
Log.w(
- NotificationPanelViewController.TAG,
+ "CameraGestureHelper",
"Unable to start camera activity",
e
)
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt b/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
index da675de2b9ec..dec3d6b679c2 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/charging/WiredChargingRippleController.kt
@@ -200,8 +200,7 @@ class WiredChargingRippleController @Inject constructor(
}
private fun updateRippleColor() {
- rippleView.setColor(
- Utils.getColorAttr(context, android.R.attr.colorAccent).defaultColor)
+ rippleView.setColor(Utils.getColorAttr(context, android.R.attr.colorAccent).defaultColor)
}
inner class ChargingRippleCommand : Command {
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
index 08393386c27f..c0cc6b41aafd 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
@@ -30,13 +30,12 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
-import androidx.core.graphics.ColorUtils;
-
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.ripple.RippleShader.RippleShape;
import com.android.systemui.ripple.RippleView;
+import com.android.systemui.ripple.RippleViewKt;
import java.text.NumberFormat;
@@ -143,16 +142,15 @@ final class WirelessChargingLayout extends FrameLayout {
mRippleView = findViewById(R.id.wireless_charging_ripple);
mRippleView.setupShader(rippleShape);
+ int color = Utils.getColorAttr(mRippleView.getContext(),
+ android.R.attr.colorAccent).getDefaultColor();
if (mRippleView.getRippleShape() == RippleShape.ROUNDED_BOX) {
mRippleView.setDuration(ROUNDED_BOX_RIPPLE_ANIMATION_DURATION);
mRippleView.setSparkleStrength(0.22f);
- int color = Utils.getColorAttr(mRippleView.getContext(),
- android.R.attr.colorAccent).getDefaultColor();
- mRippleView.setColor(ColorUtils.setAlphaComponent(color, 28));
+ mRippleView.setColor(color, 28);
} else {
mRippleView.setDuration(CIRCLE_RIPPLE_ANIMATION_DURATION);
- mRippleView.setColor(Utils.getColorAttr(mRippleView.getContext(),
- android.R.attr.colorAccent).getDefaultColor());
+ mRippleView.setColor(color, RippleViewKt.RIPPLE_DEFAULT_ALPHA);
}
OnAttachStateChangeListener listener = new OnAttachStateChangeListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt b/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt
new file mode 100644
index 000000000000..cbed21cf65d6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderFactory.kt
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.decor
+
+import android.content.res.Resources
+import android.util.Log
+import android.view.Display
+import android.view.DisplayCutout
+import android.view.DisplayInfo
+
+class CutoutDecorProviderFactory constructor(
+ private val res: Resources,
+ private val display: Display?,
+) : DecorProviderFactory() {
+
+ val displayInfo = DisplayInfo()
+
+ override val hasProviders: Boolean
+ get() {
+ display?.getDisplayInfo(displayInfo) ?: run {
+ Log.w(TAG, "display is null, can't update displayInfo")
+ }
+ return DisplayCutout.getFillBuiltInDisplayCutout(res, displayInfo.uniqueId)
+ }
+
+ override val providers: List<DecorProvider>
+ get() {
+ if (!hasProviders) {
+ return emptyList()
+ }
+
+ return ArrayList<DecorProvider>().also { list ->
+ // We need to update displayInfo before using it, but it has already updated during
+ // accessing hasProviders field
+ displayInfo.displayCutout?.getBoundBaseOnCurrentRotation()?.let { bounds ->
+ for (bound in bounds) {
+ list.add(
+ CutoutDecorProviderImpl(bound.baseOnRotation0(displayInfo.rotation))
+ )
+ }
+ }
+ }
+ }
+}
+
+private const val TAG = "CutoutDecorProviderFactory"
diff --git a/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt
new file mode 100644
index 000000000000..991b54e8035e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/decor/CutoutDecorProviderImpl.kt
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.decor
+
+import android.content.Context
+import android.view.DisplayCutout
+import android.view.Surface
+import android.view.View
+import android.view.ViewGroup
+import com.android.systemui.R
+import com.android.systemui.ScreenDecorations.DisplayCutoutView
+
+class CutoutDecorProviderImpl(
+ @DisplayCutout.BoundsPosition override val alignedBound: Int
+) : BoundDecorProvider() {
+
+ override val viewId: Int = when (alignedBound) {
+ DisplayCutout.BOUNDS_POSITION_TOP -> R.id.display_cutout
+ DisplayCutout.BOUNDS_POSITION_LEFT -> R.id.display_cutout_left
+ DisplayCutout.BOUNDS_POSITION_RIGHT -> R.id.display_cutout_right
+ else -> R.id.display_cutout_bottom
+ }
+
+ override fun inflateView(
+ context: Context,
+ parent: ViewGroup,
+ @Surface.Rotation rotation: Int,
+ tintColor: Int
+ ): View {
+ return DisplayCutoutView(context, alignedBound).also { view ->
+ view.id = viewId
+ view.setColor(tintColor)
+ parent.addView(view)
+ view.updateRotation(rotation)
+ }
+ }
+
+ override fun onReloadResAndMeasure(
+ view: View,
+ reloadToken: Int,
+ @Surface.Rotation rotation: Int,
+ tintColor: Int,
+ displayUniqueId: String?
+ ) {
+ (view as? DisplayCutoutView)?.let { cutoutView ->
+ cutoutView.setColor(tintColor)
+ cutoutView.updateRotation(rotation)
+ cutoutView.onDisplayChanged(displayUniqueId)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
index de6d7278971c..0681f50726a8 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/DecorProvider.kt
@@ -32,7 +32,7 @@ abstract class DecorProvider {
abstract val viewId: Int
/** The number of total aligned bounds */
- val numOfAlignedEdge: Int
+ val numOfAlignedBound: Int
get() = alignedBounds.size
/** The aligned bounds for the view which is created through inflateView() */
@@ -57,16 +57,8 @@ abstract class DecorProvider {
@Surface.Rotation rotation: Int,
tintColor: Int
): View
-}
-/**
- * Split list to 2 list, and return it back as Pair<>. The providers on the first list contains this
- * alignedBound element. The providers on the second list do not contain this alignedBound element
- */
-fun List<DecorProvider>.partitionAlignedBound(
- @DisplayCutout.BoundsPosition alignedBound: Int
-): Pair<List<DecorProvider>, List<DecorProvider>> {
- return partition { it.alignedBounds.contains(alignedBound) }
+ override fun toString() = "${javaClass.simpleName}{alignedBounds=$alignedBounds}"
}
/**
@@ -94,3 +86,61 @@ abstract class BoundDecorProvider : DecorProvider() {
listOf(alignedBound)
}
}
+
+/**
+ * Split list to 2 sub-lists, and return it back as Pair<>. The providers on the first list contains
+ * this alignedBound element. The providers on the second list do not contain this alignedBound
+ * element.
+ */
+fun List<DecorProvider>.partitionAlignedBound(
+ @DisplayCutout.BoundsPosition alignedBound: Int
+): Pair<List<DecorProvider>, List<DecorProvider>> {
+ return partition { it.alignedBounds.contains(alignedBound) }
+}
+
+/**
+ * Get the proper bound from DecorProvider list
+ * Time complexity: O(N), N is the number of providers
+ *
+ * Choose order
+ * 1. Return null if list is empty
+ * 2. If list contains BoundDecorProvider, return its alignedBound[0] because it is a must-have
+ * bound
+ * 3. Return the bound with most DecorProviders
+ */
+fun List<DecorProvider>.getProperBound(): Int? {
+ // Return null if list is empty
+ if (isEmpty()) {
+ return null
+ }
+
+ // Choose alignedBounds[0] of BoundDecorProvider if any
+ val singleBoundProvider = firstOrNull { it.numOfAlignedBound == 1 }
+ if (singleBoundProvider != null) {
+ return singleBoundProvider.alignedBounds[0]
+ }
+
+ // Return the bound with most DecorProviders
+ val boundCount = intArrayOf(0, 0, 0, 0)
+ for (provider in this) {
+ for (bound in provider.alignedBounds) {
+ boundCount[bound]++
+ }
+ }
+ var maxCount = 0
+ var maxCountBound: Int? = null
+ val bounds = arrayOf(
+ // Put top and bottom at first to get the highest priority to be chosen
+ DisplayCutout.BOUNDS_POSITION_TOP,
+ DisplayCutout.BOUNDS_POSITION_BOTTOM,
+ DisplayCutout.BOUNDS_POSITION_LEFT,
+ DisplayCutout.BOUNDS_POSITION_RIGHT
+ )
+ for (bound in bounds) {
+ if (boundCount[bound] > maxCount) {
+ maxCountBound = bound
+ maxCount = boundCount[bound]
+ }
+ }
+ return maxCountBound
+}
diff --git a/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt b/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
index dfb0b5aad912..45b8a08a9b45 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/OverlayWindow.kt
@@ -114,7 +114,8 @@ class OverlayWindow(private val context: Context) {
pw.println(" rootView=$rootView")
for (i in 0 until rootView.childCount) {
val child = rootView.getChildAt(i)
- pw.println(" child[$i]=$child")
+ val provider = viewProviderMap[child.id]?.second
+ pw.println(" child[$i]=$child $provider")
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java
index d5db63dc9093..75a97de10e7e 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java
@@ -35,7 +35,7 @@ import java.util.Set;
public class ComplicationUtils {
/**
* Converts a {@link com.android.settingslib.dream.DreamBackend.ComplicationType} to
- * {@link ComplicationType}.
+ * {@link Complication.ComplicationType}.
*/
@Complication.ComplicationType
public static int convertComplicationType(@DreamBackend.ComplicationType int type) {
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java
index 1c72e49eb06a..2503d3c3edad 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamHomeControlsComplication.java
@@ -151,8 +151,8 @@ public class DreamHomeControlsComplication implements Complication {
* Controls behavior of the dream complication.
*/
static class DreamHomeControlsChipViewController extends ViewController<ImageView> {
- private static final boolean DEBUG = false;
private static final String TAG = "DreamHomeControlsCtrl";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final ActivityStarter mActivityStarter;
private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamMediaEntryComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamMediaEntryComplication.java
new file mode 100644
index 000000000000..21a51d1096d5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DreamMediaEntryComplication.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.complication;
+
+import static com.android.systemui.dreams.complication.dagger.DreamMediaEntryComplicationComponent.DreamMediaEntryModule.DREAM_MEDIA_ENTRY_VIEW;
+import static com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule.DREAM_MEDIA_ENTRY_LAYOUT_PARAMS;
+
+import android.util.Log;
+import android.view.View;
+
+import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.dreams.complication.dagger.DreamMediaEntryComplicationComponent;
+import com.android.systemui.media.dream.MediaDreamComplication;
+import com.android.systemui.util.ViewController;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * A dream complication that shows a media entry chip to launch media control view.
+ */
+public class DreamMediaEntryComplication implements Complication {
+ private final DreamMediaEntryComplicationComponent.Factory mComponentFactory;
+
+ @Inject
+ public DreamMediaEntryComplication(
+ DreamMediaEntryComplicationComponent.Factory componentFactory) {
+ mComponentFactory = componentFactory;
+ }
+
+ @Override
+ public ViewHolder createView(ComplicationViewModel model) {
+ return mComponentFactory.create().getViewHolder();
+ }
+
+ /**
+ * Contains values/logic associated with the dream complication view.
+ */
+ public static class DreamMediaEntryViewHolder implements ViewHolder {
+ private final View mView;
+ private final ComplicationLayoutParams mLayoutParams;
+ private final DreamMediaEntryViewController mViewController;
+
+ @Inject
+ DreamMediaEntryViewHolder(
+ DreamMediaEntryViewController dreamMediaEntryViewController,
+ @Named(DREAM_MEDIA_ENTRY_VIEW) View view,
+ @Named(DREAM_MEDIA_ENTRY_LAYOUT_PARAMS) ComplicationLayoutParams layoutParams
+ ) {
+ mView = view;
+ mLayoutParams = layoutParams;
+ mViewController = dreamMediaEntryViewController;
+ mViewController.init();
+ }
+
+ @Override
+ public View getView() {
+ return mView;
+ }
+
+ @Override
+ public ComplicationLayoutParams getLayoutParams() {
+ return mLayoutParams;
+ }
+ }
+
+ /**
+ * Controls behavior of the dream complication.
+ */
+ static class DreamMediaEntryViewController extends ViewController<View> {
+ private static final String TAG = "DreamMediaEntryVwCtrl";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private final DreamOverlayStateController mDreamOverlayStateController;
+ private final MediaDreamComplication mMediaComplication;
+
+ private boolean mMediaComplicationAdded;
+
+ @Inject
+ DreamMediaEntryViewController(
+ @Named(DREAM_MEDIA_ENTRY_VIEW) View view,
+ DreamOverlayStateController dreamOverlayStateController,
+ MediaDreamComplication mediaComplication) {
+ super(view);
+ mDreamOverlayStateController = dreamOverlayStateController;
+ mMediaComplication = mediaComplication;
+ mView.setOnClickListener(this::onClickMediaEntry);
+ }
+
+ @Override
+ protected void onViewAttached() {
+ }
+
+ @Override
+ protected void onViewDetached() {
+ removeMediaComplication();
+ }
+
+ private void onClickMediaEntry(View v) {
+ if (DEBUG) Log.d(TAG, "media entry complication tapped");
+
+ if (!mMediaComplicationAdded) {
+ addMediaComplication();
+ } else {
+ removeMediaComplication();
+ }
+ }
+
+ private void addMediaComplication() {
+ mView.setSelected(true);
+ mDreamOverlayStateController.addComplication(mMediaComplication);
+ mMediaComplicationAdded = true;
+ }
+
+ private void removeMediaComplication() {
+ mView.setSelected(false);
+ mDreamOverlayStateController.removeComplication(mMediaComplication);
+ mMediaComplicationAdded = false;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
index 567bdbc01170..a981f255a873 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/SmartSpaceComplication.java
@@ -70,11 +70,7 @@ public class SmartSpaceComplication implements Complication {
new BcSmartspaceDataPlugin.SmartspaceTargetListener() {
@Override
public void onSmartspaceTargetsUpdated(List<? extends Parcelable> targets) {
- if (!targets.isEmpty()) {
- mDreamOverlayStateController.addComplication(mComplication);
- } else {
- mDreamOverlayStateController.removeComplication(mComplication);
- }
+ mDreamOverlayStateController.addComplication(mComplication);
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamMediaEntryComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamMediaEntryComplicationComponent.java
new file mode 100644
index 000000000000..ed05daf35ed9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/DreamMediaEntryComplicationComponent.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.complication.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.android.systemui.R;
+import com.android.systemui.dreams.complication.DreamMediaEntryComplication;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Named;
+import javax.inject.Scope;
+
+import dagger.Module;
+import dagger.Provides;
+import dagger.Subcomponent;
+
+/**
+ * Responsible for generating dependencies for the {@link DreamMediaEntryComplication}.
+ */
+@Subcomponent(modules = DreamMediaEntryComplicationComponent.DreamMediaEntryModule.class)
+@DreamMediaEntryComplicationComponent.DreamMediaEntryComplicationScope
+public interface DreamMediaEntryComplicationComponent {
+ /**
+ * Creates a view holder for the media entry complication.
+ */
+ DreamMediaEntryComplication.DreamMediaEntryViewHolder getViewHolder();
+
+ /**
+ * Scope of the media entry complication.
+ */
+ @Documented
+ @Retention(RUNTIME)
+ @Scope
+ @interface DreamMediaEntryComplicationScope {}
+
+ /**
+ * Factory that generates a {@link DreamMediaEntryComplicationComponent}.
+ */
+ @Subcomponent.Factory
+ interface Factory {
+ DreamMediaEntryComplicationComponent create();
+ }
+
+ /**
+ * Scoped injected values for the {@link DreamMediaEntryComplicationComponent}.
+ */
+ @Module
+ interface DreamMediaEntryModule {
+ String DREAM_MEDIA_ENTRY_VIEW = "dream_media_entry_view";
+
+ /**
+ * Provides the dream media entry view.
+ */
+ @Provides
+ @DreamMediaEntryComplicationScope
+ @Named(DREAM_MEDIA_ENTRY_VIEW)
+ static View provideMediaEntryView(LayoutInflater layoutInflater) {
+ return (View) layoutInflater.inflate(R.layout.dream_overlay_media_entry_chip, null);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
index eb07238ce752..759d6ec3bf21 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/dagger/RegisteredComplicationsModule.java
@@ -38,15 +38,19 @@ import dagger.Provides;
},
subcomponents = {
DreamHomeControlsComplicationComponent.class,
+ DreamMediaEntryComplicationComponent.class
})
public interface RegisteredComplicationsModule {
String DREAM_CLOCK_TIME_COMPLICATION_LAYOUT_PARAMS = "time_complication_layout_params";
String DREAM_SMARTSPACE_LAYOUT_PARAMS = "smartspace_layout_params";
String DREAM_HOME_CONTROLS_CHIP_LAYOUT_PARAMS = "home_controls_chip_layout_params";
+ String DREAM_MEDIA_ENTRY_LAYOUT_PARAMS = "media_entry_layout_params";
int DREAM_CLOCK_TIME_COMPLICATION_WEIGHT = 1;
int DREAM_SMARTSPACE_COMPLICATION_WEIGHT = 0;
+ int DREAM_MEDIA_COMPLICATION_WEIGHT = -1;
int DREAM_HOME_CONTROLS_CHIP_COMPLICATION_WEIGHT = 1;
+ int DREAM_MEDIA_ENTRY_COMPLICATION_WEIGHT = 0;
/**
* Provides layout parameters for the clock time complication.
@@ -78,6 +82,21 @@ public interface RegisteredComplicationsModule {
}
/**
+ * Provides layout parameters for the media entry complication.
+ */
+ @Provides
+ @Named(DREAM_MEDIA_ENTRY_LAYOUT_PARAMS)
+ static ComplicationLayoutParams provideMediaEntryLayoutParams(@Main Resources res) {
+ return new ComplicationLayoutParams(
+ res.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width),
+ res.getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height),
+ ComplicationLayoutParams.POSITION_BOTTOM
+ | ComplicationLayoutParams.POSITION_START,
+ ComplicationLayoutParams.DIRECTION_END,
+ DREAM_MEDIA_ENTRY_COMPLICATION_WEIGHT);
+ }
+
+ /**
* Provides layout parameters for the smartspace complication.
*/
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
index 9e2b7c748631..a3dc77993d30 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java
@@ -50,7 +50,6 @@ import com.android.settingslib.bluetooth.LocalBluetoothAdapter;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.systemui.CoreStartable;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
@@ -61,6 +60,7 @@ import java.util.List;
import java.util.Set;
import javax.inject.Inject;
+import javax.inject.Provider;
/** */
@SysUISingleton
@@ -106,6 +106,8 @@ public class KeyboardUI extends CoreStartable implements InputManager.OnTabletMo
protected volatile Context mContext;
+ private final Provider<LocalBluetoothManager> mBluetoothManagerProvider;
+
private boolean mEnabled;
private String mKeyboardName;
private CachedBluetoothDeviceManager mCachedDeviceManager;
@@ -122,8 +124,9 @@ public class KeyboardUI extends CoreStartable implements InputManager.OnTabletMo
private int mState;
@Inject
- public KeyboardUI(Context context) {
+ public KeyboardUI(Context context, Provider<LocalBluetoothManager> bluetoothManagerProvider) {
super(context);
+ this.mBluetoothManagerProvider = bluetoothManagerProvider;
}
@Override
@@ -181,7 +184,7 @@ public class KeyboardUI extends CoreStartable implements InputManager.OnTabletMo
return;
}
- LocalBluetoothManager bluetoothManager = Dependency.get(LocalBluetoothManager.class);
+ LocalBluetoothManager bluetoothManager = mBluetoothManagerProvider.get();
if (bluetoothManager == null) {
if (DEBUG) {
Slog.e(TAG, "Failed to retrieve LocalBluetoothManager instance");
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 7b497ade683c..c48271e0348a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -518,9 +518,20 @@ class MediaDataManager(
}
val actions = createActionsFromState(it.packageName,
mediaControllerFactory.create(it.token), UserHandle(it.userId))
- val data = it.copy(
- semanticActions = actions,
- isPlaying = isPlayingState(state.state))
+
+ // Control buttons
+ // If flag is enabled and controller has a PlaybackState,
+ // create actions from session info
+ // otherwise, no need to update semantic actions.
+ val data = if (actions != null) {
+ it.copy(
+ semanticActions = actions,
+ isPlaying = isPlayingState(state.state))
+ } else {
+ it.copy(
+ isPlaying = isPlayingState(state.state)
+ )
+ }
if (DEBUG) Log.d(TAG, "State updated outside of notification")
onMediaDataLoaded(key, key, data)
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index 08cf57c7594e..b39770d302be 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -356,15 +356,6 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
mHeaderSubtitle.setText(subTitle);
mHeaderTitle.setGravity(Gravity.NO_GRAVITY);
}
- if (!mAdapter.isDragging()) {
- int currentActivePosition = mAdapter.getCurrentActivePosition();
- if (!colorSetUpdated && !deviceSetChanged && currentActivePosition >= 0
- && currentActivePosition < mAdapter.getItemCount()) {
- mAdapter.notifyItemChanged(currentActivePosition);
- } else {
- mAdapter.notifyDataSetChanged();
- }
- }
// Show when remote media session is available or
// when the device supports BT LE audio + media is playing
mStopButton.setVisibility(getStopButtonVisibility());
@@ -374,6 +365,18 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements
mBroadcastIcon.setVisibility(getBroadcastIconVisibility());
mBroadcastIcon.setOnClickListener(v -> onBroadcastIconClick());
+ if (!mAdapter.isDragging()) {
+ int currentActivePosition = mAdapter.getCurrentActivePosition();
+ if (!colorSetUpdated && !deviceSetChanged && currentActivePosition >= 0
+ && currentActivePosition < mAdapter.getItemCount()) {
+ mAdapter.notifyItemChanged(currentActivePosition);
+ } else {
+ mAdapter.notifyDataSetChanged();
+ }
+ } else {
+ mMediaOutputController.setRefreshing(false);
+ mMediaOutputController.refreshDataSetIfNeeded();
+ }
}
private void updateButtonBackgroundColorFilter() {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java b/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java
index c5448713970c..acd04f216a98 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java
@@ -25,6 +25,7 @@ import androidx.annotation.Nullable;
import com.android.systemui.CoreStartable;
import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.dreams.complication.DreamMediaEntryComplication;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.MediaData;
import com.android.systemui.media.MediaDataManager;
@@ -54,7 +55,7 @@ public class MediaDreamSentinel extends CoreStartable {
}
mAdded = false;
- mDreamOverlayStateController.removeComplication(mComplication);
+ mDreamOverlayStateController.removeComplication(mMediaEntryComplication);
}
@Override
@@ -79,24 +80,24 @@ public class MediaDreamSentinel extends CoreStartable {
}
mAdded = true;
- mDreamOverlayStateController.addComplication(mComplication);
+ mDreamOverlayStateController.addComplication(mMediaEntryComplication);
}
};
private final MediaDataManager mMediaDataManager;
private final DreamOverlayStateController mDreamOverlayStateController;
- private final MediaDreamComplication mComplication;
+ private final DreamMediaEntryComplication mMediaEntryComplication;
private final FeatureFlags mFeatureFlags;
@Inject
public MediaDreamSentinel(Context context, MediaDataManager mediaDataManager,
DreamOverlayStateController dreamOverlayStateController,
- MediaDreamComplication complication,
+ DreamMediaEntryComplication mediaEntryComplication,
FeatureFlags featureFlags) {
super(context);
mMediaDataManager = mediaDataManager;
mDreamOverlayStateController = dreamOverlayStateController;
- mComplication = complication;
+ mMediaEntryComplication = mediaEntryComplication;
mFeatureFlags = featureFlags;
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java
index 3408d97dd33f..052608f17e0e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java
@@ -16,6 +16,8 @@
package com.android.systemui.media.dream.dagger;
+import static com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule.DREAM_MEDIA_COMPLICATION_WEIGHT;
+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import android.content.Context;
@@ -93,7 +95,7 @@ public interface MediaComplicationComponent {
ComplicationLayoutParams.POSITION_TOP
| ComplicationLayoutParams.POSITION_START,
ComplicationLayoutParams.DIRECTION_DOWN,
- 0,
+ DREAM_MEDIA_COMPLICATION_WEIGHT,
true);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
index 00a22f20e94d..35a6c74518e0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt
@@ -30,7 +30,6 @@ import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.view.accessibility.AccessibilityManager
-import androidx.core.graphics.ColorUtils
import com.android.settingslib.Utils
import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
@@ -209,8 +208,7 @@ class MediaTttChipControllerReceiver @Inject constructor(
// Center the ripple on the bottom of the screen in the middle.
rippleView.setCenter(width * 0.5f, height.toFloat())
val color = Utils.getColorAttrDefaultColor(context, R.attr.wallpaperTextColorAccent)
- val colorWithAlpha = ColorUtils.setAlphaComponent(color, 70)
- rippleView.setColor(colorWithAlpha)
+ rippleView.setColor(color, 70)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
index a153cb6c0d31..f93c671f6740 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt
@@ -26,6 +26,7 @@ import com.android.internal.logging.UiEventLogger
import com.android.internal.statusbar.IUndoMediaTransferCallback
import com.android.systemui.R
import com.android.systemui.media.taptotransfer.common.DEFAULT_TIMEOUT_MILLIS
+import com.android.systemui.plugins.FalsingManager
/**
* A class enumerating all the possible states of the media tap-to-transfer chip on the sender
@@ -106,12 +107,15 @@ enum class ChipStateSender(
controllerSender: MediaTttChipControllerSender,
routeInfo: MediaRoute2Info,
undoCallback: IUndoMediaTransferCallback?,
- uiEventLogger: MediaTttSenderUiEventLogger
+ uiEventLogger: MediaTttSenderUiEventLogger,
+ falsingManager: FalsingManager,
): View.OnClickListener? {
if (undoCallback == null) {
return null
}
return View.OnClickListener {
+ if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return@OnClickListener
+
uiEventLogger.logUndoClicked(
MediaTttSenderUiEvents.MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_RECEIVER_CLICKED
)
@@ -141,12 +145,15 @@ enum class ChipStateSender(
controllerSender: MediaTttChipControllerSender,
routeInfo: MediaRoute2Info,
undoCallback: IUndoMediaTransferCallback?,
- uiEventLogger: MediaTttSenderUiEventLogger
+ uiEventLogger: MediaTttSenderUiEventLogger,
+ falsingManager: FalsingManager,
): View.OnClickListener? {
if (undoCallback == null) {
return null
}
return View.OnClickListener {
+ if (falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return@OnClickListener
+
uiEventLogger.logUndoClicked(
MediaTttSenderUiEvents.MEDIA_TTT_SENDER_UNDO_TRANSFER_TO_THIS_DEVICE_CLICKED
)
@@ -212,7 +219,8 @@ enum class ChipStateSender(
controllerSender: MediaTttChipControllerSender,
routeInfo: MediaRoute2Info,
undoCallback: IUndoMediaTransferCallback?,
- uiEventLogger: MediaTttSenderUiEventLogger
+ uiEventLogger: MediaTttSenderUiEventLogger,
+ falsingManager: FalsingManager,
): View.OnClickListener? = null
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt
index 933548963390..5ad82fd9fd8f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt
@@ -22,21 +22,25 @@ import android.media.MediaRoute2Info
import android.os.PowerManager
import android.util.Log
import android.view.Gravity
+import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.view.accessibility.AccessibilityManager
import android.widget.TextView
import com.android.internal.statusbar.IUndoMediaTransferCallback
+import com.android.systemui.Gefingerpoken
import com.android.systemui.R
import com.android.systemui.animation.Interpolators
import com.android.systemui.animation.ViewHierarchyAnimator
+import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.taptotransfer.common.ChipInfoCommon
import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon
import com.android.systemui.media.taptotransfer.common.MediaTttLogger
import com.android.systemui.media.taptotransfer.common.MediaTttRemovalReason
+import com.android.systemui.plugins.FalsingManager
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.concurrency.DelayableExecutor
@@ -58,7 +62,9 @@ class MediaTttChipControllerSender @Inject constructor(
accessibilityManager: AccessibilityManager,
configurationController: ConfigurationController,
powerManager: PowerManager,
- private val uiEventLogger: MediaTttSenderUiEventLogger
+ private val uiEventLogger: MediaTttSenderUiEventLogger,
+ private val falsingManager: FalsingManager,
+ private val falsingCollector: FalsingCollector,
) : MediaTttChipControllerCommon<ChipSenderInfo>(
context,
logger,
@@ -70,6 +76,9 @@ class MediaTttChipControllerSender @Inject constructor(
powerManager,
R.layout.media_ttt_chip,
) {
+
+ private lateinit var parent: MediaTttChipRootView
+
override val windowLayoutParams = commonWindowLayoutParams.apply {
gravity = Gravity.TOP.or(Gravity.CENTER_HORIZONTAL)
}
@@ -121,6 +130,15 @@ class MediaTttChipControllerSender @Inject constructor(
val chipState = newChipInfo.state
+ // Detect falsing touches on the chip.
+ parent = currentChipView as MediaTttChipRootView
+ parent.touchHandler = object : Gefingerpoken {
+ override fun onTouchEvent(ev: MotionEvent?): Boolean {
+ falsingCollector.onTouchEvent(ev)
+ return false
+ }
+ }
+
// App icon
val iconName = setIcon(currentChipView, newChipInfo.routeInfo.clientPackageName)
@@ -136,7 +154,11 @@ class MediaTttChipControllerSender @Inject constructor(
// Undo
val undoView = currentChipView.requireViewById<View>(R.id.undo)
val undoClickListener = chipState.undoClickListener(
- this, newChipInfo.routeInfo, newChipInfo.undoCallback, uiEventLogger
+ this,
+ newChipInfo.routeInfo,
+ newChipInfo.undoCallback,
+ uiEventLogger,
+ falsingManager,
)
undoView.setOnClickListener(undoClickListener)
undoView.visibility = (undoClickListener != null).visibleIfTrue()
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipRootView.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipRootView.kt
new file mode 100644
index 000000000000..3373159fba4e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipRootView.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.taptotransfer.sender
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.MotionEvent
+import android.widget.FrameLayout
+import com.android.systemui.Gefingerpoken
+
+/** A simple subclass that allows for observing touch events on chip. */
+class MediaTttChipRootView(
+ context: Context,
+ attrs: AttributeSet?
+) : FrameLayout(context, attrs) {
+
+ /** Assign this field to observe touch events. */
+ var touchHandler: Gefingerpoken? = null
+
+ override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
+ touchHandler?.onTouchEvent(ev)
+ return super.dispatchTouchEvent(ev)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index ce6aaae6e98c..0ec4eef1e551 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -43,6 +43,7 @@ import com.android.systemui.qs.QSUserSwitcherEvent;
import com.android.systemui.qs.user.UserSwitchDialogController;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.user.data.source.UserRecord;
import javax.inject.Inject;
@@ -95,7 +96,7 @@ public class UserDetailView extends PseudoGridView {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- UserSwitcherController.UserRecord item = getItem(position);
+ UserRecord item = getItem(position);
return createUserDetailItemView(convertView, parent, item);
}
@@ -113,7 +114,7 @@ public class UserDetailView extends PseudoGridView {
}
public UserDetailItemView createUserDetailItemView(View convertView, ViewGroup parent,
- UserSwitcherController.UserRecord item) {
+ UserRecord item) {
UserDetailItemView v = UserDetailItemView.convertOrInflate(
parent.getContext(), convertView, parent);
if (!item.isCurrent || item.isGuest) {
@@ -134,7 +135,7 @@ public class UserDetailView extends PseudoGridView {
v.bind(name, drawable, item.info.id);
}
v.setActivated(item.isCurrent);
- v.setDisabledByAdmin(item.isDisabledByAdmin);
+ v.setDisabledByAdmin(mController.isDisabledByAdmin(item));
v.setEnabled(item.isSwitchToEnabled);
v.setAlpha(v.isEnabled() ? USER_SWITCH_ENABLED_ALPHA : USER_SWITCH_DISABLED_ALPHA);
@@ -146,7 +147,7 @@ public class UserDetailView extends PseudoGridView {
}
private static Drawable getDrawable(Context context,
- UserSwitcherController.UserRecord item) {
+ UserRecord item) {
Drawable icon = getIconDrawable(context, item);
int iconColorRes;
if (item.isCurrent) {
@@ -171,22 +172,24 @@ public class UserDetailView extends PseudoGridView {
}
Trace.beginSection("UserDetailView.Adapter#onClick");
- UserSwitcherController.UserRecord tag =
- (UserSwitcherController.UserRecord) view.getTag();
- if (tag.isDisabledByAdmin) {
+ UserRecord userRecord =
+ (UserRecord) view.getTag();
+ if (mController.isDisabledByAdmin(userRecord)) {
final Intent intent = RestrictedLockUtils.getShowAdminSupportDetailsIntent(
- mContext, tag.enforcedAdmin);
+ mContext, mController.getEnforcedAdmin(userRecord));
mController.startActivity(intent);
- } else if (tag.isSwitchToEnabled) {
+ } else if (userRecord.isSwitchToEnabled) {
MetricsLogger.action(mContext, MetricsEvent.QS_SWITCH_USER);
mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_SWITCH);
- if (!tag.isAddUser && !tag.isRestricted && !tag.isDisabledByAdmin) {
+ if (!userRecord.isAddUser
+ && !userRecord.isRestricted
+ && !mController.isDisabledByAdmin(userRecord)) {
if (mCurrentUserView != null) {
mCurrentUserView.setActivated(false);
}
view.setActivated(true);
}
- onUserListItemClicked(tag, mDialogShower);
+ onUserListItemClicked(userRecord, mDialogShower);
}
Trace.endSection();
}
diff --git a/packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt b/packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
index db7c1fd86be0..d2f3a6a7bee1 100644
--- a/packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
+++ b/packages/SystemUI/src/com/android/systemui/ripple/RippleShader.kt
@@ -68,7 +68,7 @@ class RippleShader internal constructor(rippleShape: RippleShape = RippleShape.C
float rippleInsideAlpha = (1.-inside) * in_fadeFill;
float rippleRingAlpha = (1.-sparkleRing) * in_fadeRing;
float rippleAlpha = max(rippleInsideAlpha, rippleRingAlpha) * in_color.a;
- vec4 ripple = in_color * rippleAlpha;
+ vec4 ripple = vec4(in_color.rgb, 1.0) * rippleAlpha;
return mix(ripple, vec4(sparkle), sparkle * in_sparkle_strength);
}
"""
@@ -84,7 +84,7 @@ class RippleShader internal constructor(rippleShape: RippleShape = RippleShape.C
float rippleInsideAlpha = (1.-inside) * in_fadeFill;
float rippleRingAlpha = (1.-sparkleRing) * in_fadeRing;
float rippleAlpha = max(rippleInsideAlpha, rippleRingAlpha) * in_color.a;
- vec4 ripple = in_color * rippleAlpha;
+ vec4 ripple = vec4(in_color.rgb, 1.0) * rippleAlpha;
return mix(ripple, vec4(sparkle), sparkle * in_sparkle_strength);
}
"""
@@ -100,7 +100,7 @@ class RippleShader internal constructor(rippleShape: RippleShape = RippleShape.C
float rippleInsideAlpha = (1.-inside) * in_fadeFill;
float rippleRingAlpha = (1.-sparkleRing) * in_fadeRing;
float rippleAlpha = max(rippleInsideAlpha, rippleRingAlpha) * in_color.a;
- vec4 ripple = in_color * rippleAlpha;
+ vec4 ripple = vec4(in_color.rgb, 1.0) * rippleAlpha;
return mix(ripple, vec4(sparkle), sparkle * in_sparkle_strength);
}
"""
diff --git a/packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt b/packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
index 60c8f3719a2e..1e51ffa292b7 100644
--- a/packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/ripple/RippleView.kt
@@ -25,10 +25,12 @@ import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
+import androidx.core.graphics.ColorUtils
import com.android.systemui.ripple.RippleShader.RippleShape
private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.3f
private const val RIPPLE_DEFAULT_COLOR: Int = 0xffffffff.toInt()
+const val RIPPLE_DEFAULT_ALPHA: Int = 45
/**
* A generic expanding ripple effect.
@@ -111,9 +113,12 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
rippleInProgress = true
}
- /** Set the color to be used for the ripple. */
- fun setColor(color: Int) {
- rippleShader.color = color
+ /** Set the color to be used for the ripple.
+ *
+ * The alpha value of the color will be applied to the ripple. The alpha range is [0-100].
+ */
+ fun setColor(color: Int, alpha: Int = RIPPLE_DEFAULT_ALPHA) {
+ rippleShader.color = ColorUtils.setAlphaComponent(color, alpha)
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index 35f32caffe21..695a80b2b95d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -229,6 +229,7 @@ public class TakeScreenshotService extends Service {
Log.d(TAG, "handleMessage: Using request processor");
mProcessor.processAsync(request,
(r) -> dispatchToController(r, onSaved, callback));
+ return;
}
dispatchToController(request, onSaved, callback);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java
index 9818af3751a7..1cdacb93ba45 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelView.java
@@ -17,32 +17,30 @@
package com.android.systemui.shade;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.FrameLayout;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.TapAgainView;
-public class NotificationPanelView extends PanelView {
+/** The shade view. */
+public final class NotificationPanelView extends FrameLayout {
+ static final boolean DEBUG = false;
- private static final boolean DEBUG = false;
-
- /**
- * Fling expanding QS.
- */
- public static final int FLING_EXPAND = 0;
-
- public static final String COUNTER_PANEL_OPEN = "panel_open";
- public static final String COUNTER_PANEL_OPEN_QS = "panel_open_qs";
+ private final Paint mAlphaPaint = new Paint();
private int mCurrentPanelAlpha;
- private final Paint mAlphaPaint = new Paint();
private boolean mDozing;
private RtlChangeListener mRtlChangeListener;
+ private NotificationPanelViewController.TouchHandler mTouchHandler;
+ private OnConfigurationChangedListener mOnConfigurationChangedListener;
public NotificationPanelView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -99,7 +97,36 @@ public class NotificationPanelView extends PanelView {
return findViewById(R.id.shade_falsing_tap_again);
}
+ /** Sets the touch handler for this view. */
+ public void setOnTouchListener(NotificationPanelViewController.TouchHandler touchHandler) {
+ super.setOnTouchListener(touchHandler);
+ mTouchHandler = touchHandler;
+ }
+
+ void setOnConfigurationChangedListener(OnConfigurationChangedListener listener) {
+ mOnConfigurationChangedListener = listener;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent event) {
+ return mTouchHandler.onInterceptTouchEvent(event);
+ }
+
+ @Override
+ public void dispatchConfigurationChanged(Configuration newConfig) {
+ super.dispatchConfigurationChanged(newConfig);
+ mOnConfigurationChangedListener.onConfigurationChanged(newConfig);
+ }
+
+ /** Callback for right-to-left setting changes. */
interface RtlChangeListener {
+ /** Called when right-to-left setting changes. */
void onRtlPropertielsChanged(int layoutDirection);
}
+
+ /** Callback for config changes. */
+ interface OnConfigurationChangedListener {
+ /** Called when configuration changes. */
+ void onConfigurationChanged(Configuration newConfig);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 5f07f9f1c9ad..9a8395cdad68 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -33,7 +33,7 @@ import static com.android.systemui.classifier.Classifier.GENERIC;
import static com.android.systemui.classifier.Classifier.QS_COLLAPSE;
import static com.android.systemui.classifier.Classifier.QUICK_SETTINGS;
import static com.android.systemui.classifier.Classifier.UNLOCK;
-import static com.android.systemui.shade.PanelView.DEBUG;
+import static com.android.systemui.shade.NotificationPanelView.DEBUG;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
@@ -248,7 +248,7 @@ import javax.inject.Provider;
@CentralSurfacesComponent.CentralSurfacesScope
public final class NotificationPanelViewController {
- public static final String TAG = PanelView.class.getSimpleName();
+ public static final String TAG = "PanelView";
public static final float FLING_MAX_LENGTH_SECONDS = 0.6f;
public static final float FLING_SPEED_UP_FACTOR = 0.6f;
public static final float FLING_CLOSING_MAX_LENGTH_SECONDS = 0.6f;
@@ -274,7 +274,7 @@ public final class NotificationPanelViewController {
/**
* Fling expanding QS.
*/
- private static final int FLING_EXPAND = 0;
+ public static final int FLING_EXPAND = 0;
/**
* Fling collapsing QS, potentially stopping when QS becomes QQS.
@@ -430,7 +430,8 @@ public final class NotificationPanelViewController {
private boolean mQsTracking;
/**
- * If set, the ongoing touch gesture might both trigger the expansion in {@link PanelView} and
+ * If set, the ongoing touch gesture might both trigger the expansion in {@link
+ * NotificationPanelView} and
* the expansion for quick settings.
*/
private boolean mConflictingQsExpansionGesture;
@@ -5405,13 +5406,13 @@ public final class NotificationPanelViewController {
return animator;
}
- /** Update the visibility of {@link PanelView} if necessary. */
+ /** Update the visibility of {@link NotificationPanelView} if necessary. */
public void updateVisibility() {
mView.setVisibility(shouldPanelBeVisible() ? VISIBLE : INVISIBLE);
}
/**
- * Updates the panel expansion and {@link PanelView} visibility if necessary.
+ * Updates the panel expansion and {@link NotificationPanelView} visibility if necessary.
*
* TODO(b/200063118): Could public calls to this method be replaced with calls to
* {@link #updateVisibility()}? That would allow us to make this method private.
@@ -6170,7 +6171,7 @@ public final class NotificationPanelViewController {
}
public class OnConfigurationChangedListener implements
- PanelView.OnConfigurationChangedListener {
+ NotificationPanelView.OnConfigurationChangedListener {
@Override
public void onConfigurationChanged(Configuration newConfig) {
loadDimens();
diff --git a/packages/SystemUI/src/com/android/systemui/shade/PanelView.java b/packages/SystemUI/src/com/android/systemui/shade/PanelView.java
deleted file mode 100644
index 4349d816b3c3..000000000000
--- a/packages/SystemUI/src/com/android/systemui/shade/PanelView.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.shade;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.widget.FrameLayout;
-
-import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
-
-public abstract class PanelView extends FrameLayout {
- public static final boolean DEBUG = false;
- public static final String TAG = PanelView.class.getSimpleName();
- private NotificationPanelViewController.TouchHandler mTouchHandler;
-
- protected CentralSurfaces mCentralSurfaces;
- protected HeadsUpManagerPhone mHeadsUpManager;
-
- protected KeyguardBottomAreaView mKeyguardBottomArea;
- private OnConfigurationChangedListener mOnConfigurationChangedListener;
-
- public PanelView(Context context) {
- super(context);
- }
-
- public PanelView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public PanelView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
- public void setOnTouchListener(NotificationPanelViewController.TouchHandler touchHandler) {
- super.setOnTouchListener(touchHandler);
- mTouchHandler = touchHandler;
- }
-
- public void setOnConfigurationChangedListener(OnConfigurationChangedListener listener) {
- mOnConfigurationChangedListener = listener;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent event) {
- return mTouchHandler.onInterceptTouchEvent(event);
- }
-
- @Override
- public void dispatchConfigurationChanged(Configuration newConfig) {
- super.dispatchConfigurationChanged(newConfig);
- mOnConfigurationChangedListener.onConfigurationChanged(newConfig);
- }
-
- interface OnConfigurationChangedListener {
- void onConfigurationChanged(Configuration newConfig);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
index b9684fcb8a01..3d161d9bfa75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/EmptyShadeView.java
@@ -24,6 +24,8 @@ import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
@@ -73,6 +75,7 @@ public class EmptyShadeView extends StackScrollerDecorView {
}
@Override
+ @NonNull
public ExpandableViewState createExpandableViewState() {
return new EmptyShadeViewState();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 87f8a03098f5..47dc5c2a5513 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -19,9 +19,12 @@ package com.android.systemui.statusbar;
import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.KEYGUARD_MANAGEMENT_DISCLOSURE;
import static android.app.admin.DevicePolicyResources.Strings.SystemUi.KEYGUARD_NAMED_MANAGEMENT_DISCLOSURE;
+import static android.hardware.biometrics.BiometricSourceType.FACE;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
+import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
+import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser;
import static com.android.systemui.DejankUtils.whitelistIpcs;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.IMPORTANT_MSG_MIN_DURATION;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT;
@@ -428,9 +431,9 @@ public class KeyguardIndicationController {
if (info == null) {
// Use the current user owner information if enabled.
final boolean ownerInfoEnabled = mLockPatternUtils.isOwnerInfoEnabled(
- KeyguardUpdateMonitor.getCurrentUser());
+ getCurrentUser());
if (ownerInfoEnabled) {
- info = mLockPatternUtils.getOwnerInfo(KeyguardUpdateMonitor.getCurrentUser());
+ info = mLockPatternUtils.getOwnerInfo(getCurrentUser());
}
}
@@ -595,7 +598,7 @@ public class KeyguardIndicationController {
private void updateLockScreenLogoutView() {
final boolean shouldShowLogout = mKeyguardUpdateMonitor.isLogoutEnabled()
- && KeyguardUpdateMonitor.getCurrentUser() != UserHandle.USER_SYSTEM;
+ && getCurrentUser() != UserHandle.USER_SYSTEM;
if (shouldShowLogout) {
mRotateTextViewController.updateIndication(
INDICATION_TYPE_LOGOUT,
@@ -610,7 +613,7 @@ public class KeyguardIndicationController {
if (mFalsingManager.isFalseTap(LOW_PENALTY)) {
return;
}
- int currentUserId = KeyguardUpdateMonitor.getCurrentUser();
+ int currentUserId = getCurrentUser();
mDevicePolicyManager.logoutUser();
})
.build(),
@@ -767,7 +770,7 @@ public class KeyguardIndicationController {
mHandler.removeMessages(MSG_HIDE_BIOMETRIC_MESSAGE);
hideBiometricMessageDelayed(
mBiometricMessageFollowUp != null
- ? DEFAULT_HIDE_DELAY_MS * 2
+ ? IMPORTANT_MSG_MIN_DURATION * 2
: DEFAULT_HIDE_DELAY_MS
);
@@ -847,7 +850,7 @@ public class KeyguardIndicationController {
mTopIndicationView.setVisibility(GONE);
mTopIndicationView.setText(null);
mLockScreenIndicationView.setVisibility(View.VISIBLE);
- updateLockScreenIndications(animate, KeyguardUpdateMonitor.getCurrentUser());
+ updateLockScreenIndications(animate, getCurrentUser());
}
protected String computePowerIndication() {
@@ -915,7 +918,7 @@ public class KeyguardIndicationController {
public void showActionToUnlock() {
if (mDozing
&& !mKeyguardUpdateMonitor.getUserCanSkipBouncer(
- KeyguardUpdateMonitor.getCurrentUser())) {
+ getCurrentUser())) {
return;
}
@@ -928,7 +931,7 @@ public class KeyguardIndicationController {
}
} else {
final boolean canSkipBouncer = mKeyguardUpdateMonitor.getUserCanSkipBouncer(
- KeyguardUpdateMonitor.getCurrentUser());
+ getCurrentUser());
if (canSkipBouncer) {
final boolean faceAuthenticated = mKeyguardUpdateMonitor.getIsFaceAuthenticated();
final boolean udfpsSupported = mKeyguardUpdateMonitor.isUdfpsSupported();
@@ -1045,12 +1048,15 @@ public class KeyguardIndicationController {
return;
}
- boolean showActionToUnlock =
- msgId == KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
- if (biometricSourceType == BiometricSourceType.FACE
- && !showActionToUnlock
- && mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
- KeyguardUpdateMonitor.getCurrentUser())
+ final boolean faceAuthSoftError = biometricSourceType == FACE
+ && msgId != BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
+ final boolean faceAuthFailed = biometricSourceType == FACE
+ && msgId == BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; // ran through matcher & failed
+ final boolean isUnlockWithFingerprintPossible =
+ mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
+ getCurrentUser());
+ if (faceAuthSoftError
+ && isUnlockWithFingerprintPossible
&& !mCoExFaceHelpMsgIdsToShow.contains(msgId)) {
if (DEBUG) {
Log.d(TAG, "skip showing msgId=" + msgId + " helpString=" + helpString
@@ -1061,8 +1067,16 @@ public class KeyguardIndicationController {
mStatusBarKeyguardViewManager.showBouncerMessage(helpString,
mInitialTextColorState);
} else if (mScreenLifecycle.getScreenState() == SCREEN_ON) {
- showBiometricMessage(helpString);
- } else if (showActionToUnlock) {
+ if (faceAuthFailed && isUnlockWithFingerprintPossible) {
+ showBiometricMessage(
+ mContext.getString(R.string.keyguard_face_failed),
+ mContext.getString(R.string.keyguard_suggest_fingerprint)
+ );
+ } else {
+ showBiometricMessage(helpString);
+ }
+ } else if (faceAuthFailed) {
+ // show action to unlock
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SHOW_ACTION_TO_UNLOCK),
TRANSIENT_BIOMETRIC_ERROR_TIMEOUT);
} else {
@@ -1080,17 +1094,17 @@ public class KeyguardIndicationController {
return;
}
- if (biometricSourceType == BiometricSourceType.FACE
+ if (biometricSourceType == FACE
&& msgId == FaceManager.FACE_ERROR_UNABLE_TO_PROCESS) {
// suppress all face UNABLE_TO_PROCESS errors
if (DEBUG) {
Log.d(TAG, "skip showing FACE_ERROR_UNABLE_TO_PROCESS errString="
+ errString);
}
- } else if (biometricSourceType == BiometricSourceType.FACE
+ } else if (biometricSourceType == FACE
&& msgId == FaceManager.FACE_ERROR_TIMEOUT) {
if (mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
- KeyguardUpdateMonitor.getCurrentUser())) {
+ getCurrentUser())) {
// no message if fingerprint is also enrolled
if (DEBUG) {
Log.d(TAG, "skip showing FACE_ERROR_TIMEOUT due to co-ex logic");
@@ -1122,8 +1136,9 @@ public class KeyguardIndicationController {
BiometricSourceType biometricSourceType, KeyguardUpdateMonitor updateMonitor) {
if (biometricSourceType == BiometricSourceType.FINGERPRINT)
return shouldSuppressFingerprintError(msgId, updateMonitor);
- if (biometricSourceType == BiometricSourceType.FACE)
+ if (biometricSourceType == FACE) {
return shouldSuppressFaceError(msgId, updateMonitor);
+ }
return false;
}
@@ -1152,7 +1167,7 @@ public class KeyguardIndicationController {
@Override
public void onTrustChanged(int userId) {
- if (KeyguardUpdateMonitor.getCurrentUser() != userId) {
+ if (getCurrentUser() != userId) {
return;
}
updateDeviceEntryIndication(false);
@@ -1172,7 +1187,7 @@ public class KeyguardIndicationController {
@Override
public void onBiometricRunningStateChanged(boolean running,
BiometricSourceType biometricSourceType) {
- if (running && biometricSourceType == BiometricSourceType.FACE) {
+ if (running && biometricSourceType == FACE) {
// Let's hide any previous messages when authentication starts, otherwise
// multiple auth attempts would overlap.
hideBiometricMessage();
@@ -1186,7 +1201,7 @@ public class KeyguardIndicationController {
super.onBiometricAuthenticated(userId, biometricSourceType, isStrongBiometric);
hideBiometricMessage();
- if (biometricSourceType == BiometricSourceType.FACE
+ if (biometricSourceType == FACE
&& !mKeyguardBypassController.canBypass()) {
showActionToUnlock();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
index 2ca1bebfcf9f..7b49ecdcd981 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInteractionTracker.kt
@@ -1,7 +1,6 @@
package com.android.systemui.statusbar
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.statusbar.notification.NotificationEntryManager
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import javax.inject.Inject
@@ -12,14 +11,12 @@ import javax.inject.Inject
*/
@SysUISingleton
class NotificationInteractionTracker @Inject constructor(
- private val clicker: NotificationClickNotifier,
- private val entryManager: NotificationEntryManager
+ clicker: NotificationClickNotifier,
) : NotifCollectionListener, NotificationInteractionListener {
private val interactions = mutableMapOf<String, Boolean>()
init {
clicker.addNotificationInteractionListener(this)
- entryManager.addCollectionListener(this)
}
fun hasUserInteractedWith(key: String): Boolean {
@@ -38,5 +35,3 @@ class NotificationInteractionTracker @Inject constructor(
interactions[key] = true
}
}
-
-private const val TAG = "NotificationInteractionTracker"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 221428747558..cea3debe6379 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -29,6 +29,8 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
+import androidx.annotation.NonNull;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.R;
@@ -153,6 +155,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
@Override
+ @NonNull
public ExpandableViewState createExpandableViewState() {
return new ShelfState();
}
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 8cb18a06057e..59022c0ffbf2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -50,7 +50,6 @@ import android.util.Pair;
import com.android.internal.messages.nano.SystemMessageProto;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.CoreStartable;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.UiBackground;
@@ -76,20 +75,22 @@ public class InstantAppNotifier extends CoreStartable
private final Executor mUiBgExecutor;
private final ArraySet<Pair<String, Integer>> mCurrentNotifs = new ArraySet<>();
private final CommandQueue mCommandQueue;
- private KeyguardStateController mKeyguardStateController;
+ private final KeyguardStateController mKeyguardStateController;
@Inject
- public InstantAppNotifier(Context context, CommandQueue commandQueue,
- @UiBackground Executor uiBgExecutor) {
+ public InstantAppNotifier(
+ Context context,
+ CommandQueue commandQueue,
+ @UiBackground Executor uiBgExecutor,
+ KeyguardStateController keyguardStateController) {
super(context);
mCommandQueue = commandQueue;
mUiBgExecutor = uiBgExecutor;
+ mKeyguardStateController = keyguardStateController;
}
@Override
public void start() {
- mKeyguardStateController = Dependency.get(KeyguardStateController.class);
-
// listen for user / profile change.
try {
ActivityManager.getService().registerUserSwitchObserver(mUserSwitchListener, TAG);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
deleted file mode 100644
index c9c6f28b5b27..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationListController.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.notification;
-
-import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
-
-import java.util.Objects;
-
-/**
- * Root controller for the list of notifications in the shade.
- *
- * TODO: Much of the code in NotificationPresenter should eventually move in here. It will proxy
- * domain-specific behavior (ARC, etc) to subcontrollers.
- */
-public class NotificationListController {
- private final NotificationEntryManager mEntryManager;
- private final NotificationListContainer mListContainer;
- private final DeviceProvisionedController mDeviceProvisionedController;
-
- public NotificationListController(
- NotificationEntryManager entryManager,
- NotificationListContainer listContainer,
- DeviceProvisionedController deviceProvisionedController) {
- mEntryManager = Objects.requireNonNull(entryManager);
- mListContainer = Objects.requireNonNull(listContainer);
- mDeviceProvisionedController = Objects.requireNonNull(deviceProvisionedController);
- }
-
- /**
- * Causes the controller to register listeners on its dependencies. This method must be called
- * before the controller is ready to perform its duties.
- */
- public void bind() {
- mEntryManager.addNotificationEntryListener(mEntryListener);
- mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
- }
-
- @SuppressWarnings("FieldCanBeLocal")
- private final NotificationEntryListener mEntryListener = new NotificationEntryListener() {
- @Override
- public void onEntryRemoved(
- NotificationEntry entry,
- NotificationVisibility visibility,
- boolean removedByUser,
- int reason) {
- mListContainer.cleanUpViewStateForEntry(entry);
- }
- };
-
- // TODO: (b/145659174) remove after moving to NewNotifPipeline. Replaced by
- // DeviceProvisionedCoordinator
- private final DeviceProvisionedListener mDeviceProvisionedListener =
- new DeviceProvisionedListener() {
- @Override
- public void onDeviceProvisionedChanged() {
- mEntryManager.updateNotifications("device provisioned changed");
- }
- };
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index dbf4810b4fd7..126a986ee5f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -18,10 +18,8 @@ package com.android.systemui.statusbar.notification
import android.animation.ObjectAnimator
import android.util.FloatProperty
-import com.android.systemui.Dumpable
import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.collection.NotificationEntry
@@ -34,20 +32,17 @@ import com.android.systemui.statusbar.phone.panelstate.PanelExpansionChangeEvent
import com.android.systemui.statusbar.phone.panelstate.PanelExpansionListener
import com.android.systemui.statusbar.policy.HeadsUpManager
import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener
-import java.io.PrintWriter
import javax.inject.Inject
import kotlin.math.min
@SysUISingleton
class NotificationWakeUpCoordinator @Inject constructor(
- dumpManager: DumpManager,
private val mHeadsUpManager: HeadsUpManager,
private val statusBarStateController: StatusBarStateController,
private val bypassController: KeyguardBypassController,
private val dozeParameters: DozeParameters,
private val screenOffAnimationController: ScreenOffAnimationController
-) : OnHeadsUpChangedListener, StatusBarStateController.StateListener, PanelExpansionListener,
- Dumpable {
+) : OnHeadsUpChangedListener, StatusBarStateController.StateListener, PanelExpansionListener {
private val mNotificationVisibility = object : FloatProperty<NotificationWakeUpCoordinator>(
"notificationVisibility") {
@@ -65,7 +60,6 @@ class NotificationWakeUpCoordinator @Inject constructor(
private var mLinearDozeAmount: Float = 0.0f
private var mDozeAmount: Float = 0.0f
- private var mDozeAmountSource: String = "init"
private var mNotificationVisibleAmount = 0.0f
private var mNotificationsVisible = false
private var mNotificationsVisibleForExpansion = false
@@ -148,7 +142,6 @@ class NotificationWakeUpCoordinator @Inject constructor(
}
init {
- dumpManager.registerDumpable(this)
mHeadsUpManager.addListener(this)
statusBarStateController.addCallback(this)
addListener(object : WakeUpListener {
@@ -255,14 +248,13 @@ class NotificationWakeUpCoordinator @Inject constructor(
// Let's notify the scroller that an animation started
notifyAnimationStart(mLinearDozeAmount == 1.0f)
}
- setDozeAmount(linear, eased, source = "StatusBar")
+ setDozeAmount(linear, eased)
}
- fun setDozeAmount(linear: Float, eased: Float, source: String) {
+ fun setDozeAmount(linear: Float, eased: Float) {
val changed = linear != mLinearDozeAmount
mLinearDozeAmount = linear
mDozeAmount = eased
- mDozeAmountSource = source
mStackScrollerController.setDozeAmount(mDozeAmount)
updateHideAmount()
if (changed && linear == 0.0f) {
@@ -279,7 +271,7 @@ class NotificationWakeUpCoordinator @Inject constructor(
// undefined state, so it's an indication that we should do state cleanup. We override
// the doze amount to 0f (not dozing) so that the notifications are no longer hidden.
// See: UnlockedScreenOffAnimationController.onFinishedWakingUp()
- setDozeAmount(0f, 0f, source = "Override: Shade->Shade (lock cancelled by unlock)")
+ setDozeAmount(0f, 0f)
}
if (overrideDozeAmountIfAnimatingScreenOff(mLinearDozeAmount)) {
@@ -319,11 +311,12 @@ class NotificationWakeUpCoordinator @Inject constructor(
*/
private fun overrideDozeAmountIfBypass(): Boolean {
if (bypassController.bypassEnabled) {
- if (statusBarStateController.state == StatusBarState.KEYGUARD) {
- setDozeAmount(1f, 1f, source = "Override: bypass (keyguard)")
- } else {
- setDozeAmount(0f, 0f, source = "Override: bypass (shade)")
+ var amount = 1.0f
+ if (statusBarStateController.state == StatusBarState.SHADE ||
+ statusBarStateController.state == StatusBarState.SHADE_LOCKED) {
+ amount = 0.0f
}
+ setDozeAmount(amount, amount)
return true
}
return false
@@ -339,7 +332,7 @@ class NotificationWakeUpCoordinator @Inject constructor(
*/
private fun overrideDozeAmountIfAnimatingScreenOff(linearDozeAmount: Float): Boolean {
if (screenOffAnimationController.overrideNotificationsFullyDozingOnKeyguard()) {
- setDozeAmount(1f, 1f, source = "Override: animating screen off")
+ setDozeAmount(1f, 1f)
return true
}
@@ -433,24 +426,4 @@ class NotificationWakeUpCoordinator @Inject constructor(
*/
@JvmDefault fun onPulseExpansionChanged(expandingChanged: Boolean) {}
}
-
- override fun dump(pw: PrintWriter, args: Array<out String>) {
- pw.println("mLinearDozeAmount: $mLinearDozeAmount")
- pw.println("mDozeAmount: $mDozeAmount")
- pw.println("mDozeAmountSource: $mDozeAmountSource")
- pw.println("mNotificationVisibleAmount: $mNotificationVisibleAmount")
- pw.println("mNotificationsVisible: $mNotificationsVisible")
- pw.println("mNotificationsVisibleForExpansion: $mNotificationsVisibleForExpansion")
- pw.println("mVisibilityAmount: $mVisibilityAmount")
- pw.println("mLinearVisibilityAmount: $mLinearVisibilityAmount")
- pw.println("pulseExpanding: $pulseExpanding")
- pw.println("state: ${StatusBarState.toString(state)}")
- pw.println("fullyAwake: $fullyAwake")
- pw.println("wakingUp: $wakingUp")
- pw.println("willWakeUp: $willWakeUp")
- pw.println("collapsedEnoughToHide: $collapsedEnoughToHide")
- pw.println("pulsing: $pulsing")
- pw.println("notificationsFullyHidden: $notificationsFullyHidden")
- pw.println("canShowPulsingHuns: $canShowPulsingHuns")
- }
-}
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
index 385fbb5ccdee..be9f133c9aeb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerImpl.kt
@@ -27,20 +27,20 @@ import com.android.systemui.statusbar.notification.AnimatedImageNotificationMana
import com.android.systemui.statusbar.notification.NotificationActivityStarter
import com.android.systemui.statusbar.notification.NotificationClicker
import com.android.systemui.statusbar.notification.NotificationEntryManager
-import com.android.systemui.statusbar.notification.NotificationListController
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore
import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.TargetSdkResolver
import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
import com.android.systemui.statusbar.notification.collection.init.NotifPipelineInitializer
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
import com.android.systemui.statusbar.notification.collection.render.NotifStackController
import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
import com.android.systemui.statusbar.notification.logging.NotificationLogger
import com.android.systemui.statusbar.notification.row.NotifBindPipelineInitializer
import com.android.systemui.statusbar.notification.stack.NotificationListContainer
import com.android.systemui.statusbar.phone.CentralSurfaces
-import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.wm.shell.bubbles.Bubbles
import dagger.Lazy
import java.io.PrintWriter
@@ -65,7 +65,6 @@ class NotificationsControllerImpl @Inject constructor(
private val notifPipelineInitializer: Lazy<NotifPipelineInitializer>,
private val notifBindPipelineInitializer: NotifBindPipelineInitializer,
private val notificationLogger: NotificationLogger,
- private val deviceProvisionedController: DeviceProvisionedController,
private val notificationRowBinder: NotificationRowBinderImpl,
private val notificationsMediaManager: NotificationMediaManager,
private val headsUpViewBinder: HeadsUpViewBinder,
@@ -85,12 +84,11 @@ class NotificationsControllerImpl @Inject constructor(
) {
notificationListener.registerAsSystemService()
- val listController =
- NotificationListController(
- entryManager,
- listContainer,
- deviceProvisionedController)
- listController.bind()
+ notifPipeline.get().addCollectionListener(object : NotifCollectionListener {
+ override fun onEntryRemoved(entry: NotificationEntry, reason: Int) {
+ listContainer.cleanUpViewStateForEntry(entry)
+ }
+ })
notificationRowBinder.setNotificationClicker(
clickerBuilder.build(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 855390d75ff8..8574f872ad9c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -25,8 +25,6 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -68,6 +66,9 @@ import android.widget.Chronometer;
import android.widget.FrameLayout;
import android.widget.ImageView;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -3247,6 +3248,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
@Override
+ @NonNull
public ExpandableViewState createExpandableViewState() {
return new NotificationViewState();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index 8f73b802271d..1e09b8a37645 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -29,6 +29,7 @@ import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.FrameLayout;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.systemui.Dumpable;
@@ -66,7 +67,7 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
protected float mContentTransformationAmount;
protected boolean mIsLastChild;
protected int mContentShift;
- private final ExpandableViewState mViewState;
+ @NonNull private final ExpandableViewState mViewState;
private float mContentTranslation;
protected boolean mLastInSection;
protected boolean mFirstInSection;
@@ -610,6 +611,7 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
public void setActualHeightAnimating(boolean animating) {}
+ @NonNull
protected ExpandableViewState createExpandableViewState() {
return new ExpandableViewState();
}
@@ -642,7 +644,12 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
return mViewState;
}
- @Nullable public ExpandableViewState getViewState() {
+ /**
+ * Get the {@link ExpandableViewState} associated with the view.
+ *
+ * @return the ExpandableView's view state.
+ */
+ @NonNull public ExpandableViewState getViewState() {
return mViewState;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
index e43ecf70a308..49dc6550a51f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
@@ -23,6 +23,8 @@ import android.util.AttributeSet;
import android.util.IndentingPrintWriter;
import android.view.View;
+import androidx.annotation.NonNull;
+
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
import com.android.systemui.statusbar.notification.stack.ViewState;
@@ -142,6 +144,7 @@ public class FooterView extends StackScrollerDecorView {
}
@Override
+ @NonNull
public ExpandableViewState createExpandableViewState() {
return new FooterViewState();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
deleted file mode 100644
index 6abfee9818bc..000000000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification.row;
-
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
-
-import android.content.Context;
-import android.metrics.LogMaker;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
-import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
-import com.android.systemui.statusbar.notification.logging.NotificationCounters;
-import com.android.systemui.util.Compile;
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Manager for the notification blocking helper - tracks and helps create the blocking helper
- * affordance.
- */
-public class NotificationBlockingHelperManager {
- /** Enables debug logging and always makes the blocking helper show up after a dismiss. */
- private static final String TAG = "BlockingHelper";
- private static final boolean DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG);
- private static final boolean DEBUG_ALWAYS_SHOW = false;
-
- private final Context mContext;
- private final NotificationGutsManager mNotificationGutsManager;
- private final NotificationEntryManager mNotificationEntryManager;
- private final MetricsLogger mMetricsLogger;
- private final GroupMembershipManager mGroupMembershipManager;
- /** Row that the blocking helper will be shown in (via {@link NotificationGuts}. */
- private ExpandableNotificationRow mBlockingHelperRow;
- private Set<String> mNonBlockablePkgs;
-
- /**
- * Whether the notification shade/stack is expanded - used to determine blocking helper
- * eligibility.
- */
- private boolean mIsShadeExpanded;
-
- /**
- * Injected constructor. See {@link NotificationsModule}.
- */
- public NotificationBlockingHelperManager(
- Context context,
- NotificationGutsManager notificationGutsManager,
- NotificationEntryManager notificationEntryManager,
- MetricsLogger metricsLogger,
- GroupMembershipManager groupMembershipManager) {
- mContext = context;
- mNotificationGutsManager = notificationGutsManager;
- mNotificationEntryManager = notificationEntryManager;
- mMetricsLogger = metricsLogger;
- mNonBlockablePkgs = new HashSet<>();
- Collections.addAll(mNonBlockablePkgs, mContext.getResources().getStringArray(
- com.android.internal.R.array.config_nonBlockableNotificationPackages));
- mGroupMembershipManager = groupMembershipManager;
- }
-
- /**
- * Potentially shows the blocking helper, represented via the {@link NotificationInfo} menu
- * item, in the current row if user sentiment is negative.
- *
- * @param row row to render the blocking helper in
- * @param menuRow menu used to generate the {@link NotificationInfo} view that houses the
- * blocking helper UI
- * @return whether we're showing a blocking helper in the given notification row
- */
- boolean perhapsShowBlockingHelper(
- ExpandableNotificationRow row, NotificationMenuRowPlugin menuRow) {
- // We only show the blocking helper if:
- // - User sentiment is negative (DEBUG flag can bypass)
- // - The notification shade is fully expanded (guarantees we're not touching a HUN).
- // - The row is blockable (i.e. not non-blockable)
- // - The dismissed row is a valid group (>1 or 0 children from the same channel)
- // or the only child in the group
- final NotificationEntry entry = row.getEntry();
- if ((entry.getUserSentiment() == USER_SENTIMENT_NEGATIVE || DEBUG_ALWAYS_SHOW)
- && mIsShadeExpanded
- && !row.getIsNonblockable()
- && ((!row.isChildInGroup() || mGroupMembershipManager.isOnlyChildInGroup(entry))
- && row.getNumUniqueChannels() <= 1)) {
- // Dismiss any current blocking helper before continuing forward (only one can be shown
- // at a given time).
- dismissCurrentBlockingHelper();
-
- if (DEBUG) {
- Log.d(TAG, "Manager.perhapsShowBlockingHelper: Showing new blocking helper");
- }
-
- // Enable blocking helper on the row before moving forward so everything in the guts is
- // correctly prepped.
- mBlockingHelperRow = row;
- mBlockingHelperRow.setBlockingHelperShowing(true);
-
- // Log triggering of blocking helper by the system. This log line
- // should be emitted before the "display" log line.
- mMetricsLogger.write(
- getLogMaker().setSubtype(MetricsEvent.BLOCKING_HELPER_TRIGGERED_BY_SYSTEM));
-
- // We don't care about the touch origin (x, y) since we're opening guts without any
- // explicit user interaction.
- mNotificationGutsManager.openGuts(
- mBlockingHelperRow, 0, 0, menuRow.getLongpressMenuItem(mContext));
-
- mMetricsLogger.count(NotificationCounters.BLOCKING_HELPER_SHOWN, 1);
- return true;
- }
- return false;
- }
-
- /**
- * Dismiss the currently showing blocking helper, if any, through a notification update.
- *
- * @return whether the blocking helper was dismissed
- */
- boolean dismissCurrentBlockingHelper() {
- if (!isBlockingHelperRowNull()) {
- if (DEBUG) {
- Log.d(TAG, "Manager.dismissCurrentBlockingHelper: Dismissing current helper");
- }
- if (!mBlockingHelperRow.isBlockingHelperShowing()) {
- Log.e(TAG, "Manager.dismissCurrentBlockingHelper: "
- + "Non-null row is not showing a blocking helper");
- }
-
- mBlockingHelperRow.setBlockingHelperShowing(false);
- if (mBlockingHelperRow.isAttachedToWindow()) {
- mNotificationEntryManager.updateNotifications("dismissCurrentBlockingHelper");
- }
- mBlockingHelperRow = null;
- return true;
- }
- return false;
- }
-
- /**
- * Update the expansion status of the notification shade/stack.
- *
- * @param expandedHeight how much the shade is expanded ({code 0} indicating it's collapsed)
- */
- public void setNotificationShadeExpanded(float expandedHeight) {
- mIsShadeExpanded = expandedHeight > 0.0f;
- }
-
- /**
- * Returns whether the given package name is in the list of non-blockable packages.
- */
- public boolean isNonblockable(String packageName, String channelName) {
- return mNonBlockablePkgs.contains(packageName)
- || mNonBlockablePkgs.contains(makeChannelKey(packageName, channelName));
- }
-
- private LogMaker getLogMaker() {
- return mBlockingHelperRow.getEntry().getSbn()
- .getLogMaker()
- .setCategory(MetricsEvent.NOTIFICATION_BLOCKING_HELPER);
- }
-
- // Format must stay in sync with frameworks/base/core/res/res/values/config.xml
- // config_nonBlockableNotificationPackages
- private String makeChannelKey(String pkg, String channel) {
- return pkg + ":" + channel;
- }
-
- @VisibleForTesting
- boolean isBlockingHelperRowNull() {
- return mBlockingHelperRow == null;
- }
-
- @VisibleForTesting
- void setBlockingHelperRowForTest(ExpandableNotificationRow blockingHelperRowForTest) {
- mBlockingHelperRow = blockingHelperRowForTest;
- }
-
- @VisibleForTesting
- void setNonBlockablePkgs(String[] pkgsAndChannels) {
- mNonBlockablePkgs = new HashSet<>();
- Collections.addAll(mNonBlockablePkgs, pkgsAndChannels);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index cc87499d39cb..1fb265fea0b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -4460,8 +4460,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
}
private void updateVisibility() {
- boolean shouldShow = !mAmbientState.isFullyHidden() || !onKeyguard();
- setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
+ mController.updateVisibility(!mAmbientState.isFullyHidden() || !onKeyguard());
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
@@ -4526,17 +4525,21 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- void updateEmptyShadeView(boolean visible, boolean notifVisibleInShade) {
+ void updateEmptyShadeView(boolean visible, boolean areNotificationsHiddenInShade) {
mEmptyShadeView.setVisible(visible, mIsExpanded && mAnimationsEnabled);
int oldTextRes = mEmptyShadeView.getTextResource();
- int newTextRes = notifVisibleInShade
+ int newTextRes = areNotificationsHiddenInShade
? R.string.dnd_suppressing_shade_text : R.string.empty_shade_text;
if (oldTextRes != newTextRes) {
mEmptyShadeView.setText(newTextRes);
}
}
+ public boolean isEmptyShadeViewVisible() {
+ return mEmptyShadeView.isVisible();
+ }
+
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void updateFooterView(boolean visible, boolean showDismissView, boolean showHistory) {
if (mFooterView == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index e6eceb555897..ec1e6207ef8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -177,7 +177,6 @@ public class NotificationStackScrollLayoutController {
private NotificationStackScrollLayout mView;
private boolean mFadeNotificationsOnDismiss;
private NotificationSwipeHelper mSwipeHelper;
- private boolean mShowEmptyShadeView;
@Nullable private Boolean mHistoryEnabled;
private int mBarState;
private HeadsUpAppearanceController mHeadsUpAppearanceController;
@@ -1173,8 +1172,21 @@ public class NotificationStackScrollLayoutController {
}
/**
- * Update whether we should show the empty shade view (no notifications in the shade).
- * If so, send the update to our view.
+ * Set the visibility of the view, and propagate it to specific children.
+ *
+ * @param visible either the view is visible or not.
+ */
+ public void updateVisibility(boolean visible) {
+ mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+
+ if (mView.getVisibility() == View.VISIBLE) {
+ // Synchronize EmptyShadeView visibility with the parent container.
+ updateShowEmptyShadeView();
+ }
+ }
+
+ /**
+ * Update whether we should show the empty shade view ("no notifications" in the shade).
*
* When in split mode, notifications are always visible regardless of the state of the
* QuickSettings panel. That being the case, empty view is always shown if the other conditions
@@ -1182,18 +1194,31 @@ public class NotificationStackScrollLayoutController {
*/
public void updateShowEmptyShadeView() {
Trace.beginSection("NSSLC.updateShowEmptyShadeView");
- mShowEmptyShadeView = mStatusBarStateController.getCurrentOrUpcomingState() != KEYGUARD
+
+ final boolean shouldShow = getVisibleNotificationCount() == 0
&& !mView.isQsFullScreen()
- && getVisibleNotificationCount() == 0;
+ // Hide empty shade view when in transition to Keyguard.
+ // That avoids "No Notifications" to blink when transitioning to AOD.
+ // For more details, see: b/228790482
+ && !isInTransitionToKeyguard();
+
+ mView.updateEmptyShadeView(shouldShow, mZenModeController.areNotificationsHiddenInShade());
- mView.updateEmptyShadeView(
- mShowEmptyShadeView,
- mZenModeController.areNotificationsHiddenInShade());
Trace.endSection();
}
+ /**
+ * @return true if {@link StatusBarStateController} is in transition to the KEYGUARD
+ * and false otherwise.
+ */
+ private boolean isInTransitionToKeyguard() {
+ final int currentState = mStatusBarStateController.getState();
+ final int upcomingState = mStatusBarStateController.getCurrentOrUpcomingState();
+ return (currentState != upcomingState && upcomingState == KEYGUARD);
+ }
+
public boolean isShowingEmptyShadeView() {
- return mShowEmptyShadeView;
+ return mView.isEmptyShadeViewVisible();
}
public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 6d513d0da5c1..353355bef7bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -120,11 +120,64 @@ public class StackScrollAlgorithm {
updateClipping(algorithmState, ambientState);
updateSpeedBumpState(algorithmState, speedBumpIndex);
updateShelfState(algorithmState, ambientState);
+ updateAlphaState(algorithmState, ambientState);
getNotificationChildrenStates(algorithmState, ambientState);
}
+ private void updateAlphaState(StackScrollAlgorithmState algorithmState,
+ AmbientState ambientState) {
+ for (ExpandableView view : algorithmState.visibleChildren) {
+ final ViewState viewState = view.getViewState();
+
+ final boolean isHunGoingToShade = ambientState.isShadeExpanded()
+ && view == ambientState.getTrackedHeadsUpRow();
+
+ if (isHunGoingToShade) {
+ // Keep 100% opacity for heads up notification going to shade.
+ viewState.alpha = 1f;
+ } else if (ambientState.isOnKeyguard()) {
+ // Adjust alpha for wakeup to lockscreen.
+ viewState.alpha = 1f - ambientState.getHideAmount();
+ } else if (ambientState.isExpansionChanging()) {
+ // Adjust alpha for shade open & close.
+ float expansion = ambientState.getExpansionFraction();
+ viewState.alpha = ambientState.isBouncerInTransit()
+ ? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion)
+ : ShadeInterpolation.getContentAlpha(expansion);
+ }
+
+ // For EmptyShadeView if on keyguard, we need to control the alpha to create
+ // a nice transition when the user is dragging down the notification panel.
+ if (view instanceof EmptyShadeView && ambientState.isOnKeyguard()) {
+ final float fractionToShade = ambientState.getFractionToShade();
+ viewState.alpha = ShadeInterpolation.getContentAlpha(fractionToShade);
+ }
+
+ NotificationShelf shelf = ambientState.getShelf();
+ if (shelf != null) {
+ final ViewState shelfState = shelf.getViewState();
+
+ // After the shelf has updated its yTranslation, explicitly set alpha=0 for view
+ // below shelf to skip rendering them in the hardware layer. We do not set them
+ // invisible because that runs invalidate & onDraw when these views return onscreen,
+ // which is more expensive.
+ if (shelfState.hidden) {
+ // When the shelf is hidden, it won't clip views, so we don't hide rows
+ return;
+ }
+
+ final float shelfTop = shelfState.yTranslation;
+ final float viewTop = viewState.yTranslation;
+ if (viewTop >= shelfTop) {
+ viewState.alpha = 0;
+ }
+ }
+ }
+ }
+
/**
* How expanded or collapsed notifications are when pulling down the shade.
+ *
* @param ambientState Current ambient state.
* @return 0 when fully collapsed, 1 when expanded.
*/
@@ -208,22 +261,6 @@ public class StackScrollAlgorithm {
}
shelf.updateState(algorithmState, ambientState);
-
- // After the shelf has updated its yTranslation, explicitly set alpha=0 for view below shelf
- // to skip rendering them in the hardware layer. We do not set them invisible because that
- // runs invalidate & onDraw when these views return onscreen, which is more expensive.
- if (shelf.getViewState().hidden) {
- // When the shelf is hidden, it won't clip views, so we don't hide rows
- return;
- }
- final float shelfTop = shelf.getViewState().yTranslation;
-
- for (ExpandableView view : algorithmState.visibleChildren) {
- final float viewTop = view.getViewState().yTranslation;
- if (viewTop >= shelfTop) {
- view.getViewState().alpha = 0;
- }
- }
}
private void updateClipping(StackScrollAlgorithmState algorithmState,
@@ -473,21 +510,6 @@ public class StackScrollAlgorithm {
ExpandableViewState viewState = view.getViewState();
viewState.location = ExpandableViewState.LOCATION_UNKNOWN;
- final boolean isHunGoingToShade = ambientState.isShadeExpanded()
- && view == ambientState.getTrackedHeadsUpRow();
- if (isHunGoingToShade) {
- // Keep 100% opacity for heads up notification going to shade.
- } else if (ambientState.isOnKeyguard()) {
- // Adjust alpha for wakeup to lockscreen.
- viewState.alpha = 1f - ambientState.getHideAmount();
- } else if (ambientState.isExpansionChanging()) {
- // Adjust alpha for shade open & close.
- float expansion = ambientState.getExpansionFraction();
- viewState.alpha = ambientState.isBouncerInTransit()
- ? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(expansion)
- : ShadeInterpolation.getContentAlpha(expansion);
- }
-
final float expansionFraction = getExpansionFractionWithoutShelf(
algorithmState, ambientState);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
index 747c4debb771..52a45d6785ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesCommandQueueCallbacks.java
@@ -55,7 +55,6 @@ import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.qs.QSPanelController;
-import com.android.systemui.shade.NotificationPanelView;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.statusbar.CommandQueue;
@@ -326,12 +325,12 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
mNotificationPanelViewController.expand(true /* animate */);
mNotificationStackScrollLayoutController.setWillExpand(true);
mHeadsUpManager.unpinAll(true /* userUnpinned */);
- mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN, 1);
+ mMetricsLogger.count("panel_open", 1);
} else if (!mNotificationPanelViewController.isInSettings()
&& !mNotificationPanelViewController.isExpanding()) {
mNotificationPanelViewController.flingSettings(0 /* velocity */,
- NotificationPanelView.FLING_EXPAND);
- mMetricsLogger.count(NotificationPanelView.COUNTER_PANEL_OPEN_QS, 1);
+ NotificationPanelViewController.FLING_EXPAND);
+ mMetricsLogger.count("panel_open_qs", 1);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index ed186ab6a10b..8273d5737c2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -33,7 +33,6 @@ import android.widget.LinearLayout.LayoutParams;
import androidx.annotation.VisibleForTesting;
import com.android.internal.statusbar.StatusBarIcon;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.demomode.DemoModeCommandReceiver;
@@ -137,11 +136,12 @@ public interface StatusBarIconController {
LinearLayout linearLayout,
FeatureFlags featureFlags,
StatusBarPipelineFlags statusBarPipelineFlags,
- Provider<WifiViewModel> wifiViewModelProvider) {
+ Provider<WifiViewModel> wifiViewModelProvider,
+ DarkIconDispatcher darkIconDispatcher) {
super(linearLayout, featureFlags, statusBarPipelineFlags, wifiViewModelProvider);
mIconHPadding = mContext.getResources().getDimensionPixelSize(
R.dimen.status_bar_icon_padding);
- mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
+ mDarkIconDispatcher = darkIconDispatcher;
}
@Override
@@ -198,20 +198,24 @@ public interface StatusBarIconController {
private final FeatureFlags mFeatureFlags;
private final StatusBarPipelineFlags mStatusBarPipelineFlags;
private final Provider<WifiViewModel> mWifiViewModelProvider;
+ private final DarkIconDispatcher mDarkIconDispatcher;
@Inject
public Factory(
FeatureFlags featureFlags,
StatusBarPipelineFlags statusBarPipelineFlags,
- Provider<WifiViewModel> wifiViewModelProvider) {
+ Provider<WifiViewModel> wifiViewModelProvider,
+ DarkIconDispatcher darkIconDispatcher) {
mFeatureFlags = featureFlags;
mStatusBarPipelineFlags = statusBarPipelineFlags;
mWifiViewModelProvider = wifiViewModelProvider;
+ mDarkIconDispatcher = darkIconDispatcher;
}
public DarkIconManager create(LinearLayout group) {
return new DarkIconManager(
- group, mFeatureFlags, mStatusBarPipelineFlags, mWifiViewModelProvider);
+ group, mFeatureFlags, mStatusBarPipelineFlags, mWifiViewModelProvider,
+ mDarkIconDispatcher);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
index 77654273bde4..103f3fc21f91 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt
@@ -46,7 +46,7 @@ import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.flow.stateIn
/**
* Provides data related to the wifi state.
@@ -118,12 +118,19 @@ class WifiRepositoryImpl @Inject constructor(
}
}
- trySend(WIFI_NETWORK_DEFAULT)
connectivityManager.registerNetworkCallback(WIFI_NETWORK_CALLBACK_REQUEST, callback)
awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
}
- .shareIn(scope, started = SharingStarted.WhileSubscribed())
+ // There will be multiple wifi icons in different places that will frequently
+ // subscribe/unsubscribe to flows as the views attach/detach. Using [stateIn] ensures that
+ // new subscribes will get the latest value immediately upon subscription. Otherwise, the
+ // views could show stale data. See b/244173280.
+ .stateIn(
+ scope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = WIFI_NETWORK_DEFAULT
+ )
override val wifiActivity: Flow<WifiActivityModel> =
if (wifiManager == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
index 169347a5ac1a..163060814545 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
@@ -49,6 +49,7 @@ import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.phone.UserAvatarView;
+import com.android.systemui.user.data.source.UserRecord;
import com.android.systemui.util.ViewController;
import javax.inject.Inject;
@@ -79,7 +80,7 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
@VisibleForTesting
UserAvatarView mUserAvatarView;
private View mUserAvatarViewWithBackground;
- UserSwitcherController.UserRecord mCurrentUser;
+ UserRecord mCurrentUser;
private boolean mIsKeyguardShowing;
// State info for the user switch and keyguard
@@ -269,10 +270,10 @@ public class KeyguardQsUserSwitchController extends ViewController<FrameLayout>
* @return true if the current user has changed
*/
private boolean updateCurrentUser() {
- UserSwitcherController.UserRecord previousUser = mCurrentUser;
+ UserRecord previousUser = mCurrentUser;
mCurrentUser = null;
for (int i = 0; i < mAdapter.getCount(); i++) {
- UserSwitcherController.UserRecord r = mAdapter.getItem(i);
+ UserRecord r = mAdapter.getItem(i);
if (r.isCurrent) {
mCurrentUser = r;
return !mCurrentUser.equals(previousUser);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
index 03ab888d1253..e2f5734cb4f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherController.java
@@ -52,6 +52,7 @@ import com.android.systemui.statusbar.notification.stack.AnimationProperties;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
+import com.android.systemui.user.data.source.UserRecord;
import com.android.systemui.util.ViewController;
import java.util.ArrayList;
@@ -287,8 +288,8 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS
}
KeyguardUserDetailItemView newView = (KeyguardUserDetailItemView)
mAdapter.getView(i, oldView, mListView);
- UserSwitcherController.UserRecord userTag =
- (UserSwitcherController.UserRecord) newView.getTag();
+ UserRecord userTag =
+ (UserRecord) newView.getTag();
if (userTag.isCurrent) {
if (i != 0) {
Log.w(TAG, "Current user is not the first view in the list");
@@ -443,7 +444,7 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS
private KeyguardUserSwitcherController mKeyguardUserSwitcherController;
private View mCurrentUserView;
// List of users where the first entry is always the current user
- private ArrayList<UserSwitcherController.UserRecord> mUsersOrdered = new ArrayList<>();
+ private ArrayList<UserRecord> mUsersOrdered = new ArrayList<>();
KeyguardUserAdapter(Context context, Resources resources, LayoutInflater layoutInflater,
UserSwitcherController controller,
@@ -464,10 +465,10 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS
}
void refreshUserOrder() {
- ArrayList<UserSwitcherController.UserRecord> users = super.getUsers();
+ ArrayList<UserRecord> users = super.getUsers();
mUsersOrdered = new ArrayList<>(users.size());
for (int i = 0; i < users.size(); i++) {
- UserSwitcherController.UserRecord record = users.get(i);
+ UserRecord record = users.get(i);
if (record.isCurrent) {
mUsersOrdered.add(0, record);
} else {
@@ -477,19 +478,19 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS
}
@Override
- protected ArrayList<UserSwitcherController.UserRecord> getUsers() {
+ protected ArrayList<UserRecord> getUsers() {
return mUsersOrdered;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
- UserSwitcherController.UserRecord item = getItem(position);
+ UserRecord item = getItem(position);
return createUserDetailItemView(convertView, parent, item);
}
KeyguardUserDetailItemView convertOrInflate(View convertView, ViewGroup parent) {
if (!(convertView instanceof KeyguardUserDetailItemView)
- || !(convertView.getTag() instanceof UserSwitcherController.UserRecord)) {
+ || !(convertView.getTag() instanceof UserRecord)) {
convertView = mLayoutInflater.inflate(
R.layout.keyguard_user_switcher_item, parent, false);
}
@@ -497,7 +498,7 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS
}
KeyguardUserDetailItemView createUserDetailItemView(View convertView, ViewGroup parent,
- UserSwitcherController.UserRecord item) {
+ UserRecord item) {
KeyguardUserDetailItemView v = convertOrInflate(convertView, parent);
v.setOnClickListener(this);
@@ -513,7 +514,7 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS
v.bind(name, drawable, item.info.id);
}
v.setActivated(item.isCurrent);
- v.setDisabledByAdmin(item.isDisabledByAdmin);
+ v.setDisabledByAdmin(mController.isDisabledByAdmin(item));
v.setEnabled(item.isSwitchToEnabled);
v.setAlpha(v.isEnabled() ? USER_SWITCH_ENABLED_ALPHA : USER_SWITCH_DISABLED_ALPHA);
@@ -524,7 +525,7 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS
return v;
}
- private Drawable getDrawable(UserSwitcherController.UserRecord item) {
+ private Drawable getDrawable(UserRecord item) {
Drawable drawable;
if (item.isCurrent && item.isGuest) {
drawable = mContext.getDrawable(R.drawable.ic_avatar_guest_user);
@@ -547,7 +548,7 @@ public class KeyguardUserSwitcherController extends ViewController<KeyguardUserS
@Override
public void onClick(View v) {
- UserSwitcherController.UserRecord user = (UserSwitcherController.UserRecord) v.getTag();
+ UserRecord user = (UserRecord) v.getTag();
if (mKeyguardUserSwitcherController.isListAnimating()) {
return;
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 836d57131fac..e2d16015235e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -45,6 +45,7 @@ import android.os.UserManager;
import android.provider.Settings;
import android.telephony.TelephonyCallback;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -54,6 +55,7 @@ import android.widget.BaseAdapter;
import android.widget.Toast;
import androidx.annotation.Nullable;
+import androidx.collection.SimpleArrayMap;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.jank.InteractionJankMonitor;
@@ -83,6 +85,7 @@ import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.user.CreateUserActivity;
+import com.android.systemui.user.data.source.UserRecord;
import com.android.systemui.util.settings.GlobalSettings;
import com.android.systemui.util.settings.SecureSettings;
@@ -138,6 +141,9 @@ public class UserSwitcherController implements Dumpable {
private final InteractionJankMonitor mInteractionJankMonitor;
private final LatencyTracker mLatencyTracker;
private final DialogLaunchAnimator mDialogLaunchAnimator;
+ private final SimpleArrayMap<UserRecord, EnforcedAdmin> mEnforcedAdminByUserRecord =
+ new SimpleArrayMap<>();
+ private final ArraySet<UserRecord> mDisabledByAdmin = new ArraySet<>();
private ArrayList<UserRecord> mUsers = new ArrayList<>();
@VisibleForTesting
@@ -975,6 +981,21 @@ public class UserSwitcherController implements Dumpable {
return mKeyguardStateController;
}
+ /**
+ * Returns the {@link EnforcedAdmin} for the given record, or {@code null} if there isn't one.
+ */
+ @Nullable
+ public EnforcedAdmin getEnforcedAdmin(UserRecord record) {
+ return mEnforcedAdminByUserRecord.get(record);
+ }
+
+ /**
+ * Returns {@code true} if the given record is disabled by the admin; {@code false} otherwise.
+ */
+ public boolean isDisabledByAdmin(UserRecord record) {
+ return mDisabledByAdmin.contains(record);
+ }
+
public static abstract class BaseUserAdapter extends BaseAdapter {
final UserSwitcherController mController;
@@ -1106,11 +1127,11 @@ public class UserSwitcherController implements Dumpable {
UserManager.DISALLOW_ADD_USER, mUserTracker.getUserId());
if (admin != null && !RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
UserManager.DISALLOW_ADD_USER, mUserTracker.getUserId())) {
- record.isDisabledByAdmin = true;
- record.enforcedAdmin = admin;
+ mDisabledByAdmin.add(record);
+ mEnforcedAdminByUserRecord.put(record, admin);
} else {
- record.isDisabledByAdmin = false;
- record.enforcedAdmin = null;
+ mDisabledByAdmin.remove(record);
+ mEnforcedAdminByUserRecord.put(record, null);
}
}
@@ -1152,74 +1173,6 @@ public class UserSwitcherController implements Dumpable {
}
}
- public static final class UserRecord {
- public final UserInfo info;
- public final Bitmap picture;
- public final boolean isGuest;
- public final boolean isCurrent;
- public final boolean isAddUser;
- public final boolean isAddSupervisedUser;
- /** If true, the record is only visible to the owner and only when unlocked. */
- public final boolean isRestricted;
- public boolean isDisabledByAdmin;
- public EnforcedAdmin enforcedAdmin;
- public boolean isSwitchToEnabled;
-
- public UserRecord(UserInfo info, Bitmap picture, boolean isGuest, boolean isCurrent,
- boolean isAddUser, boolean isRestricted, boolean isSwitchToEnabled,
- boolean isAddSupervisedUser) {
- this.info = info;
- this.picture = picture;
- this.isGuest = isGuest;
- this.isCurrent = isCurrent;
- this.isAddUser = isAddUser;
- this.isRestricted = isRestricted;
- this.isSwitchToEnabled = isSwitchToEnabled;
- this.isAddSupervisedUser = isAddSupervisedUser;
- }
-
- public UserRecord copyWithIsCurrent(boolean _isCurrent) {
- return new UserRecord(info, picture, isGuest, _isCurrent, isAddUser, isRestricted,
- isSwitchToEnabled, isAddSupervisedUser);
- }
-
- public int resolveId() {
- if (isGuest || info == null) {
- return UserHandle.USER_NULL;
- }
- return info.id;
- }
-
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("UserRecord(");
- if (info != null) {
- sb.append("name=\"").append(info.name).append("\" id=").append(info.id);
- } else {
- if (isGuest) {
- sb.append("<add guest placeholder>");
- } else if (isAddUser) {
- sb.append("<add user placeholder>");
- }
- }
- if (isGuest) sb.append(" <isGuest>");
- if (isAddUser) sb.append(" <isAddUser>");
- if (isAddSupervisedUser) sb.append(" <isAddSupervisedUser>");
- if (isCurrent) sb.append(" <isCurrent>");
- if (picture != null) sb.append(" <hasPicture>");
- if (isRestricted) sb.append(" <isRestricted>");
- if (isDisabledByAdmin) {
- sb.append(" <isDisabledByAdmin>");
- sb.append(" enforcedAdmin=").append(enforcedAdmin);
- }
- if (isSwitchToEnabled) {
- sb.append(" <isSwitchToEnabled>");
- }
- sb.append(')');
- return sb.toString();
- }
- }
-
private final KeyguardStateController.Callback mCallback =
new KeyguardStateController.Callback() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt b/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
index 80c55c0bad07..ff0f0d48a7c5 100644
--- a/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt
@@ -51,7 +51,7 @@ import com.android.systemui.statusbar.policy.UserSwitcherController
import com.android.systemui.statusbar.policy.UserSwitcherController.BaseUserAdapter
import com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA
import com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA
-import com.android.systemui.statusbar.policy.UserSwitcherController.UserRecord
+import com.android.systemui.user.data.source.UserRecord
import javax.inject.Inject
import kotlin.math.ceil
@@ -81,16 +81,17 @@ class UserSwitcherActivity @Inject constructor(
}
}
// When the add users options become available, insert another option to manage users
- private val manageUserRecord = UserRecord(
- null /* info */,
- null /* picture */,
- false /* isGuest */,
- false /* isCurrent */,
- false /* isAddUser */,
- false /* isRestricted */,
- false /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */
- )
+ private val manageUserRecord =
+ UserRecord(
+ null /* info */,
+ null /* picture */,
+ false /* isGuest */,
+ false /* isCurrent */,
+ false /* isAddUser */,
+ false /* isRestricted */,
+ false /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */
+ )
private val adapter = object : BaseUserAdapter(userSwitcherController) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
diff --git a/packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt b/packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt
new file mode 100644
index 000000000000..6ab6d7d7891a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package com.android.systemui.user.data.source
+
+import android.content.pm.UserInfo
+import android.graphics.Bitmap
+import android.os.UserHandle
+
+/**
+ * Encapsulates raw data for a user or an option item related to managing users on the device.
+ */
+data class UserRecord(
+ /** Relevant user information. If `null`, this record is not a user but an option item. */
+ @JvmField
+ val info: UserInfo?,
+ /** An image representing the user. */
+ @JvmField
+ val picture: Bitmap?,
+ /** Whether this record represents an option to switch to a guest user. */
+ @JvmField
+ val isGuest: Boolean,
+ /** Whether this record represents the currently-selected user. */
+ @JvmField
+ val isCurrent: Boolean,
+ /** Whether this record represents an option to add another user to the device. */
+ @JvmField
+ val isAddUser: Boolean,
+ /** If true, the record is only visible to the owner and only when unlocked. */
+ @JvmField
+ val isRestricted: Boolean,
+ /** Whether it is possible to switch to this user. */
+ @JvmField
+ val isSwitchToEnabled: Boolean,
+ /** Whether this record represents an option to add another supervised user to the device. */
+ @JvmField
+ val isAddSupervisedUser: Boolean,
+) {
+ /**
+ * Returns a new instance of [UserRecord] with its [isCurrent] set to the given value.
+ */
+ fun copyWithIsCurrent(isCurrent: Boolean): UserRecord {
+ return copy(isCurrent = isCurrent)
+ }
+
+ /**
+ * Returns the user ID for the user represented by this instance or [UserHandle.USER_NULL] if
+ * this instance if a guest or does not represent a user (represents an option item).
+ */
+ fun resolveId(): Int {
+ return if (isGuest || info == null) {
+ UserHandle.USER_NULL
+ } else {
+ info.id
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/OWNERS b/packages/SystemUI/src/com/android/systemui/volume/OWNERS
new file mode 100644
index 000000000000..e627d610dc0a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/OWNERS
@@ -0,0 +1,4 @@
+asc@google.com # send reviews here
+
+juliacr@google.com
+tsuji@google.com
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index aecec9d100cc..d68e8bd36c40 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -387,6 +387,33 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
}
@Test
+ public void onResume_sideFpsHintShouldBeShown_sideFpsHintShown() {
+ setupGetSecurityView();
+ setupConditionsToEnableSideFpsHint();
+ mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
+ reset(mSidefpsController);
+
+ mKeyguardSecurityContainerController.onResume(0);
+
+ verify(mSidefpsController).show();
+ verify(mSidefpsController, never()).hide();
+ }
+
+ @Test
+ public void onResume_sideFpsHintShouldNotBeShown_sideFpsHintHidden() {
+ setupGetSecurityView();
+ setupConditionsToEnableSideFpsHint();
+ setSideFpsHintEnabledFromResources(false);
+ mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
+ reset(mSidefpsController);
+
+ mKeyguardSecurityContainerController.onResume(0);
+
+ verify(mSidefpsController).hide();
+ verify(mSidefpsController, never()).show();
+ }
+
+ @Test
public void showNextSecurityScreenOrFinish_setsSecurityScreenToPinAfterSimPinUnlock() {
// GIVEN the current security method is SimPin
when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index f2ac0c7a7736..28e99da49496 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -57,7 +57,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.policy.UserSwitcherController.UserRecord;
+import com.android.systemui.user.data.source.UserRecord;
import com.android.systemui.util.settings.GlobalSettings;
import org.junit.Before;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index 64a7986d05b1..df10dfe9f160 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -16,7 +16,6 @@ package com.android.systemui;
import static android.view.DisplayCutout.BOUNDS_POSITION_BOTTOM;
import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
-import static android.view.DisplayCutout.BOUNDS_POSITION_LENGTH;
import static android.view.DisplayCutout.BOUNDS_POSITION_RIGHT;
import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
@@ -36,6 +35,7 @@ import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -49,7 +49,6 @@ import android.annotation.IdRes;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.TypedArray;
-import android.graphics.Insets;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -60,7 +59,6 @@ import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
-import android.util.RotationUtils;
import android.util.Size;
import android.view.Display;
import android.view.DisplayCutout;
@@ -80,6 +78,8 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.decor.CornerDecorProvider;
+import com.android.systemui.decor.CutoutDecorProviderFactory;
+import com.android.systemui.decor.CutoutDecorProviderImpl;
import com.android.systemui.decor.DecorProvider;
import com.android.systemui.decor.DecorProviderFactory;
import com.android.systemui.decor.FaceScanningOverlayProviderImpl;
@@ -157,6 +157,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
@Mock
private DisplayInfo mDisplayInfo;
private PrivacyDotViewController.ShowingListener mPrivacyDotShowingListener;
+ @Mock
+ private CutoutDecorProviderFactory mCutoutFactory;
+ private List<DecorProvider> mMockCutoutList;
@Before
public void setup() {
@@ -206,6 +209,11 @@ public class ScreenDecorationsTest extends SysuiTestCase {
DisplayCutout.BOUNDS_POSITION_RIGHT,
R.layout.privacy_dot_bottom_right));
+ // Default no cutout
+ mMockCutoutList = new ArrayList<>();
+ doAnswer(it -> !(mMockCutoutList.isEmpty())).when(mCutoutFactory).getHasProviders();
+ doReturn(mMockCutoutList).when(mCutoutFactory).getProviders();
+
mFaceScanningDecorProvider = spy(new FaceScanningOverlayProviderImpl(
BOUNDS_POSITION_TOP,
mAuthController,
@@ -239,6 +247,11 @@ public class ScreenDecorationsTest extends SysuiTestCase {
super.updateOverlayWindowVisibilityIfViewExists(view);
mExecutor.runAllReady();
}
+
+ @Override
+ protected CutoutDecorProviderFactory getCutoutFactory() {
+ return ScreenDecorationsTest.this.mCutoutFactory;
+ }
});
mScreenDecorations.mDisplayInfo = mDisplayInfo;
doReturn(1f).when(mScreenDecorations).getPhysicalPixelDisplaySizeRatio();
@@ -429,11 +442,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_NoCutout_NoPrivacyDot_NoFaceScanning() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
- // no cutout
- doReturn(null).when(mScreenDecorations).getCutout();
+ // no cutout (default)
mScreenDecorations.start();
// No views added.
@@ -448,11 +459,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_NoCutout_PrivacyDot_NoFaceScanning() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
- // no cutout
- doReturn(null).when(mScreenDecorations).getCutout();
+ // no cutout (default)
mScreenDecorations.start();
@@ -484,11 +493,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_NoCutout_NoPrivacyDot_NoFaceScanning() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
- // no cutout
- doReturn(null).when(mScreenDecorations).getCutout();
+ // no cutout (default)
mScreenDecorations.start();
@@ -516,11 +523,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_NoCutout_PrivacyDot_NoFaceScanning() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
- // no cutout
- doReturn(null).when(mScreenDecorations).getCutout();
+ // no cutout (default)
mScreenDecorations.start();
@@ -555,10 +560,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
- // no cutout
- doReturn(null).when(mScreenDecorations).getCutout();
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
+
+ // no cutout (default)
mScreenDecorations.start();
// Size of corner view should same as rounded_corner_radius{_top|_bottom}
@@ -574,11 +578,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded3px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
- // no cutout
- doReturn(null).when(mScreenDecorations).getCutout();
+ // no cutout (default)
mScreenDecorations.start();
View leftRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_TOP].getRootView()
@@ -611,13 +613,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
// left cutout
- final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
mScreenDecorations.start();
View topRoundedCorner = mScreenDecorations.mOverlays[BOUNDS_POSITION_LEFT].getRootView()
@@ -647,13 +646,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_CutoutShortEdge_NoPrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// Top window is created for top cutout.
@@ -671,13 +667,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_CutoutShortEdge_PrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// Top window is created for top cutout.
@@ -706,13 +699,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_CutoutLongEdge_NoPrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// left cutout
- final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
mScreenDecorations.start();
// Left window is created for left cutout.
@@ -734,13 +724,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_CutoutLongEdge_PrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
// left cutout
- final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
mScreenDecorations.start();
// Left window is created for left cutout.
@@ -762,13 +749,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_CutoutShortEdge_NoPrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// Top window is created for rounded corner and top cutout.
@@ -791,13 +775,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_CutoutShortEdge_PrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// Top window is created for rounded corner and top cutout.
@@ -823,13 +804,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_CutoutLongEdge_NoPrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// left cutout
- final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
mScreenDecorations.start();
// Left window is created for rounded corner and left cutout.
@@ -842,13 +820,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_CutoutLongEdge_PrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
// left cutout
- final Rect[] bounds = {new Rect(0, 50, 1, 60), null, null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
mScreenDecorations.start();
// Left window is created for rounded corner, left cutout, and privacy.
@@ -863,13 +838,11 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_CutoutShortAndLongEdge_NoPrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// top and left cutout
- final Rect[] bounds = {new Rect(0, 50, 1, 60), new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// Top window is created for rounded corner and top cutout.
@@ -883,13 +856,11 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testRounding_CutoutShortAndLongEdge_PrivacyDot() {
setupResources(20 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 20 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 20 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
// top and left cutout
- final Rect[] bounds = {new Rect(0, 50, 1, 60), new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// Top window is created for rounded corner and top cutout.
@@ -905,21 +876,16 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_NoPrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// Set to short edge cutout(top).
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
verifyOverlaysExistAndAdded(false, true, false, false, View.VISIBLE);
// Switch to long edge cutout(left).
- final Rect[] newBounds = {new Rect(0, 50, 1, 60), null, null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), newBounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.set(0, new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
mScreenDecorations.onConfigurationChanged(new Configuration());
verifyOverlaysExistAndAdded(true, false, false, false, View.VISIBLE);
@@ -929,13 +895,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNoRounding_SwitchFrom_ShortEdgeCutout_To_LongCutout_PrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
// Set to short edge cutout(top).
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
verifyOverlaysExistAndAdded(false, true, false, true, View.VISIBLE);
@@ -943,9 +906,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
verify(mDotViewController, times(1)).setShowingListener(null);
// Switch to long edge cutout(left).
- final Rect[] newBounds = {new Rect(0, 50, 1, 60), null, null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(1, 0, 0, 0), newBounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.set(0, new CutoutDecorProviderImpl(BOUNDS_POSITION_LEFT));
mScreenDecorations.onConfigurationChanged(new Configuration());
verifyOverlaysExistAndAdded(true, false, true, false, View.VISIBLE);
@@ -973,20 +934,16 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testDelayedCutout_NoPrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
- // top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ // No cutout (default)
mScreenDecorations.start();
verifyOverlaysExistAndAdded(false, false, false, false, null);
- when(mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout))
- .thenReturn(true);
+ // top cutout
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+
mScreenDecorations.onConfigurationChanged(new Configuration());
// Only top windows should be added.
@@ -997,13 +954,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testDelayedCutout_PrivacyDot() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
- // top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ // no cutout (default)
mScreenDecorations.start();
// Both top and bottom windows should be added with INVISIBLE because of only privacy dot,
@@ -1015,9 +968,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
verify(mDotViewController, times(1)).setShowingListener(
mScreenDecorations.mPrivacyDotShowingListener);
- when(mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout))
- .thenReturn(true);
+ // top cutout
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
+
mScreenDecorations.onConfigurationChanged(new Configuration());
// Both top and bottom windows should be added with VISIBLE because of privacy dot and
@@ -1043,8 +996,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning*/);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning*/);
mDisplayInfo.rotation = Surface.ROTATION_0;
mScreenDecorations.start();
@@ -1058,8 +1010,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded5px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning*/);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning*/);
mDisplayInfo.rotation = Surface.ROTATION_270;
mScreenDecorations.onConfigurationChanged(null);
@@ -1072,8 +1023,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testOnlyRoundedCornerRadiusTop() {
setupResources(0 /* radius */, 10 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
mScreenDecorations.start();
@@ -1094,8 +1044,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testOnlyRoundedCornerRadiusBottom() {
setupResources(0 /* radius */, 0 /* radiusTop */, 20 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
mScreenDecorations.start();
@@ -1166,13 +1115,10 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testSupportHwcLayer_SwitchFrom_NotSupport() {
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// should only inflate mOverlays when the hwc doesn't support screen decoration
@@ -1195,16 +1141,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testNotSupportHwcLayer_SwitchFrom_Support() {
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// should only inflate hwc layer when the hwc supports screen decoration
@@ -1234,16 +1177,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
/* roundedTopDrawable */,
getTestsDrawable(com.android.systemui.tests.R.drawable.rounded4px)
/* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- true /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
// Inflate top and bottom overlay with INVISIBLE because of only privacy dots on sw layer
@@ -1277,11 +1217,9 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testAutoShowHideOverlayWindowWhenNoRoundedAndNoCutout() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, true /* privacyDot */,
- true /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */);
- // no cutout
- doReturn(null).when(mScreenDecorations).getCutout();
+ // no cutout (default)
mScreenDecorations.start();
// Inflate top and bottom overlay with INVISIBLE because of only privacy dots on sw layer
@@ -1315,16 +1253,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testHwcLayer_noPrivacyDot_noFaceScanning() {
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
@@ -1337,16 +1272,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testHwcLayer_PrivacyDot_FaceScanning() {
setupResources(0 /* radius */, 10 /* radiusTop */, 20 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- true /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, true /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
@@ -1364,16 +1296,13 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testOnDisplayChanged_hwcLayer() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
final DisplayDecorationSupport decorationSupport = new DisplayDecorationSupport();
decorationSupport.format = PixelFormat.R_8;
doReturn(decorationSupport).when(mDisplay).getDisplayDecorationSupport();
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
@@ -1390,18 +1319,16 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testOnDisplayChanged_nonHwcLayer() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
// top cutout
- final Rect[] bounds = {null, new Rect(9, 0, 10, 1), null, null};
- doReturn(getDisplayCutoutForRotation(Insets.of(0, 1, 0, 0), bounds))
- .when(mScreenDecorations).getCutout();
+ mMockCutoutList.add(new CutoutDecorProviderImpl(BOUNDS_POSITION_TOP));
mScreenDecorations.start();
- final ScreenDecorations.DisplayCutoutView cutoutView =
- mScreenDecorations.mCutoutViews[BOUNDS_POSITION_TOP];
+ final ScreenDecorations.DisplayCutoutView cutoutView = (ScreenDecorations.DisplayCutoutView)
+ mScreenDecorations.getOverlayView(R.id.display_cutout);
+ assertNotNull(cutoutView);
spyOn(cutoutView);
doReturn(mDisplay).when(cutoutView).getDisplay();
@@ -1414,8 +1341,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testHasSameProvidersWithNullOverlays() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, false /* fillCutout */, false /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, false /* privacyDot */, false /* faceScanning */);
mScreenDecorations.start();
@@ -1433,8 +1359,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
public void testHasSameProvidersWithPrivacyDots() {
setupResources(0 /* radius */, 0 /* radiusTop */, 0 /* radiusBottom */,
null /* roundedTopDrawable */, null /* roundedBottomDrawable */,
- 0 /* roundedPadding */, true /* fillCutout */, true /* privacyDot */,
- false /* faceScanning */);
+ 0 /* roundedPadding */, true /* privacyDot */, false /* faceScanning */);
mScreenDecorations.start();
@@ -1471,7 +1396,7 @@ public class ScreenDecorationsTest extends SysuiTestCase {
private void setupResources(int radius, int radiusTop, int radiusBottom,
@Nullable Drawable roundedTopDrawable, @Nullable Drawable roundedBottomDrawable,
- int roundedPadding, boolean fillCutout, boolean privacyDot, boolean faceScanning) {
+ int roundedPadding, boolean privacyDot, boolean faceScanning) {
mContext.getOrCreateTestableResources().addOverride(
com.android.internal.R.array.config_displayUniqueIdArray,
new String[]{});
@@ -1511,8 +1436,6 @@ public class ScreenDecorationsTest extends SysuiTestCase {
}
mContext.getOrCreateTestableResources().addOverride(
R.dimen.rounded_corner_content_padding, roundedPadding);
- mContext.getOrCreateTestableResources().addOverride(
- com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout);
mPrivacyDecorProviders = new ArrayList<>();
if (privacyDot) {
@@ -1531,19 +1454,4 @@ public class ScreenDecorationsTest extends SysuiTestCase {
when(mFaceScanningProviderFactory.getProviders()).thenReturn(mFaceScanningProviders);
when(mFaceScanningProviderFactory.getHasProviders()).thenReturn(faceScanning);
}
-
- private DisplayCutout getDisplayCutoutForRotation(Insets safeInsets, Rect[] cutoutBounds) {
- final int rotation = mContext.getDisplay().getRotation();
- final Insets insets = RotationUtils.rotateInsets(safeInsets, rotation);
- final Rect[] sorted = new Rect[BOUNDS_POSITION_LENGTH];
- for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
- final int rotatedPos = ScreenDecorations.getBoundPositionFromRotation(i, rotation);
- if (cutoutBounds[i] != null) {
- RotationUtils.rotateBounds(cutoutBounds[i], new Rect(0, 0, 100, 200), rotation);
- }
- sorted[rotatedPos] = cutoutBounds[i];
- }
- return new DisplayCutout(insets, sorted[BOUNDS_POSITION_LEFT], sorted[BOUNDS_POSITION_TOP],
- sorted[BOUNDS_POSITION_RIGHT], sorted[BOUNDS_POSITION_BOTTOM]);
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index e0d1f7a19130..b18b0abcaab1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -20,6 +20,8 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRIN
import static android.hardware.biometrics.BiometricManager.Authenticators;
import static android.hardware.biometrics.BiometricManager.BIOMETRIC_MULTI_SENSOR_FINGERPRINT_AND_FACE;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
+
import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertEquals;
@@ -157,13 +159,15 @@ public class AuthControllerTest extends SysuiTestCase {
@Mock
private InteractionJankMonitor mInteractionJankMonitor;
@Captor
- ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mFpAuthenticatorsRegisteredCaptor;
+ private ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mFpAuthenticatorsRegisteredCaptor;
+ @Captor
+ private ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mFaceAuthenticatorsRegisteredCaptor;
@Captor
- ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mFaceAuthenticatorsRegisteredCaptor;
+ private ArgumentCaptor<BiometricStateListener> mBiometricStateCaptor;
@Captor
- ArgumentCaptor<BiometricStateListener> mBiometricStateCaptor;
+ private ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor;
@Captor
- ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor;
+ private ArgumentCaptor<WakefulnessLifecycle.Observer> mWakefullnessObserverCaptor;
private TestableContext mContextSpy;
private Execution mExecution;
@@ -242,7 +246,9 @@ public class AuthControllerTest extends SysuiTestCase {
mFaceAuthenticatorsRegisteredCaptor.capture());
when(mStatusBarStateController.isDozing()).thenReturn(false);
+ when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE);
verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
+ verify(mWakefulnessLifecycle).addObserver(mWakefullnessObserverCaptor.capture());
mFpAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(fpProps);
mFaceAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(faceProps);
@@ -759,16 +765,37 @@ public class AuthControllerTest extends SysuiTestCase {
}
@Test
- public void testForwardsDozeEvent() throws RemoteException {
+ public void testForwardsDozeEvents() throws RemoteException {
+ when(mStatusBarStateController.isDozing()).thenReturn(true);
+ when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE);
mAuthController.setBiometicContextListener(mContextListener);
- mStatusBarStateListenerCaptor.getValue().onDozingChanged(false);
mStatusBarStateListenerCaptor.getValue().onDozingChanged(true);
+ mStatusBarStateListenerCaptor.getValue().onDozingChanged(false);
+
+ InOrder order = inOrder(mContextListener);
+ order.verify(mContextListener, times(2)).onDozeChanged(eq(true), eq(true));
+ order.verify(mContextListener).onDozeChanged(eq(false), eq(true));
+ order.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testForwardsWakeEvents() throws RemoteException {
+ when(mStatusBarStateController.isDozing()).thenReturn(false);
+ when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE);
+ mAuthController.setBiometicContextListener(mContextListener);
+
+ mWakefullnessObserverCaptor.getValue().onStartedGoingToSleep();
+ mWakefullnessObserverCaptor.getValue().onFinishedGoingToSleep();
+ mWakefullnessObserverCaptor.getValue().onStartedWakingUp();
+ mWakefullnessObserverCaptor.getValue().onFinishedWakingUp();
+ mWakefullnessObserverCaptor.getValue().onPostFinishedWakingUp();
InOrder order = inOrder(mContextListener);
- // invoked twice since the initial state is false
- order.verify(mContextListener, times(2)).onDozeChanged(eq(false));
- order.verify(mContextListener).onDozeChanged(eq(true));
+ order.verify(mContextListener).onDozeChanged(eq(false), eq(true));
+ order.verify(mContextListener).onDozeChanged(eq(false), eq(false));
+ order.verify(mContextListener).onDozeChanged(eq(false), eq(true));
+ order.verifyNoMoreInteractions();
}
// Helpers
diff --git a/packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt
index 3ac28c8d0d37..2af055783c22 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/charging/WiredChargingRippleControllerTest.kt
@@ -107,11 +107,11 @@ class WiredChargingRippleControllerTest : SysuiTestCase() {
reset(rippleView)
captor.value.onThemeChanged()
- verify(rippleView).setColor(ArgumentMatchers.anyInt())
+ verify(rippleView).setColor(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())
reset(rippleView)
captor.value.onUiModeChanged()
- verify(rippleView).setColor(ArgumentMatchers.anyInt())
+ verify(rippleView).setColor(ArgumentMatchers.anyInt(), ArgumentMatchers.anyInt())
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
new file mode 100644
index 000000000000..1040ec453a7c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/decor/CutoutDecorProviderFactoryTest.kt
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.decor
+
+import android.graphics.Insets
+import android.graphics.Rect
+import android.testing.AndroidTestingRunner
+import android.testing.TestableResources
+import android.util.RotationUtils
+import android.util.Size
+import android.view.Display
+import android.view.DisplayCutout
+import android.view.DisplayCutout.BOUNDS_POSITION_LENGTH
+import android.view.DisplayInfo
+import android.view.Surface
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.any
+import org.junit.Assert
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.doAnswer
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class CutoutDecorProviderFactoryTest : SysuiTestCase() {
+
+ @Mock private lateinit var display: Display
+ private var testableRes: TestableResources? = null
+ private lateinit var factory: CutoutDecorProviderFactory
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ testableRes = mContext.orCreateTestableResources
+ factory = CutoutDecorProviderFactory(testableRes!!.resources, display)
+ }
+
+ private fun setupFillCutout(fillCutout: Boolean) {
+ testableRes!!.addOverride(
+ com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, fillCutout
+ )
+ }
+
+ private fun setupDisplayInfo(
+ displayCutout: DisplayCutout? = null,
+ @Surface.Rotation rotation: Int = Surface.ROTATION_0,
+ displayId: Int = -1
+ ) {
+ doAnswer {
+ it.getArgument<DisplayInfo>(0).let { info ->
+ info.displayCutout = displayCutout
+ info.rotation = rotation
+ info.displayId = displayId
+ }
+ true
+ }.`when`(display).getDisplayInfo(any<DisplayInfo>())
+ }
+
+ private fun getCutout(
+ safeInsets: Insets,
+ cutoutBounds: Array<Rect?>,
+ @Surface.Rotation rotation: Int = Surface.ROTATION_0,
+ cutoutParentSizeForRotate: Size = Size(100, 200)
+ ): DisplayCutout {
+ val insets = RotationUtils.rotateInsets(safeInsets, rotation)
+ val sorted = arrayOfNulls<Rect>(BOUNDS_POSITION_LENGTH)
+ for (pos in 0 until BOUNDS_POSITION_LENGTH) {
+ val rotatedPos = (pos - rotation + BOUNDS_POSITION_LENGTH) % BOUNDS_POSITION_LENGTH
+ if (cutoutBounds[pos] != null) {
+ RotationUtils.rotateBounds(
+ cutoutBounds[pos],
+ cutoutParentSizeForRotate.width,
+ cutoutParentSizeForRotate.height,
+ rotation
+ )
+ }
+ sorted[rotatedPos] = cutoutBounds[pos]
+ }
+ return DisplayCutout(
+ insets,
+ sorted[DisplayCutout.BOUNDS_POSITION_LEFT],
+ sorted[DisplayCutout.BOUNDS_POSITION_TOP],
+ sorted[DisplayCutout.BOUNDS_POSITION_RIGHT],
+ sorted[DisplayCutout.BOUNDS_POSITION_BOTTOM]
+ )
+ }
+
+ @Test
+ fun testGetNothingIfNoCutout() {
+ setupFillCutout(false)
+
+ Assert.assertFalse(factory.hasProviders)
+ Assert.assertEquals(0, factory.providers.size)
+ }
+
+ @Test
+ fun testGetTopCutoutProvider() {
+ setupFillCutout(true)
+ setupDisplayInfo(
+ getCutout(
+ safeInsets = Insets.of(0, 1, 0, 0),
+ cutoutBounds = arrayOf(null, Rect(9, 0, 10, 1), null, null)
+ )
+ )
+
+ Assert.assertTrue(factory.hasProviders)
+
+ val providers = factory.providers
+ Assert.assertEquals(1, providers.size)
+ Assert.assertEquals(1, providers[0].numOfAlignedBound)
+ Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_TOP, providers[0].alignedBounds[0])
+ }
+
+ @Test
+ fun testGetBottomCutoutProviderOnLandscape() {
+ setupFillCutout(true)
+ setupDisplayInfo(
+ getCutout(
+ safeInsets = Insets.of(0, 0, 0, 1),
+ cutoutBounds = arrayOf(null, null, null, Rect(45, 199, 55, 200)),
+ rotation = Surface.ROTATION_90
+ ),
+ Surface.ROTATION_90
+ )
+
+ Assert.assertTrue(factory.hasProviders)
+
+ val providers = factory.providers
+ Assert.assertEquals(1, providers.size)
+ Assert.assertEquals(1, providers[0].numOfAlignedBound)
+ Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_BOTTOM, providers[0].alignedBounds[0])
+ }
+
+ @Test
+ fun testGetLeftCutoutProviderOnSeascape() {
+ setupFillCutout(true)
+ setupDisplayInfo(
+ getCutout(
+ safeInsets = Insets.of(1, 0, 0, 0),
+ cutoutBounds = arrayOf(Rect(0, 20, 1, 40), null, null, null),
+ rotation = Surface.ROTATION_270
+ ),
+ Surface.ROTATION_270
+ )
+
+ Assert.assertTrue(factory.hasProviders)
+
+ val providers = factory.providers
+ Assert.assertEquals(1, providers.size)
+ Assert.assertEquals(1, providers[0].numOfAlignedBound)
+ Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_LEFT, providers[0].alignedBounds[0])
+ }
+
+ @Test
+ fun testGetTopRightCutoutProviderOnReverse() {
+ setupFillCutout(true)
+ setupDisplayInfo(
+ getCutout(
+ safeInsets = Insets.of(0, 1, 1, 0),
+ cutoutBounds = arrayOf(
+ null,
+ Rect(9, 0, 10, 1),
+ Rect(99, 40, 100, 60),
+ null
+ ),
+ rotation = Surface.ROTATION_180
+ ),
+ Surface.ROTATION_180
+ )
+
+ Assert.assertTrue(factory.hasProviders)
+
+ val providers = factory.providers
+ Assert.assertEquals(2, providers.size)
+ Assert.assertEquals(1, providers[0].numOfAlignedBound)
+ Assert.assertEquals(1, providers[1].numOfAlignedBound)
+ providers.sortedBy { it.alignedBounds[0] }.let {
+ Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_TOP, it[0].alignedBounds[0])
+ Assert.assertEquals(DisplayCutout.BOUNDS_POSITION_RIGHT, it[1].alignedBounds[0])
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamMediaEntryComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamMediaEntryComplicationTest.java
new file mode 100644
index 000000000000..bc944404efe6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/DreamMediaEntryComplicationTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.complication;
+
+import static org.mockito.Mockito.verify;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.View;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.media.dream.MediaDreamComplication;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class DreamMediaEntryComplicationTest extends SysuiTestCase {
+ @Mock
+ private View mView;
+
+ @Mock
+ private DreamOverlayStateController mDreamOverlayStateController;
+
+ @Mock
+ private MediaDreamComplication mMediaComplication;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ /**
+ * Ensures clicking media entry chip adds/removes media complication.
+ */
+ @Test
+ public void testClick() {
+ final DreamMediaEntryComplication.DreamMediaEntryViewController viewController =
+ new DreamMediaEntryComplication.DreamMediaEntryViewController(
+ mView,
+ mDreamOverlayStateController,
+ mMediaComplication);
+
+ final ArgumentCaptor<View.OnClickListener> clickListenerCaptor =
+ ArgumentCaptor.forClass(View.OnClickListener.class);
+ verify(mView).setOnClickListener(clickListenerCaptor.capture());
+
+ clickListenerCaptor.getValue().onClick(mView);
+ verify(mView).setSelected(true);
+ verify(mDreamOverlayStateController).addComplication(mMediaComplication);
+ clickListenerCaptor.getValue().onClick(mView);
+ verify(mView).setSelected(false);
+ verify(mDreamOverlayStateController).removeComplication(mMediaComplication);
+ }
+
+ /**
+ * Ensures media complication is removed when the view is detached.
+ */
+ @Test
+ public void testOnViewDetached() {
+ final DreamMediaEntryComplication.DreamMediaEntryViewController viewController =
+ new DreamMediaEntryComplication.DreamMediaEntryViewController(
+ mView,
+ mDreamOverlayStateController,
+ mMediaComplication);
+
+ viewController.onViewDetached();
+ verify(mView).setSelected(false);
+ verify(mDreamOverlayStateController).removeComplication(mMediaComplication);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
index 7d54758acee7..fa8f88a08368 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/SmartSpaceComplicationTest.java
@@ -43,7 +43,7 @@ import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
-import java.util.Arrays;
+import java.util.Collections;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -61,9 +61,6 @@ public class SmartSpaceComplicationTest extends SysuiTestCase {
private SmartSpaceComplication mComplication;
@Mock
- private ComplicationViewModel mComplicationViewModel;
-
- @Mock
private View mBcSmartspaceView;
@Before
@@ -125,12 +122,12 @@ public class SmartSpaceComplicationTest extends SysuiTestCase {
// Test
final SmartspaceTarget target = Mockito.mock(SmartspaceTarget.class);
- listenerCaptor.getValue().onSmartspaceTargetsUpdated(Arrays.asList(target));
+ listenerCaptor.getValue().onSmartspaceTargetsUpdated(Collections.singletonList(target));
verify(mDreamOverlayStateController).addComplication(eq(mComplication));
}
@Test
- public void testOverlayActive_targetsEmpty_removesComplication() {
+ public void testOverlayActive_targetsEmpty_addsComplication() {
final SmartSpaceComplication.Registrant registrant = getRegistrant();
registrant.start();
@@ -145,13 +142,9 @@ public class SmartSpaceComplicationTest extends SysuiTestCase {
ArgumentCaptor.forClass(BcSmartspaceDataPlugin.SmartspaceTargetListener.class);
verify(mSmartspaceController).addListener(listenerCaptor.capture());
- final SmartspaceTarget target = Mockito.mock(SmartspaceTarget.class);
- listenerCaptor.getValue().onSmartspaceTargetsUpdated(Arrays.asList(target));
- verify(mDreamOverlayStateController).addComplication(eq(mComplication));
-
// Test
- listenerCaptor.getValue().onSmartspaceTargetsUpdated(Arrays.asList());
- verify(mDreamOverlayStateController).removeComplication(eq(mComplication));
+ listenerCaptor.getValue().onSmartspaceTargetsUpdated(Collections.emptyList());
+ verify(mDreamOverlayStateController).addComplication(eq(mComplication));
}
@Test
@@ -170,8 +163,7 @@ public class SmartSpaceComplicationTest extends SysuiTestCase {
ArgumentCaptor.forClass(BcSmartspaceDataPlugin.SmartspaceTargetListener.class);
verify(mSmartspaceController).addListener(listenerCaptor.capture());
- final SmartspaceTarget target = Mockito.mock(SmartspaceTarget.class);
- listenerCaptor.getValue().onSmartspaceTargetsUpdated(Arrays.asList(target));
+ listenerCaptor.getValue().onSmartspaceTargetsUpdated(Collections.emptyList());
verify(mDreamOverlayStateController).addComplication(eq(mComplication));
// Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
index d1ed8e983cdd..f9c7d2d5cb41 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
@@ -31,7 +31,6 @@ import com.android.systemui.statusbar.SbnBuilder
import com.android.systemui.tuner.TunerService
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
@@ -108,6 +107,7 @@ class MediaDataManagerTest : SysuiTestCase() {
private val clock = FakeSystemClock()
@Mock private lateinit var tunerService: TunerService
@Captor lateinit var tunableCaptor: ArgumentCaptor<TunerService.Tunable>
+ @Captor lateinit var callbackCaptor: ArgumentCaptor<(String, PlaybackState) -> Unit>
private val instanceIdSequence = InstanceIdSequenceFake(1 shl 20)
@@ -974,7 +974,6 @@ class MediaDataManagerTest : SysuiTestCase() {
fun testPlaybackStateChange_keyExists_callsListener() {
// Notification has been added
addNotificationAndLoad()
- val callbackCaptor = argumentCaptor<(String, PlaybackState) -> Unit>()
verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor)
// Callback gets an updated state
@@ -992,7 +991,6 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testPlaybackStateChange_keyDoesNotExist_doesNothing() {
val state = PlaybackState.Builder().build()
- val callbackCaptor = argumentCaptor<(String, PlaybackState) -> Unit>()
verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor)
// No media added with this key
@@ -1013,7 +1011,6 @@ class MediaDataManagerTest : SysuiTestCase() {
// And then get a state update
val state = PlaybackState.Builder().build()
- val callbackCaptor = argumentCaptor<(String, PlaybackState) -> Unit>()
verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor)
// Then no changes are made
@@ -1022,6 +1019,83 @@ class MediaDataManagerTest : SysuiTestCase() {
anyBoolean())
}
+ @Test
+ fun testPlaybackState_PauseWhenFlagTrue_keyExists_callsListener() {
+ whenever(mediaFlags.areMediaSessionActionsEnabled(any(), any())).thenReturn(true)
+ val state = PlaybackState.Builder()
+ .setState(PlaybackState.STATE_PAUSED, 0L, 1f)
+ .build()
+ whenever(controller.playbackState).thenReturn(state)
+
+ addNotificationAndLoad()
+ verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor)
+ callbackCaptor.value.invoke(KEY, state)
+
+ verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY),
+ capture(mediaDataCaptor), eq(true), eq(0), eq(false))
+ assertThat(mediaDataCaptor.value.isPlaying).isFalse()
+ assertThat(mediaDataCaptor.value.semanticActions).isNotNull()
+ }
+
+ @Test
+ fun testPlaybackState_PauseStateAfterAddingResumption_keyExists_callsListener() {
+ val desc = MediaDescription.Builder().run {
+ setTitle(SESSION_TITLE)
+ build()
+ }
+ val state = PlaybackState.Builder()
+ .setState(PlaybackState.STATE_PAUSED, 0L, 1f)
+ .setActions(PlaybackState.ACTION_PLAY_PAUSE)
+ .build()
+
+ // Add resumption controls in order to have semantic actions.
+ // To make sure that they are not null after changing state.
+ mediaDataManager.addResumptionControls(
+ USER_ID,
+ desc,
+ Runnable {},
+ session.sessionToken,
+ APP_NAME,
+ pendingIntent,
+ PACKAGE_NAME
+ )
+ backgroundExecutor.runAllReady()
+ foregroundExecutor.runAllReady()
+
+ verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor)
+ callbackCaptor.value.invoke(PACKAGE_NAME, state)
+
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(PACKAGE_NAME),
+ eq(PACKAGE_NAME),
+ capture(mediaDataCaptor),
+ eq(true),
+ eq(0),
+ eq(false)
+ )
+ assertThat(mediaDataCaptor.value.isPlaying).isFalse()
+ assertThat(mediaDataCaptor.value.semanticActions).isNotNull()
+ }
+
+ @Test
+ fun testPlaybackStateNull_Pause_keyExists_callsListener() {
+ whenever(controller.playbackState).thenReturn(null)
+ val state = PlaybackState.Builder()
+ .setState(PlaybackState.STATE_PAUSED, 0L, 1f)
+ .setActions(PlaybackState.ACTION_PLAY_PAUSE)
+ .build()
+
+ addNotificationAndLoad()
+ verify(mediaTimeoutListener).stateCallback = capture(callbackCaptor)
+ callbackCaptor.value.invoke(KEY, state)
+
+ verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY),
+ capture(mediaDataCaptor), eq(true), eq(0), eq(false))
+ assertThat(mediaDataCaptor.value.isPlaying).isFalse()
+ assertThat(mediaDataCaptor.value.semanticActions).isNull()
+ }
+
/**
* Helper function to add a media notification and capture the resulting MediaData
*/
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index 61736923fb82..9be201e99b2b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -224,6 +224,14 @@ public class MediaOutputBaseDialogTest extends SysuiTestCase {
}
@Test
+ public void refresh_inDragging_directSetRefreshingToFalse() {
+ when(mMediaOutputBaseAdapter.isDragging()).thenReturn(true);
+ mMediaOutputBaseDialogImpl.refresh();
+
+ assertThat(mMediaOutputController.isRefreshing()).isFalse();
+ }
+
+ @Test
public void refresh_notInDragging_verifyUpdateAdapter() {
when(mMediaOutputBaseAdapter.getCurrentActivePosition()).thenReturn(-1);
when(mMediaOutputBaseAdapter.isDragging()).thenReturn(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java
index c101b9ffd495..2e864dc2cda8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java
@@ -18,6 +18,7 @@ package com.android.systemui.media.dream;
import static com.android.systemui.flags.Flags.MEDIA_DREAM_COMPLICATION;
+import static org.mockito.AdditionalMatchers.not;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
@@ -30,6 +31,7 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.dreams.complication.DreamMediaEntryComplication;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.MediaData;
import com.android.systemui.media.MediaDataManager;
@@ -51,7 +53,7 @@ public class MediaDreamSentinelTest extends SysuiTestCase {
DreamOverlayStateController mDreamOverlayStateController;
@Mock
- MediaDreamComplication mComplication;
+ DreamMediaEntryComplication mMediaEntryComplication;
@Mock
FeatureFlags mFeatureFlags;
@@ -72,7 +74,7 @@ public class MediaDreamSentinelTest extends SysuiTestCase {
@Test
public void testComplicationAddition() {
final MediaDreamSentinel sentinel = new MediaDreamSentinel(mContext, mMediaDataManager,
- mDreamOverlayStateController, mComplication, mFeatureFlags);
+ mDreamOverlayStateController, mMediaEntryComplication, mFeatureFlags);
sentinel.start();
@@ -85,14 +87,16 @@ public class MediaDreamSentinelTest extends SysuiTestCase {
when(mMediaDataManager.hasActiveMedia()).thenReturn(true);
listener.onMediaDataLoaded(mKey, mOldKey, mData, /* immediately= */true,
/* receivedSmartspaceCardLatency= */0, /* isSsReactived= */ false);
- verify(mDreamOverlayStateController).addComplication(eq(mComplication));
+ verify(mDreamOverlayStateController).addComplication(eq(mMediaEntryComplication));
+ verify(mDreamOverlayStateController, never()).addComplication(
+ not(eq(mMediaEntryComplication)));
listener.onMediaDataRemoved(mKey);
verify(mDreamOverlayStateController, never()).removeComplication(any());
when(mMediaDataManager.hasActiveMedia()).thenReturn(false);
listener.onMediaDataRemoved(mKey);
- verify(mDreamOverlayStateController).removeComplication(eq(mComplication));
+ verify(mDreamOverlayStateController).removeComplication(eq(mMediaEntryComplication));
}
@Test
@@ -100,7 +104,7 @@ public class MediaDreamSentinelTest extends SysuiTestCase {
when(mFeatureFlags.isEnabled(MEDIA_DREAM_COMPLICATION)).thenReturn(false);
final MediaDreamSentinel sentinel = new MediaDreamSentinel(mContext, mMediaDataManager,
- mDreamOverlayStateController, mComplication, mFeatureFlags);
+ mDreamOverlayStateController, mMediaEntryComplication, mFeatureFlags);
sentinel.start();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt
index 1061e3c6b0d5..fa47a746f8ba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt
@@ -35,7 +35,9 @@ import com.android.internal.logging.testing.UiEventLoggerFake
import com.android.internal.statusbar.IUndoMediaTransferCallback
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.media.taptotransfer.common.MediaTttLogger
+import com.android.systemui.plugins.FalsingManager
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.concurrency.FakeExecutor
@@ -48,11 +50,12 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -78,6 +81,10 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
private lateinit var viewUtil: ViewUtil
@Mock
private lateinit var commandQueue: CommandQueue
+ @Mock
+ private lateinit var falsingManager: FalsingManager
+ @Mock
+ private lateinit var falsingCollector: FalsingCollector
private lateinit var commandQueueCallback: CommandQueue.Callbacks
private lateinit var fakeAppIconDrawable: Drawable
private lateinit var fakeClock: FakeSystemClock
@@ -115,7 +122,9 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
accessibilityManager,
configurationController,
powerManager,
- senderUiEventLogger
+ senderUiEventLogger,
+ falsingManager,
+ falsingCollector
)
val callbackCaptor = ArgumentCaptor.forClass(CommandQueue.Callbacks::class.java)
@@ -421,6 +430,38 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() {
}
@Test
+ fun transferToReceiverSucceeded_withUndoRunnable_falseTap_callbackNotRun() {
+ whenever(falsingManager.isFalseTap(anyInt())).thenReturn(true)
+ var undoCallbackCalled = false
+ val undoCallback = object : IUndoMediaTransferCallback.Stub() {
+ override fun onUndoTriggered() {
+ undoCallbackCalled = true
+ }
+ }
+
+ controllerSender.displayChip(transferToReceiverSucceeded(undoCallback))
+ getChipView().getUndoButton().performClick()
+
+ assertThat(undoCallbackCalled).isFalse()
+ }
+
+ @Test
+ fun transferToReceiverSucceeded_withUndoRunnable_realTap_callbackRun() {
+ whenever(falsingManager.isFalseTap(anyInt())).thenReturn(false)
+ var undoCallbackCalled = false
+ val undoCallback = object : IUndoMediaTransferCallback.Stub() {
+ override fun onUndoTriggered() {
+ undoCallbackCalled = true
+ }
+ }
+
+ controllerSender.displayChip(transferToReceiverSucceeded(undoCallback))
+ getChipView().getUndoButton().performClick()
+
+ assertThat(undoCallbackCalled).isTrue()
+ }
+
+ @Test
fun transferToReceiverSucceeded_undoButtonClick_switchesToTransferToThisDeviceTriggered() {
val undoCallback = object : IUndoMediaTransferCallback.Stub() {
override fun onUndoTriggered() {}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
index 9b0142d6a8fe..5db3b9caa007 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
@@ -31,6 +31,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingManagerFake
import com.android.systemui.qs.QSUserSwitcherEvent
import com.android.systemui.statusbar.policy.UserSwitcherController
+import com.android.systemui.user.data.source.UserRecord
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
@@ -39,8 +40,8 @@ import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@@ -140,13 +141,14 @@ class UserDetailViewAdapterTest : SysuiTestCase() {
}
private fun createUserRecord(current: Boolean, guest: Boolean) =
- UserSwitcherController.UserRecord(
- mUserInfo,
- mPicture,
- guest,
- current,
- false /* isAddUser */,
- false /* isRestricted */,
- true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ UserRecord(
+ mUserInfo,
+ mPicture,
+ guest,
+ current,
+ false /* isAddUser */,
+ false /* isRestricted */,
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */
+ )
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
index 83e56daf1fbc..6ce9cff9a730 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/TakeScreenshotServiceTest.kt
@@ -40,6 +40,7 @@ import com.android.internal.util.ScreenshotHelper.ScreenshotRequest
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags.SCREENSHOT_REQUEST_PROCESSOR
+import com.android.systemui.flags.Flags.SCREENSHOT_WORK_PROFILE_POLICY
import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_REQUESTED_KEY_CHORD
import com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_REQUESTED_OVERVIEW
import com.android.systemui.screenshot.TakeScreenshotService.RequestCallback
@@ -47,12 +48,15 @@ import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argThat
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
+import java.util.function.Consumer
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.isNull
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
import org.mockito.Mockito.`when` as whenever
@@ -88,7 +92,16 @@ class TakeScreenshotServiceTest : SysuiTestCase() {
.thenReturn(false)
whenever(userManager.isUserUnlocked).thenReturn(true)
+ // Stub request processor as a synchronous no-op for tests with the flag enabled
+ doAnswer {
+ val request: ScreenshotRequest = it.getArgument(0) as ScreenshotRequest
+ val consumer: Consumer<ScreenshotRequest> = it.getArgument(1)
+ consumer.accept(request)
+ }.`when`(requestProcessor).processAsync(/* request= */ any(), /* callback= */ any())
+
+ // Flipped in selected test cases
flags.set(SCREENSHOT_REQUEST_PROCESSOR, false)
+ flags.set(SCREENSHOT_WORK_PROFILE_POLICY, false)
service.attach(
mContext,
@@ -105,10 +118,10 @@ class TakeScreenshotServiceTest : SysuiTestCase() {
service.onBind(null /* unused: Intent */)
service.onUnbind(null /* unused: Intent */)
- verify(controller).removeWindow()
+ verify(controller, times(1)).removeWindow()
service.onDestroy()
- verify(controller).onDestroy()
+ verify(controller, times(1)).onDestroy()
}
@Test
@@ -120,7 +133,32 @@ class TakeScreenshotServiceTest : SysuiTestCase() {
service.handleRequest(request, { /* onSaved */ }, callback)
- verify(controller).takeScreenshotFullscreen(
+ verify(controller, times(1)).takeScreenshotFullscreen(
+ eq(topComponent),
+ /* onSavedListener = */ any(),
+ /* requestCallback = */ any())
+
+ assertEquals("Expected one UiEvent", eventLogger.numLogs(), 1)
+ val logEvent = eventLogger.get(0)
+
+ assertEquals("Expected SCREENSHOT_REQUESTED UiEvent",
+ logEvent.eventId, SCREENSHOT_REQUESTED_KEY_CHORD.id)
+ assertEquals("Expected supplied package name",
+ topComponent.packageName, eventLogger.get(0).packageName)
+ }
+
+ @Test
+ fun takeScreenshot_requestProcessorEnabled() {
+ flags.set(SCREENSHOT_REQUEST_PROCESSOR, true)
+
+ val request = ScreenshotRequest(
+ TAKE_SCREENSHOT_FULLSCREEN,
+ SCREENSHOT_KEY_CHORD,
+ topComponent)
+
+ service.handleRequest(request, { /* onSaved */ }, callback)
+
+ verify(controller, times(1)).takeScreenshotFullscreen(
eq(topComponent),
/* onSavedListener = */ any(),
/* requestCallback = */ any())
@@ -143,7 +181,7 @@ class TakeScreenshotServiceTest : SysuiTestCase() {
service.handleRequest(request, { /* onSaved */ }, callback)
- verify(controller).takeScreenshotPartial(
+ verify(controller, times(1)).takeScreenshotPartial(
/* topComponent = */ isNull(),
/* onSavedListener = */ any(),
/* requestCallback = */ any())
@@ -167,7 +205,7 @@ class TakeScreenshotServiceTest : SysuiTestCase() {
service.handleRequest(request, { /* onSaved */ }, callback)
- verify(controller).handleImageAsScreenshot(
+ verify(controller, times(1)).handleImageAsScreenshot(
argThat { b -> b.equalsHardwareBitmap(bitmap) },
eq(bounds),
eq(Insets.NONE), eq(TASK_ID), eq(USER_ID), eq(topComponent),
@@ -193,8 +231,8 @@ class TakeScreenshotServiceTest : SysuiTestCase() {
service.handleRequest(request, { /* onSaved */ }, callback)
- verify(notificationsController).notifyScreenshotError(anyInt())
- verify(callback).reportError()
+ verify(notificationsController, times(1)).notifyScreenshotError(anyInt())
+ verify(callback, times(1)).reportError()
verifyZeroInteractions(controller)
}
@@ -217,7 +255,7 @@ class TakeScreenshotServiceTest : SysuiTestCase() {
service.handleRequest(request, { /* onSaved */ }, callback)
// error shown: Toast.makeText(...).show(), untestable
- verify(callback).reportError()
+ verify(callback, times(1)).reportError()
verifyZeroInteractions(controller)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index 98389c2c7a6f..e2ce939cb66c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -458,7 +458,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
NotificationWakeUpCoordinator coordinator =
new NotificationWakeUpCoordinator(
- mDumpManager,
mock(HeadsUpManagerPhone.class),
new StatusBarStateControllerImpl(new UiEventLoggerFake(), mDumpManager,
mInteractionJankMonitor),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 351dd0c49519..05692b3e6749 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -570,6 +570,33 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase {
}
@Test
+ public void onBiometricHelp_coEx_faceFailure() {
+ createController();
+
+ // GIVEN unlocking with fingerprint is possible
+ when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(anyInt()))
+ .thenReturn(true);
+
+ String message = "A message";
+ mController.setVisible(true);
+
+ // WHEN there's a face not recognized message
+ mController.getKeyguardCallback().onBiometricHelp(
+ KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED,
+ message,
+ BiometricSourceType.FACE);
+
+ // THEN show sequential messages such as: 'face not recognized' and
+ // 'try fingerprint instead'
+ verifyIndicationMessage(
+ INDICATION_TYPE_BIOMETRIC_MESSAGE,
+ mContext.getString(R.string.keyguard_face_failed));
+ verifyIndicationMessage(
+ INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP,
+ mContext.getString(R.string.keyguard_suggest_fingerprint));
+ }
+
+ @Test
public void transientIndication_visibleWhenDozing_unlessSwipeUp_fromError() {
createController();
String message = mContext.getString(R.string.keyguard_unlock);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
deleted file mode 100644
index 19dd027daedd..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationListControllerTest.java
+++ /dev/null
@@ -1,123 +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.statusbar.notification;
-
-import static com.android.systemui.statusbar.notification.NotificationEntryManager.UNDEFINED_DISMISS_REASON;
-
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.verify;
-
-import android.app.ActivityManager;
-import android.app.Notification;
-import android.os.UserHandle;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class NotificationListControllerTest extends SysuiTestCase {
- private NotificationListController mController;
-
- @Mock private NotificationEntryManager mEntryManager;
- @Mock private NotificationListContainer mListContainer;
- @Mock private DeviceProvisionedController mDeviceProvisionedController;
-
- @Captor private ArgumentCaptor<NotificationEntryListener> mEntryListenerCaptor;
- @Captor private ArgumentCaptor<DeviceProvisionedListener> mProvisionedCaptor;
-
- private NotificationEntryListener mEntryListener;
- private DeviceProvisionedListener mProvisionedListener;
-
- private int mNextNotifId = 0;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
-
- mController = new NotificationListController(
- mEntryManager,
- mListContainer,
- mDeviceProvisionedController);
- mController.bind();
-
- // Capture callbacks passed to mocks
- verify(mEntryManager).addNotificationEntryListener(mEntryListenerCaptor.capture());
- mEntryListener = mEntryListenerCaptor.getValue();
- verify(mDeviceProvisionedController).addCallback(mProvisionedCaptor.capture());
- mProvisionedListener = mProvisionedCaptor.getValue();
- }
-
- @Test
- public void testCleanUpViewStateOnEntryRemoved() {
- final NotificationEntry entry = buildEntry();
- mEntryListener.onEntryRemoved(
- entry,
- NotificationVisibility.obtain(entry.getKey(), 0, 0, true),
- false,
- UNDEFINED_DISMISS_REASON);
- verify(mListContainer).cleanUpViewStateForEntry(entry);
- }
-
- @Test
- public void testCallUpdateNotificationsOnDeviceProvisionedChange() {
- mProvisionedListener.onDeviceProvisionedChanged();
- verify(mEntryManager).updateNotifications(anyString());
- }
-
- private NotificationEntry buildEntry() {
- mNextNotifId++;
-
- Notification.Builder n = new Notification.Builder(mContext, "")
- .setSmallIcon(R.drawable.ic_person)
- .setContentTitle("Title")
- .setContentText("Text");
-
- return new NotificationEntryBuilder()
- .setPkg(TEST_PACKAGE_NAME)
- .setOpPkg(TEST_PACKAGE_NAME)
- .setId(mNextNotifId)
- .setUid(TEST_UID)
- .setNotification(n.build())
- .setUser(new UserHandle(ActivityManager.getCurrentUser()))
- .build();
- }
-
- private static final String TEST_PACKAGE_NAME = "test";
- private static final int TEST_UID = 0;
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
deleted file mode 100644
index b20f95cfad3a..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification.row;
-
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
-import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE;
-
-import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.NotificationChannel;
-import android.content.Context;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.view.View;
-
-import androidx.test.filters.FlakyTest;
-import androidx.test.filters.SmallTest;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/**
- * Tests for {@link NotificationBlockingHelperManager}.
- */
-@SmallTest
-@FlakyTest
-@org.junit.runner.RunWith(AndroidTestingRunner.class)
-@TestableLooper.RunWithLooper
-public class NotificationBlockingHelperManagerTest extends SysuiTestCase {
- private NotificationBlockingHelperManager mBlockingHelperManager;
-
- private NotificationTestHelper mHelper;
-
- @Mock private NotificationGutsManager mGutsManager;
- @Mock private NotificationEntryManager mEntryManager;
- @Mock private NotificationMenuRow mMenuRow;
- @Mock private NotificationMenuRowPlugin.MenuItem mMenuItem;
- @Mock private GroupMembershipManager mGroupMembershipManager;
-
- @Before
- public void setUp() {
- allowTestableLooperAsMainThread();
- MockitoAnnotations.initMocks(this);
- when(mGutsManager.openGuts(
- any(View.class),
- anyInt(),
- anyInt(),
- any(NotificationMenuRowPlugin.MenuItem.class)))
- .thenReturn(true);
- when(mMenuRow.getLongpressMenuItem(any(Context.class))).thenReturn(mMenuItem);
-
- mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this));
-
- mBlockingHelperManager = new NotificationBlockingHelperManager(
- mContext, mGutsManager, mEntryManager, mock(MetricsLogger.class),
- mGroupMembershipManager);
- // By default, have the shade visible/expanded.
- mBlockingHelperManager.setNotificationShadeExpanded(1f);
- }
-
- @Test
- public void testDismissCurrentBlockingHelper_nullBlockingHelperRow() {
- // By default, this shouldn't dismiss (no pointers/vars set up!)
- assertFalse(mBlockingHelperManager.dismissCurrentBlockingHelper());
- assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
- }
-
- @Test
- public void testDismissCurrentBlockingHelper_withDetachedBlockingHelperRow() throws Exception {
- ExpandableNotificationRow row = createBlockableRowSpy();
- row.setBlockingHelperShowing(true);
- when(row.isAttachedToWindow()).thenReturn(false);
- mBlockingHelperManager.setBlockingHelperRowForTest(row);
-
- assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
- assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
-
- verify(mEntryManager, times(0)).updateNotifications(anyString());
- }
-
- @Test
- public void testDismissCurrentBlockingHelper_withAttachedBlockingHelperRow() throws Exception {
- ExpandableNotificationRow row = createBlockableRowSpy();
- row.setBlockingHelperShowing(true);
- when(row.isAttachedToWindow()).thenReturn(true);
- mBlockingHelperManager.setBlockingHelperRowForTest(row);
-
- assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
- assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
-
- verify(mEntryManager).updateNotifications(anyString());
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_shown() throws Exception {
- ExpandableNotificationRow row = createBlockableRowSpy();
- modifyRanking(row.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
-
- assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-
- verify(mGutsManager).openGuts(row, 0, 0, mMenuItem);
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_notShownForMultiChannelGroup() throws Exception {
- ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(10);
- int i = 0;
- for (ExpandableNotificationRow childRow : groupRow.getAttachedChildren()) {
- modifyRanking(childRow.getEntry())
- .setChannel(
- new NotificationChannel(
- Integer.toString(i++), "", IMPORTANCE_DEFAULT))
- .build();
- }
-
- modifyRanking(groupRow.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
-
- assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(groupRow, mMenuRow));
-
- verify(mGutsManager, never()).openGuts(groupRow, 0, 0, mMenuItem);
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_shownForLargeGroup() throws Exception {
- ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(10);
- modifyRanking(groupRow.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
-
- assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(groupRow, mMenuRow));
-
- verify(mGutsManager).openGuts(groupRow, 0, 0, mMenuItem);
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_shownForOnlyChildNotification()
- throws Exception {
- ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(1);
- // Explicitly get the children container & call getViewAtPosition on it instead of the row
- // as other factors such as view expansion may cause us to get the parent row back instead
- // of the child row.
- ExpandableNotificationRow childRow = groupRow.getChildrenContainer().getViewAtPosition(0);
- modifyRanking(childRow.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
- assertFalse(childRow.getIsNonblockable());
-
- when(mGroupMembershipManager.isOnlyChildInGroup(childRow.getEntry())).thenReturn(true);
- assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(childRow, mMenuRow));
-
- verify(mGutsManager).openGuts(childRow, 0, 0, mMenuItem);
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_notShownDueToNeutralUserSentiment() throws Exception {
- ExpandableNotificationRow row = createBlockableRowSpy();
- modifyRanking(row.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEUTRAL)
- .build();
-
- assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_notShownDueToPositiveUserSentiment()
- throws Exception {
- ExpandableNotificationRow row = createBlockableRowSpy();
- modifyRanking(row.getEntry())
- .setUserSentiment(USER_SENTIMENT_POSITIVE)
- .build();
-
- assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_notShownDueToShadeVisibility() throws Exception {
- ExpandableNotificationRow row = createBlockableRowSpy();
- modifyRanking(row.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
- // Hide the shade
- mBlockingHelperManager.setNotificationShadeExpanded(0f);
-
- assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_notShownDueToNonblockability() throws Exception {
- ExpandableNotificationRow row = createBlockableRowSpy();
- when(row.getIsNonblockable()).thenReturn(true);
- modifyRanking(row.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
-
- assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
- }
-
- @Test
- public void testPerhapsShowBlockingHelper_notShownAsNotificationIsInMultipleChildGroup()
- throws Exception {
- ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(2);
- // Explicitly get the children container & call getViewAtPosition on it instead of the row
- // as other factors such as view expansion may cause us to get the parent row back instead
- // of the child row.
- ExpandableNotificationRow childRow = groupRow.getChildrenContainer().getViewAtPosition(0);
- modifyRanking(childRow.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
-
- assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(childRow, mMenuRow));
- }
-
- @Test
- public void testBlockingHelperShowAndDismiss() throws Exception{
- ExpandableNotificationRow row = createBlockableRowSpy();
- modifyRanking(row.getEntry())
- .setUserSentiment(USER_SENTIMENT_NEGATIVE)
- .build();
- when(row.isAttachedToWindow()).thenReturn(true);
-
- // Show check
- assertTrue(mBlockingHelperManager.perhapsShowBlockingHelper(row, mMenuRow));
-
- verify(mGutsManager).openGuts(row, 0, 0, mMenuItem);
-
- // Dismiss check
- assertTrue(mBlockingHelperManager.dismissCurrentBlockingHelper());
- assertTrue(mBlockingHelperManager.isBlockingHelperRowNull());
-
- verify(mEntryManager).updateNotifications(anyString());
- }
-
- @Test
- public void testNonBlockable_package() {
- mBlockingHelperManager.setNonBlockablePkgs(new String[] {"banana", "strawberry:pie"});
-
- assertFalse(mBlockingHelperManager.isNonblockable("orange", "pie"));
-
- assertTrue(mBlockingHelperManager.isNonblockable("banana", "pie"));
- }
-
- @Test
- public void testNonBlockable_channel() {
- mBlockingHelperManager.setNonBlockablePkgs(new String[] {"banana", "strawberry:pie"});
-
- assertFalse(mBlockingHelperManager.isNonblockable("strawberry", "shortcake"));
-
- assertTrue(mBlockingHelperManager.isNonblockable("strawberry", "pie"));
- }
-
- private ExpandableNotificationRow createBlockableRowSpy() throws Exception {
- ExpandableNotificationRow row = spy(mHelper.createRow());
- when(row.getIsNonblockable()).thenReturn(false);
- return row;
- }
-
- private ExpandableNotificationRow createBlockableGroupRowSpy(int numChildren) throws Exception {
- ExpandableNotificationRow row = spy(mHelper.createGroup(numChildren));
- when(row.getIsNonblockable()).thenReturn(false);
- return row;
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
index 8fd6842911de..35d2363b1c2a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt
@@ -3,19 +3,21 @@ package com.android.systemui.statusbar.notification.stack
import android.annotation.DimenRes
import android.widget.FrameLayout
import androidx.test.filters.SmallTest
+import com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.ShadeInterpolation.getContentAlpha
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.EmptyShadeView
+import com.android.systemui.statusbar.NotificationShelf
+import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
-import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.BypassController
-import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.SectionProvider
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.google.common.truth.Truth.assertThat
+import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
-import junit.framework.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.mockito.Mockito.mock
@@ -26,17 +28,20 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
private val hostView = FrameLayout(context)
private val stackScrollAlgorithm = StackScrollAlgorithm(context, hostView)
- private val expandableViewState = ExpandableViewState()
private val notificationRow = mock(ExpandableNotificationRow::class.java)
private val dumpManager = mock(DumpManager::class.java)
private val mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager::class.java)
+ private val notificationShelf = mock(NotificationShelf::class.java)
+ private val emptyShadeView = EmptyShadeView(context, /* attrs= */ null).apply {
+ layout(/* l= */ 0, /* t= */ 0, /* r= */ 100, /* b= */ 100)
+ }
private val ambientState = AmbientState(
- context,
- dumpManager,
- SectionProvider { _, _ -> false },
- BypassController { false },
- mStatusBarKeyguardViewManager
+ context,
+ dumpManager,
+ /* sectionProvider */ { _, _ -> false },
+ /* bypassController */ { false },
+ mStatusBarKeyguardViewManager
)
private val testableResources = mContext.orCreateTestableResources
@@ -49,7 +54,9 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
@Before
fun setUp() {
- whenever(notificationRow.viewState).thenReturn(expandableViewState)
+ whenever(notificationShelf.viewState).thenReturn(ExpandableViewState())
+ whenever(notificationRow.viewState).thenReturn(ExpandableViewState())
+
hostView.addView(notificationRow)
}
@@ -60,7 +67,8 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
stackScrollAlgorithm.resetViewStates(ambientState, 0)
- assertThat(expandableViewState.yTranslation).isEqualTo(stackScrollAlgorithm.mHeadsUpInset)
+ assertThat(notificationRow.viewState.yTranslation)
+ .isEqualTo(stackScrollAlgorithm.mHeadsUpInset)
}
@Test
@@ -75,15 +83,12 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
stackScrollAlgorithm.resetViewStates(ambientState, 0)
// top margin presence should decrease heads up translation up to minHeadsUpTranslation
- assertThat(expandableViewState.yTranslation).isEqualTo(minHeadsUpTranslation)
+ assertThat(notificationRow.viewState.yTranslation).isEqualTo(minHeadsUpTranslation)
}
@Test
fun resetViewStates_emptyShadeView_isCenteredVertically() {
stackScrollAlgorithm.initView(context)
- val emptyShadeView = EmptyShadeView(context, /* attrs= */ null).apply {
- layout(/* l= */ 0, /* t= */ 0, /* r= */ 100, /* b= */ 100)
- }
hostView.removeAllViews()
hostView.addView(emptyShadeView)
ambientState.layoutMaxHeight = 1280
@@ -98,6 +103,121 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
}
@Test
+ fun resetViewStates_hunGoingToShade_viewBecomesOpaque() {
+ whenever(notificationRow.isAboveShelf).thenReturn(true)
+ ambientState.isShadeExpanded = true
+ ambientState.trackedHeadsUpRow = notificationRow
+ stackScrollAlgorithm.initView(context)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ assertThat(notificationRow.viewState.alpha).isEqualTo(1f)
+ }
+
+ @Test
+ fun resetViewStates_isExpansionChanging_viewBecomesTransparent() {
+ whenever(mStatusBarKeyguardViewManager.isBouncerInTransit).thenReturn(false)
+ ambientState.isExpansionChanging = true
+ ambientState.expansionFraction = 0.25f
+ stackScrollAlgorithm.initView(context)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ val expected = getContentAlpha(0.25f)
+ assertThat(notificationRow.viewState.alpha).isEqualTo(expected)
+ }
+
+ @Test
+ fun resetViewStates_isExpansionChangingWhileBouncerInTransit_viewBecomesTransparent() {
+ whenever(mStatusBarKeyguardViewManager.isBouncerInTransit).thenReturn(true)
+ ambientState.isExpansionChanging = true
+ ambientState.expansionFraction = 0.25f
+ stackScrollAlgorithm.initView(context)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ val expected = aboutToShowBouncerProgress(0.25f)
+ assertThat(notificationRow.viewState.alpha).isEqualTo(expected)
+ }
+
+ @Test
+ fun resetViewStates_isOnKeyguard_viewBecomesTransparent() {
+ ambientState.setStatusBarState(StatusBarState.KEYGUARD)
+ ambientState.hideAmount = 0.25f
+ stackScrollAlgorithm.initView(context)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ assertThat(notificationRow.viewState.alpha).isEqualTo(1f - ambientState.hideAmount)
+ }
+
+ @Test
+ fun resetViewStates_isOnKeyguard_emptyShadeViewBecomesTransparent() {
+ ambientState.setStatusBarState(StatusBarState.KEYGUARD)
+ ambientState.fractionToShade = 0.25f
+ stackScrollAlgorithm.initView(context)
+ hostView.removeAllViews()
+ hostView.addView(emptyShadeView)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ val expected = getContentAlpha(ambientState.fractionToShade)
+ assertThat(emptyShadeView.viewState.alpha).isEqualTo(expected)
+ }
+
+ @Test
+ fun resetViewStates_isOnKeyguard_emptyShadeViewBecomesOpaque() {
+ ambientState.setStatusBarState(StatusBarState.SHADE)
+ ambientState.fractionToShade = 0.25f
+ stackScrollAlgorithm.initView(context)
+ hostView.removeAllViews()
+ hostView.addView(emptyShadeView)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ assertThat(emptyShadeView.viewState.alpha).isEqualTo(1f)
+ }
+
+ @Test
+ fun resetViewStates_hiddenShelf_viewAlphaDoesNotChange() {
+ val expected = notificationShelf.viewState.alpha
+ notificationShelf.viewState.hidden = true
+ ambientState.shelf = notificationShelf
+ stackScrollAlgorithm.initView(context)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ assertThat(notificationShelf.viewState.alpha).isEqualTo(expected)
+ }
+
+ @Test
+ fun resetViewStates_shelfTopLessThanViewTop_hidesView() {
+ notificationRow.viewState.yTranslation = 10f
+ notificationShelf.viewState.yTranslation = 0.9f
+ notificationShelf.viewState.hidden = false
+ ambientState.shelf = notificationShelf
+ stackScrollAlgorithm.initView(context)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ assertThat(notificationRow.viewState.alpha).isEqualTo(0f)
+ }
+
+ @Test
+ fun resetViewStates_shelfTopGreaterOrEqualThanViewTop_viewAlphaDoesNotChange() {
+ val expected = notificationRow.viewState.alpha
+ notificationRow.viewState.yTranslation = 10f
+ notificationShelf.viewState.yTranslation = 10f
+ notificationShelf.viewState.hidden = false
+ ambientState.shelf = notificationShelf
+ stackScrollAlgorithm.initView(context)
+
+ stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0)
+
+ assertThat(notificationRow.viewState.alpha).isEqualTo(expected)
+ }
+
+ @Test
fun getGapForLocation_onLockscreen_returnsSmallGap() {
val gap = stackScrollAlgorithm.getGapForLocation(
/* fractionToShade= */ 0f, /* onKeyguard= */ true)
@@ -267,7 +387,6 @@ class StackScrollAlgorithmTest : SysuiTestCase() {
assertEquals(10f, expandableViewState.yTranslation)
}
-
@Test
fun clampHunToTop_viewYFarAboveVisibleStack_heightCollapsed() {
val expandableViewState = ExpandableViewState()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
index a6b7e5103c78..ca98143044c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarIconControllerTest.java
@@ -58,7 +58,6 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
@Before
public void setup() {
injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
- mDependency.injectMockDependency(DarkIconDispatcher.class);
}
@Test
@@ -75,7 +74,8 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
layout,
mock(FeatureFlags.class),
mock(StatusBarPipelineFlags.class),
- () -> mock(WifiViewModel.class));
+ () -> mock(WifiViewModel.class),
+ mock(DarkIconDispatcher.class));
testCallOnAdd_forManager(manager);
}
@@ -116,8 +116,10 @@ public class StatusBarIconControllerTest extends LeakCheckedTest {
LinearLayout group,
FeatureFlags featureFlags,
StatusBarPipelineFlags statusBarPipelineFlags,
- Provider<WifiViewModel> wifiViewModelProvider) {
- super(group, featureFlags, statusBarPipelineFlags, wifiViewModelProvider);
+ Provider<WifiViewModel> wifiViewModelProvider,
+ DarkIconDispatcher darkIconDispatcher) {
+ super(group, featureFlags, statusBarPipelineFlags, wifiViewModelProvider,
+ darkIconDispatcher);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
index 982927148a2e..d070ba0e47be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt
@@ -473,6 +473,40 @@ class WifiRepositoryImplTest : SysuiTestCase() {
job.cancel()
}
+ /** Regression test for b/244173280. */
+ @Test
+ fun wifiNetwork_multipleSubscribers_newSubscribersGetCurrentValue() = runBlocking(IMMEDIATE) {
+ var latest1: WifiNetworkModel? = null
+ val job1 = underTest
+ .wifiNetwork
+ .onEach { latest1 = it }
+ .launchIn(this)
+
+ getNetworkCallback()
+ .onCapabilitiesChanged(NETWORK, createWifiNetworkCapabilities(PRIMARY_WIFI_INFO))
+
+ assertThat(latest1 is WifiNetworkModel.Active).isTrue()
+ val latest1Active = latest1 as WifiNetworkModel.Active
+ assertThat(latest1Active.networkId).isEqualTo(NETWORK_ID)
+ assertThat(latest1Active.ssid).isEqualTo(SSID)
+
+ // WHEN we add a second subscriber after having already emitted a value
+ var latest2: WifiNetworkModel? = null
+ val job2 = underTest
+ .wifiNetwork
+ .onEach { latest2 = it }
+ .launchIn(this)
+
+ // THEN the second subscribe receives the already-emitted value
+ assertThat(latest2 is WifiNetworkModel.Active).isTrue()
+ val latest2Active = latest2 as WifiNetworkModel.Active
+ assertThat(latest2Active.networkId).isEqualTo(NETWORK_ID)
+ assertThat(latest2Active.ssid).isEqualTo(SSID)
+
+ job1.cancel()
+ job2.cancel()
+ }
+
@Test
fun wifiActivity_nullWifiManager_receivesDefault() = runBlocking(IMMEDIATE) {
underTest = WifiRepositoryImpl(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
index 0dd6cbb7995a..c3805ad36533 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt
@@ -28,6 +28,7 @@ import com.android.internal.util.UserIcons
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.qs.tiles.UserDetailItemView
+import com.android.systemui.user.data.source.UserRecord
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
@@ -38,8 +39,8 @@ import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@@ -186,13 +187,14 @@ class KeyguardUserSwitcherAdapterTest : SysuiTestCase() {
}
private fun createUserRecord(isCurrentUser: Boolean, isGuestUser: Boolean) =
- UserSwitcherController.UserRecord(
- userInfo,
- picture,
- isGuestUser,
- isCurrentUser,
- false /* isAddUser */,
- false /* isRestricted */,
- true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ UserRecord(
+ userInfo,
+ picture,
+ isGuestUser,
+ isCurrentUser,
+ false /* isAddUser */,
+ false /* isRestricted */,
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */
+ )
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
index 359a780d2a94..8dcd4bb3b738 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
@@ -56,6 +56,7 @@ import com.android.systemui.qs.user.UserSwitchDialogController
import com.android.systemui.settings.UserTracker
import com.android.systemui.shade.NotificationShadeWindowView
import com.android.systemui.telephony.TelephonyListenerManager
+import com.android.systemui.user.data.source.UserRecord
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
@@ -235,15 +236,16 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Test
fun testSwitchUser_parentDialogDismissed() {
- val otherUserRecord = UserSwitcherController.UserRecord(
- secondaryUser,
- picture,
- false /* guest */,
- false /* current */,
- false /* isAddUser */,
- false /* isRestricted */,
- true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ val otherUserRecord = UserRecord(
+ secondaryUser,
+ picture,
+ false /* guest */,
+ false /* current */,
+ false /* isAddUser */,
+ false /* isRestricted */,
+ true /* isSwitchToEnabled */,
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(ownerId)
`when`(userTracker.userInfo).thenReturn(ownerInfo)
@@ -255,7 +257,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Test
fun testAddGuest_okButtonPressed() {
- val emptyGuestUserRecord = UserSwitcherController.UserRecord(
+ val emptyGuestUserRecord =
+ UserRecord(
null,
null,
true /* guest */,
@@ -263,7 +266,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(ownerId)
`when`(userTracker.userInfo).thenReturn(ownerInfo)
@@ -282,7 +286,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Test
fun testAddGuest_parentDialogDismissed() {
- val emptyGuestUserRecord = UserSwitcherController.UserRecord(
+ val emptyGuestUserRecord =
+ UserRecord(
null,
null,
true /* guest */,
@@ -290,7 +295,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(ownerId)
`when`(userTracker.userInfo).thenReturn(ownerInfo)
@@ -305,7 +311,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Test
fun testRemoveGuest_removeButtonPressed_isLogged() {
- val currentGuestUserRecord = UserSwitcherController.UserRecord(
+ val currentGuestUserRecord =
+ UserRecord(
guestInfo,
picture,
true /* guest */,
@@ -313,7 +320,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(guestInfo.id)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -331,7 +339,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Test
fun testRemoveGuest_removeButtonPressed_dialogDismissed() {
- val currentGuestUserRecord = UserSwitcherController.UserRecord(
+ val currentGuestUserRecord =
+ UserRecord(
guestInfo,
picture,
true /* guest */,
@@ -339,7 +348,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(guestInfo.id)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -353,7 +363,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Test
fun testRemoveGuest_dialogShowerUsed() {
- val currentGuestUserRecord = UserSwitcherController.UserRecord(
+ val currentGuestUserRecord =
+ UserRecord(
guestInfo,
picture,
true /* guest */,
@@ -361,7 +372,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(guestInfo.id)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -376,7 +388,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Test
fun testRemoveGuest_cancelButtonPressed_isNotLogged() {
- val currentGuestUserRecord = UserSwitcherController.UserRecord(
+ val currentGuestUserRecord =
+ UserRecord(
guestInfo,
picture,
true /* guest */,
@@ -384,7 +397,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(guestId)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -398,7 +412,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Test
fun testWipeGuest_startOverButtonPressed_isLogged() {
- val currentGuestUserRecord = UserSwitcherController.UserRecord(
+ val currentGuestUserRecord =
+ UserRecord(
guestInfo,
picture,
true /* guest */,
@@ -406,7 +421,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(guestId)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -433,7 +449,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Test
fun testWipeGuest_continueButtonPressed_isLogged() {
- val currentGuestUserRecord = UserSwitcherController.UserRecord(
+ val currentGuestUserRecord =
+ UserRecord(
guestInfo,
picture,
true /* guest */,
@@ -441,7 +458,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
`when`(userTracker.userId).thenReturn(guestId)
`when`(userTracker.userInfo).thenReturn(guestInfo)
@@ -470,11 +488,13 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Test
fun test_getCurrentUserName_shouldReturnNameOfTheCurrentUser() {
fun addUser(id: Int, name: String, isCurrent: Boolean) {
- userSwitcherController.users.add(UserSwitcherController.UserRecord(
+ userSwitcherController.users.add(
+ UserRecord(
UserInfo(id, name, 0),
null, false, isCurrent, false,
false, false, false
- ))
+ )
+ )
}
val bgUserName = "background_user"
val fgUserName = "foreground_user"
@@ -593,7 +613,7 @@ class UserSwitcherControllerTest : SysuiTestCase() {
@Test
fun onUserItemClicked_guest_runsOnBgThread() {
val dialogShower = mock(UserSwitchDialogController.DialogShower::class.java)
- val guestUserRecord = UserSwitcherController.UserRecord(
+ val guestUserRecord = UserRecord(
null,
picture,
true /* guest */,
@@ -601,7 +621,8 @@ class UserSwitcherControllerTest : SysuiTestCase() {
false /* isAddUser */,
false /* isRestricted */,
true /* isSwitchToEnabled */,
- false /* isAddSupervisedUser */)
+ false /* isAddSupervisedUser */
+ )
userSwitcherController.onUserListItemClicked(guestUserRecord, dialogShower)
assertTrue(bgExecutor.numPending() > 0)
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 6a6d2bb44d48..2b858ad045d8 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -683,8 +683,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_PACKAGE_BROADCAST_RECEIVER)) {
mTraceManager.logTrace(LOG_TAG + ".PM.onHandleForceStop",
FLAGS_PACKAGE_BROADCAST_RECEIVER,
- "intent=" + intent + ";packages=" + packages + ";uid=" + uid
- + ";doit=" + doit);
+ "intent=" + intent + ";packages=" + Arrays.toString(packages)
+ + ";uid=" + uid + ";doit=" + doit);
}
synchronized (mLock) {
final int userId = getChangingUserId();
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java b/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java
index f731c440d5f3..d20fa8ecebdf 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/MultiFingerSwipe.java
@@ -447,7 +447,7 @@ class MultiFingerSwipe extends GestureMatcher {
StringBuilder builder = new StringBuilder(super.toString());
if (getState() != STATE_GESTURE_CANCELED) {
builder.append(", mBase: ")
- .append(mBase.toString())
+ .append(Arrays.toString(mBase))
.append(", mMinPixelsBetweenSamplesX:")
.append(mMinPixelsBetweenSamplesX)
.append(", mMinPixelsBetweenSamplesY:")
diff --git a/services/backup/java/com/android/server/backup/UserBackupManagerService.java b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
index 907daa34826f..aec5f5ef9ff9 100644
--- a/services/backup/java/com/android/server/backup/UserBackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/UserBackupManagerService.java
@@ -2830,7 +2830,7 @@ public class UserBackupManagerService {
+ " includekeyvalue="
+ doKeyValue
+ " pkgs="
- + pkgList));
+ + Arrays.toString(pkgList)));
}
Slog.i(TAG, addUserIdToLogMessage(mUserId, "Beginning adb backup..."));
diff --git a/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java b/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
index 5dacdb40713b..d0300ff19178 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupEligibilityRules.java
@@ -25,9 +25,9 @@ import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import android.annotation.Nullable;
import android.app.backup.BackupManager.OperationType;
import android.app.backup.BackupTransport;
+import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
-import android.app.compat.CompatChanges;
import android.compat.annotation.Overridable;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
@@ -46,6 +46,7 @@ import com.android.server.backup.transport.TransportConnection;
import com.google.android.collect.Sets;
+import java.util.Arrays;
import java.util.Set;
/**
@@ -360,8 +361,8 @@ public class BackupEligibilityRules {
}
if (DEBUG) {
- Slog.v(TAG, "signaturesMatch(): stored=" + storedSigs + " device="
- + signingInfo.getApkContentsSigners());
+ Slog.v(TAG, "signaturesMatch(): stored=" + Arrays.toString(storedSigs)
+ + " device=" + Arrays.toString(signingInfo.getApkContentsSigners()));
}
final int nStored = storedSigs.length;
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 3d8dc148b7e2..bd1ecb23611e 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -1305,4 +1305,7 @@ public abstract class PackageManagerInternal {
* {@link android.Manifest.permission#INTERACT_ACROSS_USERS}.
*/
public abstract @SignatureResult int checkUidSignaturesForAllUsers(int uid1, int uid2);
+
+ public abstract void setPackageStoppedState(@NonNull String packageName, boolean stopped,
+ @UserIdInt int userId);
}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 01af23da0f99..a580f985dd13 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -4236,9 +4236,8 @@ public final class ActiveServices {
// Service is now being launched, its package can't be stopped.
try {
- AppGlobals.getPackageManager().setPackageStoppedState(
+ mAm.mPackageManagerInt.setPackageStoppedState(
r.packageName, false, r.userId);
- } catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ r.packageName + ": " + e);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index be0335e93d40..2cf24fa9df1f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -659,7 +659,7 @@ public class ActivityManagerService extends IActivityManager.Stub
final BroadcastQueue mFgOffloadBroadcastQueue;
// Convenient for easy iteration over the queues. Foreground is first
// so that dispatch of foreground broadcasts gets precedence.
- final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[4];
+ final BroadcastQueue[] mBroadcastQueues;
@GuardedBy("this")
BroadcastStats mLastBroadcastStats;
@@ -670,25 +670,33 @@ public class ActivityManagerService extends IActivityManager.Stub
TraceErrorLogger mTraceErrorLogger;
BroadcastQueue broadcastQueueForIntent(Intent intent) {
- if (isOnFgOffloadQueue(intent.getFlags())) {
+ return broadcastQueueForFlags(intent.getFlags(), intent);
+ }
+
+ BroadcastQueue broadcastQueueForFlags(int flags) {
+ return broadcastQueueForFlags(flags, null);
+ }
+
+ BroadcastQueue broadcastQueueForFlags(int flags, Object cookie) {
+ if (isOnFgOffloadQueue(flags)) {
if (DEBUG_BROADCAST_BACKGROUND) {
Slog.i(TAG_BROADCAST,
- "Broadcast intent " + intent + " on foreground offload queue");
+ "Broadcast intent " + cookie + " on foreground offload queue");
}
return mFgOffloadBroadcastQueue;
}
- if (isOnBgOffloadQueue(intent.getFlags())) {
+ if (isOnBgOffloadQueue(flags)) {
if (DEBUG_BROADCAST_BACKGROUND) {
Slog.i(TAG_BROADCAST,
- "Broadcast intent " + intent + " on background offload queue");
+ "Broadcast intent " + cookie + " on background offload queue");
}
return mBgOffloadBroadcastQueue;
}
- final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
+ final boolean isFg = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
if (DEBUG_BROADCAST_BACKGROUND) Slog.i(TAG_BROADCAST,
- "Broadcast intent " + intent + " on "
+ "Broadcast intent " + cookie + " on "
+ (isFg ? "foreground" : "background") + " queue");
return (isFg) ? mFgBroadcastQueue : mBgBroadcastQueue;
}
@@ -2323,7 +2331,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mOomAdjuster = new OomAdjuster(this, mProcessList, activeUids, handlerThread);
mIntentFirewall = null;
- mProcessStats = null;
+ mProcessStats = new ProcessStatsService(this, mContext.getCacheDir());
mCpHelper = new ContentProviderHelper(this, false);
mServices = null;
mSystemThread = null;
@@ -2343,6 +2351,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mPendingStartActivityUids = new PendingStartActivityUids();
mUseFifoUiScheduling = false;
mEnableOffloadQueue = false;
+ mBroadcastQueues = new BroadcastQueue[0];
mFgBroadcastQueue = mBgBroadcastQueue = mBgOffloadBroadcastQueue =
mFgOffloadBroadcastQueue = null;
mComponentAliasResolver = new ComponentAliasResolver(this);
@@ -2401,6 +2410,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mEnableOffloadQueue = SystemProperties.getBoolean(
"persist.device_config.activity_manager_native_boot.offload_queue_enabled", true);
+ mBroadcastQueues = new BroadcastQueue[4];
mFgBroadcastQueue = new BroadcastQueueImpl(this, mHandler,
"foreground", foreConstants, false);
mBgBroadcastQueue = new BroadcastQueueImpl(this, mHandler,
@@ -6727,9 +6737,8 @@ public class ActivityManagerService extends IActivityManager.Stub
// TODO: how set package stopped state should work for sdk sandboxes?
if (!isSdkSandbox) {
try {
- AppGlobals.getPackageManager().setPackageStoppedState(
+ mPackageManagerInt.setPackageStoppedState(
info.packageName, false, UserHandle.getUserId(app.uid));
- } catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ info.packageName + ": " + e);
@@ -8739,12 +8748,40 @@ public class ActivityManagerService extends IActivityManager.Stub
if (process.info.isInstantApp()) {
sb.append("Instant-App: true\n");
}
+
if (isSdkSandboxUid(process.uid)) {
+ final int appUid = Process.getAppUidForSdkSandboxUid(process.uid);
+ try {
+ String[] clientPackages = pm.getPackagesForUid(appUid);
+ // In shared UID case, don't add the package information
+ if (clientPackages.length == 1) {
+ appendSdkSandboxClientPackageHeader(sb, clientPackages[0], callingUserId);
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error getting packages for client app uid: " + appUid, e);
+ }
sb.append("SdkSandbox: true\n");
}
}
}
+ private void appendSdkSandboxClientPackageHeader(StringBuilder sb, String pkg, int userId) {
+ final IPackageManager pm = AppGlobals.getPackageManager();
+ sb.append("SdkSandbox-Client-Package: ").append(pkg);
+ try {
+ final PackageInfo pi = pm.getPackageInfo(pkg, 0, userId);
+ if (pi != null) {
+ sb.append(" v").append(pi.getLongVersionCode());
+ if (pi.versionName != null) {
+ sb.append(" (").append(pi.versionName).append(")");
+ }
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Error getting package info for SDK sandbox client: " + pkg, e);
+ }
+ sb.append("\n");
+ }
+
private static String processClass(ProcessRecord process) {
if (process == null || process.getPid() == MY_PID) {
return "system_server";
@@ -12845,9 +12882,8 @@ public class ActivityManagerService extends IActivityManager.Stub
// !!! TODO: currently no check here that we're already bound
// Backup agent is now in use, its package can't be stopped.
try {
- AppGlobals.getPackageManager().setPackageStoppedState(
+ mPackageManagerInt.setPackageStoppedState(
app.packageName, false, UserHandle.getUserId(app.uid));
- } catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ app.packageName + ": " + e);
@@ -13328,20 +13364,18 @@ public class ActivityManagerService extends IActivityManager.Stub
final long origId = Binder.clearCallingIdentity();
try {
boolean doTrim = false;
-
synchronized(this) {
ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder());
if (rl != null) {
final BroadcastRecord r = rl.curBroadcast;
- if (r != null && r == r.queue.getMatchingOrderedReceiver(r)) {
+ if (r != null) {
final boolean doNext = r.queue.finishReceiverLocked(
- r, r.resultCode, r.resultData, r.resultExtras,
+ receiver.asBinder(), r.resultCode, r.resultData, r.resultExtras,
r.resultAbort, false);
if (doNext) {
doTrim = true;
}
}
-
if (rl.app != null) {
rl.app.mReceivers.removeReceiver(rl);
}
@@ -14518,22 +14552,10 @@ public class ActivityManagerService extends IActivityManager.Stub
boolean doNext = false;
BroadcastRecord r;
BroadcastQueue queue;
-
synchronized(this) {
- if (isOnFgOffloadQueue(flags)) {
- queue = mFgOffloadBroadcastQueue;
- } else if (isOnBgOffloadQueue(flags)) {
- queue = mBgOffloadBroadcastQueue;
- } else {
- queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
- ? mFgBroadcastQueue : mBgBroadcastQueue;
- }
-
- r = queue.getMatchingOrderedReceiver(who);
- if (r != null) {
- doNext = r.queue.finishReceiverLocked(r, resultCode,
+ queue = broadcastQueueForFlags(flags);
+ doNext = queue.finishReceiverLocked(who, resultCode,
resultData, resultExtras, resultAbort, true);
- }
// updateOomAdjLocked() will be done here
trimApplicationsLocked(false, OomAdjuster.OOM_ADJ_REASON_FINISH_RECEIVER);
}
@@ -17881,6 +17903,13 @@ public class ActivityManagerService extends IActivityManager.Stub
}
/**
+ * Reset the dropbox rate limiter
+ */
+ void resetDropboxRateLimiter() {
+ mDropboxRateLimiter.reset();
+ }
+
+ /**
* Kill processes for the user with id userId and that depend on the package named packageName
*/
@Override
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 36908ce8c7b3..a42b2a48f886 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -363,6 +363,8 @@ final class ActivityManagerShellCommand extends ShellCommand {
return runGetBgRestrictionLevel(pw);
case "observe-foreground-process":
return runGetCurrentForegroundProcess(pw, mInternal, mTaskInterface);
+ case "reset-dropbox-rate-limiter":
+ return runResetDropboxRateLimiter();
default:
return handleDefaultCommands(cmd);
}
@@ -3577,6 +3579,11 @@ final class ActivityManagerShellCommand extends ShellCommand {
return 0;
}
+ int runResetDropboxRateLimiter() throws RemoteException {
+ mInternal.resetDropboxRateLimiter();
+ return 0;
+ }
+
private Resources getResources(PrintWriter pw) throws RemoteException {
// system resources does not contain all the device configuration, construct it manually.
Configuration config = mInterface.getConfiguration();
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 9be22c0e41c0..752c6b683e05 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -16,6 +16,8 @@
package com.android.server.am;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Intent;
@@ -24,8 +26,11 @@ import android.os.Handler;
import android.os.IBinder;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.annotations.GuardedBy;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.Objects;
import java.util.Set;
/**
@@ -34,22 +39,23 @@ import java.util.Set;
public abstract class BroadcastQueue {
public static final String TAG = "BroadcastQueue";
- final ActivityManagerService mService;
- final Handler mHandler;
- final BroadcastConstants mConstants;
- final BroadcastSkipPolicy mSkipPolicy;
- final String mQueueName;
-
- BroadcastQueue(ActivityManagerService service, Handler handler,
- String name, BroadcastConstants constants) {
- mService = service;
- mHandler = handler;
- mQueueName = name;
- mConstants = constants;
- mSkipPolicy = new BroadcastSkipPolicy(service);
+ final @NonNull ActivityManagerService mService;
+ final @NonNull Handler mHandler;
+ final @NonNull BroadcastConstants mConstants;
+ final @NonNull BroadcastSkipPolicy mSkipPolicy;
+ final @NonNull String mQueueName;
+
+ BroadcastQueue(@NonNull ActivityManagerService service, @NonNull Handler handler,
+ @NonNull String name, @NonNull BroadcastConstants constants,
+ @NonNull BroadcastSkipPolicy skipPolicy) {
+ mService = Objects.requireNonNull(service);
+ mHandler = Objects.requireNonNull(handler);
+ mQueueName = Objects.requireNonNull(name);
+ mConstants = Objects.requireNonNull(constants);
+ mSkipPolicy = Objects.requireNonNull(skipPolicy);
}
- void start(ContentResolver resolver) {
+ void start(@NonNull ContentResolver resolver) {
mConstants.startObserving(mHandler, resolver);
}
@@ -60,9 +66,11 @@ public abstract class BroadcastQueue {
public abstract boolean isDelayBehindServices();
- public abstract BroadcastRecord getPendingBroadcastLocked();
+ @GuardedBy("mService")
+ public abstract @Nullable BroadcastRecord getPendingBroadcastLocked();
- public abstract BroadcastRecord getActiveBroadcastLocked();
+ @GuardedBy("mService")
+ public abstract @Nullable BroadcastRecord getActiveBroadcastLocked();
/**
* Enqueue the given broadcast to be eventually dispatched.
@@ -73,9 +81,8 @@ public abstract class BroadcastQueue {
* When {@link Intent#FLAG_RECEIVER_REPLACE_PENDING} is set, this method
* internally handles replacement of any matching broadcasts.
*/
- public abstract void enqueueBroadcastLocked(BroadcastRecord r);
-
- public abstract BroadcastRecord getMatchingOrderedReceiver(IBinder receiver);
+ @GuardedBy("mService")
+ public abstract void enqueueBroadcastLocked(@NonNull BroadcastRecord r);
/**
* Signal delivered back from a {@link BroadcastReceiver} to indicate that
@@ -83,44 +90,55 @@ public abstract class BroadcastQueue {
* <p>
* If this signal isn't delivered back in a timely fashion, we assume the
* receiver has somehow wedged and we trigger an ANR.
+ *
+ * @param receiver the value to match against
+ * {@link BroadcastRecord#receiver} to identify the caller.
*/
- public abstract boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
- String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices);
+ @GuardedBy("mService")
+ public abstract boolean finishReceiverLocked(@NonNull IBinder receiver, int resultCode,
+ @Nullable String resultData, @Nullable Bundle resultExtras, boolean resultAbort,
+ boolean waitForServices);
+ @GuardedBy("mService")
public abstract void backgroundServicesFinishedLocked(int userId);
/**
* Signal from OS internals that the given process has just been actively
* attached, and is ready to begin receiving broadcasts.
*/
- public abstract boolean onApplicationAttachedLocked(ProcessRecord app);
+ @GuardedBy("mService")
+ public abstract boolean onApplicationAttachedLocked(@NonNull ProcessRecord app);
/**
* Signal from OS internals that the given process has timed out during
* an attempted start and attachment.
*/
- public abstract boolean onApplicationTimeoutLocked(ProcessRecord app);
+ @GuardedBy("mService")
+ public abstract boolean onApplicationTimeoutLocked(@NonNull ProcessRecord app);
/**
* Signal from OS internals that the given process, which had already been
* previously attached, has now encountered a problem such as crashing or
* not responding.
*/
- public abstract boolean onApplicationProblemLocked(ProcessRecord app);
+ @GuardedBy("mService")
+ public abstract boolean onApplicationProblemLocked(@NonNull ProcessRecord app);
/**
* Signal from OS internals that the given process has been killed, and is
* no longer actively running.
*/
- public abstract boolean onApplicationCleanupLocked(ProcessRecord app);
+ @GuardedBy("mService")
+ public abstract boolean onApplicationCleanupLocked(@NonNull ProcessRecord app);
/**
* Signal from OS internals that the given package (or some subset of that
* package) has been disabled or uninstalled, and that any pending
* broadcasts should be cleaned up.
*/
- public abstract boolean cleanupDisabledPackageReceiversLocked(
- String packageName, Set<String> filterByClasses, int userId, boolean doit);
+ @GuardedBy("mService")
+ public abstract boolean cleanupDisabledPackageReceiversLocked(@Nullable String packageName,
+ @Nullable Set<String> filterByClasses, int userId, boolean doit);
/**
* Quickly determine if this queue has broadcasts that are still waiting to
@@ -133,7 +151,7 @@ public abstract class BroadcastQueue {
/**
* Brief summary of internal state, useful for debugging purposes.
*/
- public abstract String describeState();
+ public abstract @NonNull String describeState();
/**
* Flush any broadcasts still waiting to be delivered, causing them to be
@@ -143,8 +161,10 @@ public abstract class BroadcastQueue {
*/
public abstract void flush();
- public abstract void dumpDebug(ProtoOutputStream proto, long fieldId);
+ public abstract void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId);
- public abstract boolean dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
- int opti, boolean dumpAll, String dumpPackage, boolean needSep);
+ @GuardedBy("mService")
+ public abstract boolean dumpLocked(@NonNull FileDescriptor fd, @NonNull PrintWriter pw,
+ @NonNull String[] args, int opti, boolean dumpAll, @Nullable String dumpPackage,
+ boolean needSep);
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueueImpl.java b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
index 2b3b21182a6c..d9146121fc27 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
@@ -42,7 +42,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
-import android.app.AppGlobals;
import android.app.BroadcastOptions;
import android.app.IApplicationThread;
import android.app.RemoteServiceException.CannotDeliverBroadcastException;
@@ -213,7 +212,14 @@ public class BroadcastQueueImpl extends BroadcastQueue {
BroadcastQueueImpl(ActivityManagerService service, Handler handler,
String name, BroadcastConstants constants, boolean allowDelayBehindServices) {
- super(service, handler, name, constants);
+ this(service, handler, name, constants, new BroadcastSkipPolicy(service),
+ allowDelayBehindServices);
+ }
+
+ BroadcastQueueImpl(ActivityManagerService service, Handler handler,
+ String name, BroadcastConstants constants, BroadcastSkipPolicy skipPolicy,
+ boolean allowDelayBehindServices) {
+ super(service, handler, name, constants, skipPolicy);
mHandler = new BroadcastHandler(handler.getLooper());
mDelayBehindServices = allowDelayBehindServices;
mDispatcher = new BroadcastDispatcher(this, mConstants, mHandler, mService);
@@ -520,10 +526,17 @@ public class BroadcastQueueImpl extends BroadcastQueue {
public BroadcastRecord getMatchingOrderedReceiver(IBinder receiver) {
BroadcastRecord br = mDispatcher.getActiveBroadcastLocked();
- if (br != null && br.receiver == receiver) {
- return br;
+ if (br == null) {
+ Slog.w(TAG_BROADCAST, "getMatchingOrderedReceiver [" + mQueueName
+ + "] no active broadcast");
+ return null;
}
- return null;
+ if (br.receiver != receiver) {
+ Slog.w(TAG_BROADCAST, "getMatchingOrderedReceiver [" + mQueueName
+ + "] active broadcast " + br.receiver + " doesn't match " + receiver);
+ return null;
+ }
+ return br;
}
// > 0 only, no worry about "eventual" recycling
@@ -551,6 +564,17 @@ public class BroadcastQueueImpl extends BroadcastQueue {
}, msgToken, (r.receiverTime + mConstants.ALLOW_BG_ACTIVITY_START_TIMEOUT));
}
+ public boolean finishReceiverLocked(IBinder receiver, int resultCode,
+ String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
+ final BroadcastRecord r = getMatchingOrderedReceiver(receiver);
+ if (r != null) {
+ return finishReceiverLocked(r, resultCode,
+ resultData, resultExtras, resultAbort, waitForServices);
+ } else {
+ return false;
+ }
+ }
+
public boolean finishReceiverLocked(BroadcastRecord r, int resultCode,
String resultData, Bundle resultExtras, boolean resultAbort, boolean waitForServices) {
final int state = r.state;
@@ -1354,9 +1378,8 @@ public class BroadcastQueueImpl extends BroadcastQueue {
// Broadcast is being executed, its package can't be stopped.
try {
- AppGlobals.getPackageManager().setPackageStoppedState(
+ mService.mPackageManagerInt.setPackageStoppedState(
r.curComponent.getPackageName(), false, r.userId);
- } catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ r.curComponent.getPackageName() + ": " + e);
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index 9abd01ac3ee9..78629b04cff2 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -464,10 +464,9 @@ public class ContentProviderHelper {
try {
checkTime(startTime,
"getContentProviderImpl: before set stopped state");
- AppGlobals.getPackageManager().setPackageStoppedState(
+ mService.mPackageManagerInt.setPackageStoppedState(
cpr.appInfo.packageName, false, userId);
checkTime(startTime, "getContentProviderImpl: after set stopped state");
- } catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ cpr.appInfo.packageName + ": " + e);
diff --git a/services/core/java/com/android/server/am/DropboxRateLimiter.java b/services/core/java/com/android/server/am/DropboxRateLimiter.java
index baf062d28457..6087f76687bf 100644
--- a/services/core/java/com/android/server/am/DropboxRateLimiter.java
+++ b/services/core/java/com/android/server/am/DropboxRateLimiter.java
@@ -19,11 +19,13 @@ package com.android.server.am;
import android.os.SystemClock;
import android.text.format.DateUtils;
import android.util.ArrayMap;
+import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
/** Rate limiter for adding errors into dropbox. */
public class DropboxRateLimiter {
+ private static final String TAG = "DropboxRateLimiter";
// After RATE_LIMIT_ALLOWED_ENTRIES have been collected (for a single breakdown of
// process/eventType) further entries will be rejected until RATE_LIMIT_BUFFER_DURATION has
// elapsed, after which the current count for this breakdown will be reset.
@@ -105,6 +107,15 @@ public class DropboxRateLimiter {
mLastMapCleanUp = now;
}
+ /** Resets the rate limiter memory. */
+ void reset() {
+ synchronized (mErrorClusterRecords) {
+ mErrorClusterRecords.clear();
+ }
+ mLastMapCleanUp = 0L;
+ Slog.i(TAG, "Rate limiter reset.");
+ }
+
String errorKey(String eventType, String processName) {
return eventType + processName;
}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index ccbca76d1868..48eb0de9011f 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -133,7 +133,6 @@ import com.android.server.SystemConfig;
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService.ProcessChangeItem;
import com.android.server.compat.PlatformCompat;
-import com.android.server.pm.dex.DexManager;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.wm.ActivityServiceConnectionsHolder;
@@ -1790,14 +1789,6 @@ public final class ProcessList {
if (app.info.isEmbeddedDexUsed()) {
runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES;
- } else if (app.info.isPrivilegedApp()) {
- final PackageList pkgList = app.getPkgList();
- synchronized (pkgList) {
- if (DexManager.isPackageSelectedToRunOob(
- pkgList.getPackageListLocked().keySet())) {
- runtimeFlags |= Zygote.ONLY_USE_SYSTEM_OAT_FILES;
- }
- }
}
if (!disableHiddenApiChecks && !mService.mHiddenApiBlacklist.isDisabled()) {
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java
index 028288f73564..dcadd5ff518c 100644
--- a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java
+++ b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java
@@ -29,6 +29,7 @@ import android.app.PendingIntent;
import android.app.ambientcontext.AmbientContextEvent;
import android.app.ambientcontext.AmbientContextEventRequest;
import android.app.ambientcontext.AmbientContextManager;
+import android.app.ambientcontext.IAmbientContextObserver;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
@@ -53,6 +54,8 @@ import com.android.server.infra.AbstractPerUserSystemService;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
+import java.util.function.Consumer;
/**
* Per-user manager service for {@link AmbientContextEvent}s.
@@ -165,20 +168,17 @@ final class AmbientContextManagerPerUserService extends
* package. A new registration from the same package will overwrite the previous registration.
*/
public void onRegisterObserver(AmbientContextEventRequest request,
- PendingIntent pendingIntent, RemoteCallback clientStatusCallback) {
+ String packageName, IAmbientContextObserver observer) {
synchronized (mLock) {
if (!setUpServiceIfNeeded()) {
Slog.w(TAG, "Detection service is not available at this moment.");
- sendStatusCallback(
- clientStatusCallback,
- AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
+ completeRegistration(observer, AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
return;
}
// Register package and add to existing ClientRequests cache
- startDetection(request, pendingIntent.getCreatorPackage(),
- createDetectionResultRemoteCallback(), clientStatusCallback);
- mMaster.newClientAdded(mUserId, request, pendingIntent, clientStatusCallback);
+ startDetection(request, packageName, observer);
+ mMaster.newClientAdded(mUserId, request, packageName, observer);
}
}
@@ -186,49 +186,46 @@ final class AmbientContextManagerPerUserService extends
* Returns a RemoteCallback that handles the status from the detection service, and
* sends results to the client callback.
*/
- private RemoteCallback getServerStatusCallback(RemoteCallback clientStatusCallback) {
+ private RemoteCallback getServerStatusCallback(Consumer<Integer> statusConsumer) {
return new RemoteCallback(result -> {
AmbientContextDetectionServiceStatus serviceStatus =
(AmbientContextDetectionServiceStatus) result.get(
AmbientContextDetectionServiceStatus.STATUS_RESPONSE_BUNDLE_KEY);
final long token = Binder.clearCallingIdentity();
try {
- String packageName = serviceStatus.getPackageName();
- Bundle bundle = new Bundle();
- bundle.putInt(
- AmbientContextManager.STATUS_RESPONSE_BUNDLE_KEY,
- serviceStatus.getStatusCode());
- clientStatusCallback.sendResult(bundle);
int statusCode = serviceStatus.getStatusCode();
+ statusConsumer.accept(statusCode);
Slog.i(TAG, "Got detection status of " + statusCode
- + " for " + packageName);
+ + " for " + serviceStatus.getPackageName());
} finally {
Binder.restoreCallingIdentity(token);
}
});
}
- @VisibleForTesting
void startDetection(AmbientContextEventRequest request, String callingPackage,
- RemoteCallback detectionResultCallback, RemoteCallback clientStatusCallback) {
+ IAmbientContextObserver observer) {
Slog.d(TAG, "Requested detection of " + request.getEventTypes());
synchronized (mLock) {
if (setUpServiceIfNeeded()) {
ensureRemoteServiceInitiated();
- mRemoteService.startDetection(request, callingPackage, detectionResultCallback,
- getServerStatusCallback(clientStatusCallback));
+ mRemoteService.startDetection(request, callingPackage,
+ createDetectionResultRemoteCallback(),
+ getServerStatusCallback(
+ statusCode -> completeRegistration(observer, statusCode)));
} else {
Slog.w(TAG, "No valid component found for AmbientContextDetectionService");
- sendStatusToCallback(clientStatusCallback,
+ completeRegistration(observer,
AmbientContextManager.STATUS_NOT_SUPPORTED);
}
}
}
/**
- * Sends an intent with a status code and empty events.
+ * Sends the result response with the specified status to the callback.
*/
- void sendStatusCallback(RemoteCallback statusCallback, int statusCode) {
+ static void sendStatusCallback(RemoteCallback statusCallback,
+ @AmbientContextManager.StatusCode int statusCode) {
Bundle bundle = new Bundle();
bundle.putInt(
AmbientContextManager.STATUS_RESPONSE_BUNDLE_KEY,
@@ -236,6 +233,15 @@ final class AmbientContextManagerPerUserService extends
statusCallback.sendResult(bundle);
}
+ static void completeRegistration(IAmbientContextObserver observer, int statusCode) {
+ try {
+ observer.onRegistrationComplete(statusCode);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call IAmbientContextObserver.onRegistrationComplete: "
+ + e.getMessage());
+ }
+ }
+
/**
* Unregisters the client from all previously registered events by removing from the
* mExistingRequests map, and unregister events from the service if those events are not
@@ -255,7 +261,7 @@ final class AmbientContextManagerPerUserService extends
synchronized (mLock) {
if (!setUpServiceIfNeeded()) {
Slog.w(TAG, "Detection service is not available at this moment.");
- sendStatusToCallback(statusCallback,
+ sendStatusCallback(statusCallback,
AmbientContextManager.STATUS_NOT_SUPPORTED);
return;
}
@@ -263,7 +269,8 @@ final class AmbientContextManagerPerUserService extends
mRemoteService.queryServiceStatus(
eventTypes,
callingPackage,
- getServerStatusCallback(statusCallback));
+ getServerStatusCallback(
+ statusCode -> sendStatusCallback(statusCallback, statusCode)));
}
}
@@ -350,18 +357,6 @@ final class AmbientContextManagerPerUserService extends
return ComponentName.unflattenFromString(consentComponent);
}
- /**
- * Sends the result response with the specified status to the callback.
- */
- void sendStatusToCallback(RemoteCallback callback,
- @AmbientContextManager.StatusCode int status) {
- Bundle bundle = new Bundle();
- bundle.putInt(
- AmbientContextManager.STATUS_RESPONSE_BUNDLE_KEY,
- status);
- callback.sendResult(bundle);
- }
-
@VisibleForTesting
void stopDetection(String packageName) {
Slog.d(TAG, "Stop detection for " + packageName);
@@ -377,13 +372,13 @@ final class AmbientContextManagerPerUserService extends
* Sends out the Intent to the client after the event is detected.
*
* @param pendingIntent Client's PendingIntent for callback
- * @param result result from the detection service
+ * @param events detected events from the detection service
*/
- private void sendDetectionResultIntent(PendingIntent pendingIntent,
- AmbientContextDetectionResult result) {
+ void sendDetectionResultIntent(PendingIntent pendingIntent,
+ List<AmbientContextEvent> events) {
Intent intent = new Intent();
intent.putExtra(AmbientContextManager.EXTRA_AMBIENT_CONTEXT_EVENTS,
- new ArrayList(result.getEvents()));
+ new ArrayList(events));
// Explicitly disallow the receiver from starting activities, to prevent apps from utilizing
// the PendingIntent as a backdoor to do this.
BroadcastOptions options = BroadcastOptions.makeBasic();
@@ -392,7 +387,7 @@ final class AmbientContextManagerPerUserService extends
pendingIntent.send(getContext(), 0, intent, null, null, null,
options.toBundle());
Slog.i(TAG, "Sending PendingIntent to " + pendingIntent.getCreatorPackage() + ": "
- + result);
+ + events);
} catch (PendingIntent.CanceledException e) {
Slog.w(TAG, "Couldn't deliver pendingIntent:" + pendingIntent);
}
@@ -405,16 +400,19 @@ final class AmbientContextManagerPerUserService extends
(AmbientContextDetectionResult) result.get(
AmbientContextDetectionResult.RESULT_RESPONSE_BUNDLE_KEY);
String packageName = detectionResult.getPackageName();
- PendingIntent pendingIntent = mMaster.getPendingIntent(mUserId, packageName);
- if (pendingIntent == null) {
+ IAmbientContextObserver observer = mMaster.getClientRequestObserver(
+ mUserId, packageName);
+ if (observer == null) {
return;
}
final long token = Binder.clearCallingIdentity();
try {
- sendDetectionResultIntent(pendingIntent, detectionResult);
+ observer.onEvents(detectionResult.getEvents());
Slog.i(TAG, "Got detection result of " + detectionResult.getEvents()
+ " for " + packageName);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call IAmbientContextObserver.onEvents: " + e.getMessage());
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
index 4206262398c7..e205e84cea26 100644
--- a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
+++ b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
@@ -27,10 +27,12 @@ import android.app.ambientcontext.AmbientContextEvent;
import android.app.ambientcontext.AmbientContextEventRequest;
import android.app.ambientcontext.AmbientContextManager;
import android.app.ambientcontext.IAmbientContextManager;
+import android.app.ambientcontext.IAmbientContextObserver;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManagerInternal;
import android.os.RemoteCallback;
+import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.UserHandle;
@@ -48,6 +50,7 @@ import com.android.server.pm.KnownPackages;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -67,31 +70,27 @@ public class AmbientContextManagerService extends
static class ClientRequest {
private final int mUserId;
private final AmbientContextEventRequest mRequest;
- private final PendingIntent mPendingIntent;
- private final RemoteCallback mClientStatusCallback;
+ private final String mPackageName;
+ private final IAmbientContextObserver mObserver;
ClientRequest(int userId, AmbientContextEventRequest request,
- PendingIntent pendingIntent, RemoteCallback clientStatusCallback) {
+ String packageName, IAmbientContextObserver observer) {
this.mUserId = userId;
this.mRequest = request;
- this.mPendingIntent = pendingIntent;
- this.mClientStatusCallback = clientStatusCallback;
+ this.mPackageName = packageName;
+ this.mObserver = observer;
}
String getPackageName() {
- return mPendingIntent.getCreatorPackage();
+ return mPackageName;
}
AmbientContextEventRequest getRequest() {
return mRequest;
}
- PendingIntent getPendingIntent() {
- return mPendingIntent;
- }
-
- RemoteCallback getClientStatusCallback() {
- return mClientStatusCallback;
+ IAmbientContextObserver getObserver() {
+ return mObserver;
}
boolean hasUserId(int userId) {
@@ -139,16 +138,16 @@ public class AmbientContextManagerService extends
}
void newClientAdded(int userId, AmbientContextEventRequest request,
- PendingIntent pendingIntent, RemoteCallback clientStatusCallback) {
- Slog.d(TAG, "New client added: " + pendingIntent.getCreatorPackage());
+ String callingPackage, IAmbientContextObserver observer) {
+ Slog.d(TAG, "New client added: " + callingPackage);
// Remove any existing ClientRequest for this user and package.
mExistingClientRequests.removeAll(
- findExistingRequests(userId, pendingIntent.getCreatorPackage()));
+ findExistingRequests(userId, callingPackage));
// Add to existing ClientRequests
mExistingClientRequests.add(
- new ClientRequest(userId, request, pendingIntent, clientStatusCallback));
+ new ClientRequest(userId, request, callingPackage, observer));
}
void clientRemoved(int userId, String packageName) {
@@ -167,10 +166,10 @@ public class AmbientContextManagerService extends
}
@Nullable
- PendingIntent getPendingIntent(int userId, String packageName) {
+ IAmbientContextObserver getClientRequestObserver(int userId, String packageName) {
for (ClientRequest clientRequest : mExistingClientRequests) {
if (clientRequest.hasUserIdAndPackageName(userId, packageName)) {
- return clientRequest.getPendingIntent();
+ return clientRequest.getObserver();
}
}
return null;
@@ -236,15 +235,13 @@ public class AmbientContextManagerService extends
* Requires ACCESS_AMBIENT_CONTEXT_EVENT permission.
*/
void startDetection(@UserIdInt int userId, AmbientContextEventRequest request,
- String packageName, RemoteCallback detectionResultCallback,
- RemoteCallback statusCallback) {
+ String packageName, IAmbientContextObserver observer) {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
synchronized (mLock) {
final AmbientContextManagerPerUserService service = getServiceForUserLocked(userId);
if (service != null) {
- service.startDetection(request, packageName, detectionResultCallback,
- statusCallback);
+ service.startDetection(request, packageName, observer);
} else {
Slog.i(TAG, "service not available for user_id: " + userId);
}
@@ -297,8 +294,7 @@ public class AmbientContextManagerService extends
Slog.d(TAG, "Restoring detection for " + clientRequest.getPackageName());
service.startDetection(clientRequest.getRequest(),
clientRequest.getPackageName(),
- service.createDetectionResultRemoteCallback(),
- clientRequest.getClientStatusCallback());
+ clientRequest.getObserver());
}
}
}
@@ -328,16 +324,45 @@ public class AmbientContextManagerService extends
Objects.requireNonNull(request);
Objects.requireNonNull(resultPendingIntent);
Objects.requireNonNull(statusCallback);
+ // Wrap the PendingIntent and statusCallback in a IAmbientContextObserver to make the
+ // code unified
+ IAmbientContextObserver observer = new IAmbientContextObserver.Stub() {
+ @Override
+ public void onEvents(List<AmbientContextEvent> events) throws RemoteException {
+ mService.sendDetectionResultIntent(resultPendingIntent, events);
+ }
+
+ @Override
+ public void onRegistrationComplete(int statusCode) throws RemoteException {
+ AmbientContextManagerPerUserService.sendStatusCallback(statusCallback,
+ statusCode);
+ }
+ };
+ registerObserverWithCallback(request, resultPendingIntent.getCreatorPackage(),
+ observer);
+ }
+
+ /**
+ * Register an observer for Ambient Context events.
+ */
+ @Override
+ public void registerObserverWithCallback(AmbientContextEventRequest request,
+ String packageName,
+ IAmbientContextObserver observer) {
+ Slog.i(TAG, "AmbientContextManagerService registerObserverWithCallback.");
+ Objects.requireNonNull(request);
+ Objects.requireNonNull(packageName);
+ Objects.requireNonNull(observer);
mContext.enforceCallingOrSelfPermission(
Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
- assertCalledByPackageOwner(resultPendingIntent.getCreatorPackage());
+ assertCalledByPackageOwner(packageName);
if (!mIsServiceEnabled) {
Slog.w(TAG, "Service not available.");
- mService.sendStatusCallback(statusCallback,
+ AmbientContextManagerPerUserService.completeRegistration(observer,
AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
return;
}
- mService.onRegisterObserver(request, resultPendingIntent, statusCallback);
+ mService.onRegisterObserver(request, packageName, observer);
}
@Override
@@ -359,7 +384,7 @@ public class AmbientContextManagerService extends
assertCalledByPackageOwner(callingPackage);
if (!mIsServiceEnabled) {
Slog.w(TAG, "Detection service not available.");
- mService.sendStatusToCallback(statusCallback,
+ AmbientContextManagerPerUserService.sendStatusCallback(statusCallback,
AmbientContextManager.STATUS_SERVICE_UNAVAILABLE);
return;
}
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java b/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java
index ec6c2f00b3b1..a3ffcde802f3 100644
--- a/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java
+++ b/services/core/java/com/android/server/ambientcontext/AmbientContextShellCommand.java
@@ -22,13 +22,15 @@ import android.annotation.NonNull;
import android.app.ambientcontext.AmbientContextEvent;
import android.app.ambientcontext.AmbientContextEventRequest;
import android.app.ambientcontext.AmbientContextManager;
+import android.app.ambientcontext.IAmbientContextObserver;
import android.content.ComponentName;
import android.os.Binder;
import android.os.RemoteCallback;
+import android.os.RemoteException;
import android.os.ShellCommand;
-import android.service.ambientcontext.AmbientContextDetectionResult;
import java.io.PrintWriter;
+import java.util.List;
/**
* Shell command for {@link AmbientContextManagerService}.
@@ -39,6 +41,7 @@ final class AmbientContextShellCommand extends ShellCommand {
new AmbientContextEventRequest.Builder()
.addEventType(AmbientContextEvent.EVENT_COUGH)
.addEventType(AmbientContextEvent.EVENT_SNORE)
+ .addEventType(AmbientContextEvent.EVENT_BACK_DOUBLE_TAP)
.build();
@NonNull
@@ -50,11 +53,11 @@ final class AmbientContextShellCommand extends ShellCommand {
/** Callbacks for AmbientContextEventService results used internally for testing. */
static class TestableCallbackInternal {
- private AmbientContextDetectionResult mLastResult;
+ private List<AmbientContextEvent> mLastEvents;
private int mLastStatus;
- public AmbientContextDetectionResult getLastResult() {
- return mLastResult;
+ public List<AmbientContextEvent> getLastEvents() {
+ return mLastEvents;
}
public int getLastStatus() {
@@ -62,19 +65,19 @@ final class AmbientContextShellCommand extends ShellCommand {
}
@NonNull
- private RemoteCallback createRemoteDetectionResultCallback() {
- return new RemoteCallback(result -> {
- AmbientContextDetectionResult detectionResult =
- (AmbientContextDetectionResult) result.get(
- AmbientContextDetectionResult.RESULT_RESPONSE_BUNDLE_KEY);
- final long token = Binder.clearCallingIdentity();
- try {
- mLastResult = detectionResult;
- out.println("Detection result available: " + detectionResult);
- } finally {
- Binder.restoreCallingIdentity(token);
+ private IAmbientContextObserver createAmbientContextObserver() {
+ return new IAmbientContextObserver.Stub() {
+ @Override
+ public void onEvents(List<AmbientContextEvent> events) throws RemoteException {
+ mLastEvents = events;
+ out.println("Detection events available: " + events);
}
- });
+
+ @Override
+ public void onRegistrationComplete(int statusCode) throws RemoteException {
+ mLastStatus = statusCode;
+ }
+ };
}
@NonNull
@@ -123,8 +126,7 @@ final class AmbientContextShellCommand extends ShellCommand {
final String packageName = getNextArgRequired();
mService.startDetection(
userId, REQUEST, packageName,
- sTestableCallbackInternal.createRemoteDetectionResultCallback(),
- sTestableCallbackInternal.createRemoteStatusCallback());
+ sTestableCallbackInternal.createAmbientContextObserver());
return 0;
}
diff --git a/services/core/java/com/android/server/appop/DiscreteRegistry.java b/services/core/java/com/android/server/appop/DiscreteRegistry.java
index 158092f33ee3..dd0c4b86a77d 100644
--- a/services/core/java/com/android/server/appop/DiscreteRegistry.java
+++ b/services/core/java/com/android/server/appop/DiscreteRegistry.java
@@ -816,8 +816,7 @@ final class DiscreteRegistry {
}
} catch (Throwable t) {
- Slog.e(TAG, "Error while cleaning timeline files: " + t.getMessage() + " "
- + t.getStackTrace());
+ Slog.e(TAG, "Error while cleaning timeline files: ", t);
}
}
}
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 66a4527bc2cb..4adbfaa79c69 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -53,8 +53,6 @@ public class BtHelper {
private static final String TAG = "AS.BtHelper";
- private static final int SOURCE_CODEC_TYPE_OPUS = 6; // TODO remove in U
-
private final @NonNull AudioDeviceBroker mDeviceBroker;
BtHelper(@NonNull AudioDeviceBroker broker) {
@@ -913,7 +911,7 @@ public class BtHelper {
return "ENCODING_APTX_HD";
case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC:
return "ENCODING_LDAC";
- case SOURCE_CODEC_TYPE_OPUS: // TODO update in U
+ case BluetoothCodecConfig.SOURCE_CODEC_TYPE_OPUS:
return "ENCODING_OPUS";
default:
return "ENCODING_BT_CODEC_TYPE(" + btCodecType + ")";
diff --git a/services/core/java/com/android/server/backup/BackupUtils.java b/services/core/java/com/android/server/backup/BackupUtils.java
index 96c562100a7a..76eba1699298 100644
--- a/services/core/java/com/android/server/backup/BackupUtils.java
+++ b/services/core/java/com/android/server/backup/BackupUtils.java
@@ -30,6 +30,7 @@ import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.stream.Collectors;
public class BackupUtils {
private static final String TAG = "BackupUtils";
@@ -64,8 +65,9 @@ public class BackupUtils {
}
if (DEBUG) {
- Slog.v(TAG, "signaturesMatch(): stored=" + storedSigHashes
- + " device=" + signingInfo.getApkContentsSigners());
+ Slog.v(TAG, "signaturesMatch(): stored="
+ + storedSigHashes.stream().map(Arrays::toString).collect(Collectors.toList())
+ + " device=" + Arrays.toString(signingInfo.getApkContentsSigners()));
}
final int nStored = storedSigHashes.size();
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricContext.java b/services/core/java/com/android/server/biometrics/log/BiometricContext.java
index c86a8cb2c39d..8265203ddacd 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricContext.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricContext.java
@@ -46,6 +46,9 @@ public interface BiometricContext {
/** If the display is in AOD. */
boolean isAod();
+ /** If the device is awake or is becoming awake. */
+ boolean isAwake();
+
/**
* Subscribe to context changes.
*
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
index 9d2fde72ea2e..3d1a6343cbf2 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
@@ -43,7 +43,7 @@ import java.util.function.Consumer;
/**
* A default provider for {@link BiometricContext}.
*/
-class BiometricContextProvider implements BiometricContext {
+final class BiometricContextProvider implements BiometricContext {
private static final String TAG = "BiometricContextProvider";
@@ -76,7 +76,8 @@ class BiometricContextProvider implements BiometricContext {
private final Map<Integer, InstanceId> mSession = new ConcurrentHashMap<>();
private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
- private boolean mIsDozing = false;
+ private boolean mIsAod = false;
+ private boolean mIsAwake = false;
@VisibleForTesting
BiometricContextProvider(@NonNull AmbientDisplayConfiguration ambientDisplayConfiguration,
@@ -85,9 +86,14 @@ class BiometricContextProvider implements BiometricContext {
try {
service.setBiometicContextListener(new IBiometricContextListener.Stub() {
@Override
- public void onDozeChanged(boolean isDozing) {
- mIsDozing = isDozing;
- notifyChanged();
+ public void onDozeChanged(boolean isDozing, boolean isAwake) {
+ isDozing = isDozing && isAodEnabled();
+ final boolean changed = (mIsAod != isDozing) || (mIsAwake != isAwake);
+ if (changed) {
+ mIsAod = isDozing;
+ mIsAwake = isAwake;
+ notifyChanged();
+ }
}
private void notifyChanged() {
@@ -97,6 +103,10 @@ class BiometricContextProvider implements BiometricContext {
notifySubscribers();
}
}
+
+ private boolean isAodEnabled() {
+ return mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
+ }
});
service.registerSessionListener(SESSION_TYPES, new ISessionListener.Stub() {
@Override
@@ -161,7 +171,12 @@ class BiometricContextProvider implements BiometricContext {
@Override
public boolean isAod() {
- return mIsDozing && mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
+ return mIsAod;
+ }
+
+ @Override
+ public boolean isAwake() {
+ return mIsAwake;
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index f2c5b970d52c..f7d94c9c2b9f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -315,21 +315,27 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
private ICancellationSignal doAuthenticate() throws RemoteException {
final AidlSession session = getFreshDaemon();
+ final OperationContext opContext = getOperationContext();
+ getBiometricContext().subscribe(opContext, ctx -> {
+ if (session.hasContextMethods()) {
+ try {
+ session.getSession().onContextChanged(ctx);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to notify context changed", e);
+ }
+ }
+
+ // TODO(b/243836005): this should come via ctx
+ final boolean isAwake = getBiometricContext().isAwake();
+ if (isAwake) {
+ mALSProbeCallback.getProbe().enable();
+ } else {
+ mALSProbeCallback.getProbe().disable();
+ }
+ });
+
if (session.hasContextMethods()) {
- final OperationContext opContext = getOperationContext();
- final ICancellationSignal cancel =
- session.getSession().authenticateWithContext(mOperationId, opContext);
- getBiometricContext()
- .subscribe(
- opContext,
- ctx -> {
- try {
- session.getSession().onContextChanged(ctx);
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to notify context changed", e);
- }
- });
- return cancel;
+ return session.getSession().authenticateWithContext(mOperationId, opContext);
} else {
return session.getSession().authenticate(mOperationId);
}
@@ -360,7 +366,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
try {
mIsPointerDown = true;
mState = STATE_STARTED;
- mALSProbeCallback.getProbe().enable();
final AidlSession session = getFreshDaemon();
if (session.hasContextMethods()) {
@@ -389,7 +394,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
try {
mIsPointerDown = false;
mState = STATE_STARTED_PAUSED_ATTEMPTED;
- mALSProbeCallback.getProbe().disable();
final AidlSession session = getFreshDaemon();
if (session.hasContextMethods()) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index 7d2cf9deb76f..e0393b54d2c5 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -94,7 +94,7 @@ class FingerprintEnrollClient extends EnrollClient<AidlSession> implements Udfps
mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
mMaxTemplatesPerUser = maxTemplatesPerUser;
- mALSProbeCallback = getLogger().getAmbientLightProbe(false /* startWithClient */);
+ mALSProbeCallback = getLogger().getAmbientLightProbe(true /* startWithClient */);
mEnrollReason = enrollReason;
if (enrollReason == FingerprintManager.ENROLL_FIND_SENSOR) {
@@ -216,7 +216,6 @@ class FingerprintEnrollClient extends EnrollClient<AidlSession> implements Udfps
public void onPointerDown(int x, int y, float minor, float major) {
try {
mIsPointerDown = true;
- mALSProbeCallback.getProbe().enable();
final AidlSession session = getFreshDaemon();
if (session.hasContextMethods()) {
@@ -240,7 +239,6 @@ class FingerprintEnrollClient extends EnrollClient<AidlSession> implements Udfps
public void onPointerUp() {
try {
mIsPointerDown = false;
- mALSProbeCallback.getProbe().disable();
final AidlSession session = getFreshDaemon();
if (session.hasContextMethods()) {
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 25d0752844fd..c835d2fe1bbd 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -116,8 +116,10 @@ public abstract class BrightnessMappingStrategy {
luxLevels = getLuxLevels(resources.getIntArray(
com.android.internal.R.array.config_autoBrightnessLevelsIdle));
} else {
- brightnessLevelsNits = displayDeviceConfig.getAutoBrightnessBrighteningLevelsNits();
- luxLevels = displayDeviceConfig.getAutoBrightnessBrighteningLevelsLux();
+ brightnessLevelsNits = getFloatArray(resources.obtainTypedArray(
+ com.android.internal.R.array.config_autoBrightnessDisplayValuesNits));
+ luxLevels = getLuxLevels(resources.getIntArray(
+ com.android.internal.R.array.config_autoBrightnessLevels));
}
// Display independent, mode independent values
diff --git a/services/core/java/com/android/server/display/DisplayControl.java b/services/core/java/com/android/server/display/DisplayControl.java
new file mode 100644
index 000000000000..e9640cf6b4d5
--- /dev/null
+++ b/services/core/java/com/android/server/display/DisplayControl.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+import android.os.IBinder;
+
+import java.util.Objects;
+
+/**
+ * Calls into SurfaceFlinger for Display creation and deletion.
+ */
+public class DisplayControl {
+ private static native IBinder nativeCreateDisplay(String name, boolean secure);
+ private static native void nativeDestroyDisplay(IBinder displayToken);
+
+ /**
+ * Create a display in SurfaceFlinger.
+ *
+ * @param name The name of the display
+ * @param secure Whether this display is secure.
+ * @return The token reference for the display in SurfaceFlinger.
+ */
+ public static IBinder createDisplay(String name, boolean secure) {
+ Objects.requireNonNull(name, "name must not be null");
+ return nativeCreateDisplay(name, secure);
+ }
+
+ /**
+ * Destroy a display in SurfaceFlinger.
+ *
+ * @param displayToken The display token for the display to be destroyed.
+ */
+ public static void destroyDisplay(IBinder displayToken) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+
+ nativeDestroyDisplay(displayToken);
+ }
+
+}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 3b627ef6a786..4f3fd6409cd8 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation;
import android.os.Environment;
@@ -150,22 +149,12 @@ import javax.xml.datatype.DatatypeConfigurationException;
* </quirks>
*
* <autoBrightness>
- * <brighteningLightDebounceMillis>
+ * <brighteningLightDebounceMillis>
* 2000
- * </brighteningLightDebounceMillis>
+ * </brighteningLightDebounceMillis>
* <darkeningLightDebounceMillis>
* 1000
* </darkeningLightDebounceMillis>
- * <displayBrightnessMapping>
- * <displayBrightnessPoint>
- * <lux>50</lux>
- * <nits>45</nits>
- * </displayBrightnessPoint>
- * <displayBrightnessPoint>
- * <lux>80</lux>
- * <nits>75</nits>
- * </displayBrightnessPoint>
- * </displayBrightnessMapping>
* </autoBrightness>
*
* <screenBrightnessRampFastDecrease>0.01</screenBrightnessRampFastDecrease>
@@ -279,39 +268,6 @@ public class DisplayDeviceConfig {
// for the corresponding values above
private float[] mBrightness;
-
- /**
- * Array of desired screen brightness in nits corresponding to the lux values
- * in the mBrightnessLevelsLux array. The display brightness is defined as the
- * measured brightness of an all-white image. The brightness values must be non-negative and
- * non-decreasing. This must be overridden in platform specific overlays
- */
- private float[] mBrightnessLevelsNits;
-
- /**
- * Array of light sensor lux values to define our levels for auto backlight
- * brightness support.
- * The N entries of this array define N + 1 control points as follows:
- * (1-based arrays)
- *
- * Point 1: (0, value[1]): lux <= 0
- * Point 2: (level[1], value[2]): 0 < lux <= level[1]
- * Point 3: (level[2], value[3]): level[2] < lux <= level[3]
- * ...
- * Point N+1: (level[N], value[N+1]): level[N] < lux
- *
- * The control points must be strictly increasing. Each control point
- * corresponds to an entry in the brightness backlight values arrays.
- * For example, if lux == level[1] (first element of the levels array)
- * then the brightness will be determined by value[2] (second element
- * of the brightness values array).
- *
- * Spline interpolation is used to determine the auto-brightness
- * backlight values for lux levels between these control points.
- *
- */
- private float[] mBrightnessLevelsLux;
-
private float mBacklightMinimum = Float.NaN;
private float mBacklightMaximum = Float.NaN;
private float mBrightnessDefault = Float.NaN;
@@ -705,20 +661,6 @@ public class DisplayDeviceConfig {
return mAutoBrightnessBrighteningLightDebounce;
}
- /**
- * @return Auto brightness brightening ambient lux levels
- */
- public float[] getAutoBrightnessBrighteningLevelsLux() {
- return mBrightnessLevelsLux;
- }
-
- /**
- * @return Auto brightness brightening nits levels
- */
- public float[] getAutoBrightnessBrighteningLevelsNits() {
- return mBrightnessLevelsNits;
- }
-
@Override
public String toString() {
return "DisplayDeviceConfig{"
@@ -761,8 +703,6 @@ public class DisplayDeviceConfig {
+ mAutoBrightnessBrighteningLightDebounce
+ ", mAutoBrightnessDarkeningLightDebounce= "
+ mAutoBrightnessDarkeningLightDebounce
- + ", mBrightnessLevelsLux= " + Arrays.toString(mBrightnessLevelsLux)
- + ", mBrightnessLevelsNits= " + Arrays.toString(mBrightnessLevelsNits)
+ "}";
}
@@ -839,7 +779,6 @@ public class DisplayDeviceConfig {
loadBrightnessRampsFromConfigXml();
loadAmbientLightSensorFromConfigXml();
setProxSensorUnspecified();
- loadAutoBrightnessConfigsFromConfigXml();
mLoadedFrom = "<config.xml>";
}
@@ -1052,7 +991,6 @@ public class DisplayDeviceConfig {
private void loadAutoBrightnessConfigValues(DisplayConfiguration config) {
loadAutoBrightnessBrighteningLightDebounce(config.getAutoBrightness());
loadAutoBrightnessDarkeningLightDebounce(config.getAutoBrightness());
- loadAutoBrightnessDisplayBrightnessMapping(config.getAutoBrightness());
}
/**
@@ -1085,33 +1023,6 @@ public class DisplayDeviceConfig {
}
}
- /**
- * Loads the auto-brightness display brightness mappings. Internally, this takes care of
- * loading the value from the display config, and if not present, falls back to config.xml.
- */
- private void loadAutoBrightnessDisplayBrightnessMapping(AutoBrightness autoBrightnessConfig) {
- if (autoBrightnessConfig == null
- || autoBrightnessConfig.getDisplayBrightnessMapping() == null) {
- mBrightnessLevelsNits = getFloatArray(mContext.getResources()
- .obtainTypedArray(com.android.internal.R.array
- .config_autoBrightnessDisplayValuesNits));
- mBrightnessLevelsLux = getFloatArray(mContext.getResources()
- .obtainTypedArray(com.android.internal.R.array
- .config_autoBrightnessLevels));
- } else {
- final int size = autoBrightnessConfig.getDisplayBrightnessMapping()
- .getDisplayBrightnessPoint().size();
- mBrightnessLevelsNits = new float[size];
- mBrightnessLevelsLux = new float[size];
- for (int i = 0; i < size; i++) {
- mBrightnessLevelsNits[i] = autoBrightnessConfig.getDisplayBrightnessMapping()
- .getDisplayBrightnessPoint().get(i).getNits().floatValue();
- mBrightnessLevelsLux[i] = autoBrightnessConfig.getDisplayBrightnessMapping()
- .getDisplayBrightnessPoint().get(i).getLux().floatValue();
- }
- }
- }
-
private void loadBrightnessMapFromConfigXml() {
// Use the config.xml mapping
final Resources res = mContext.getResources();
@@ -1337,10 +1248,6 @@ public class DisplayDeviceConfig {
com.android.internal.R.string.config_displayLightSensorType);
}
- private void loadAutoBrightnessConfigsFromConfigXml() {
- loadAutoBrightnessDisplayBrightnessMapping(null /*AutoBrightnessConfig*/);
- }
-
private void loadAmbientLightSensorFromDdc(DisplayConfiguration config) {
final SensorDetails sensorDetails = config.getLightSensor();
if (sensorDetails != null) {
@@ -1483,22 +1390,6 @@ public class DisplayDeviceConfig {
}
}
- /**
- * Extracts a float array from the specified {@link TypedArray}.
- *
- * @param array The array to convert.
- * @return the given array as a float array.
- */
- public static float[] getFloatArray(TypedArray array) {
- final int n = array.length();
- float[] vals = new float[n];
- for (int i = 0; i < n; i++) {
- vals[i] = array.getFloat(i, PowerManager.BRIGHTNESS_OFF_FLOAT);
- }
- array.recycle();
- return vals;
- }
-
static class SensorData {
public String type;
public String name;
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 330379cf58eb..b0de844389b6 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -305,7 +305,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
mSurface.release();
mSurface = null;
}
- SurfaceControl.destroyDisplay(getDisplayTokenLocked());
+ DisplayControl.destroyDisplay(getDisplayTokenLocked());
}
@Override
@@ -460,7 +460,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate,
long presentationDeadlineNanos, int state) {
synchronized (getSyncRoot()) {
- IBinder displayToken = SurfaceControl.createDisplay(mName, mFlags.mSecure);
+ IBinder displayToken = DisplayControl.createDisplay(mName, mFlags.mSecure);
mDevice = new OverlayDisplayDevice(displayToken, mName, mModes, mActiveMode,
DEFAULT_MODE_INDEX, refreshRate, presentationDeadlineNanos,
mFlags, state, surfaceTexture, mNumber) {
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 479629eae7ac..38728ce106af 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -82,8 +82,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
// Called with SyncRoot lock held.
public VirtualDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
Context context, Handler handler, Listener listener) {
- this(syncRoot, context, handler, listener,
- (String name, boolean secure) -> SurfaceControl.createDisplay(name, secure));
+ this(syncRoot, context, handler, listener, DisplayControl::createDisplay);
}
@VisibleForTesting
@@ -296,7 +295,7 @@ public class VirtualDisplayAdapter extends DisplayAdapter {
mSurface.release();
mSurface = null;
}
- SurfaceControl.destroyDisplay(getDisplayTokenLocked());
+ DisplayControl.destroyDisplay(getDisplayTokenLocked());
if (mProjection != null && mMediaProjectionCallback != null) {
try {
mProjection.unregisterCallback(mMediaProjectionCallback);
diff --git a/services/core/java/com/android/server/display/WifiDisplayAdapter.java b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
index d632ee3d021c..146b003650ac 100644
--- a/services/core/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/WifiDisplayAdapter.java
@@ -388,7 +388,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
String name = display.getFriendlyDisplayName();
String address = display.getDeviceAddress();
- IBinder displayToken = SurfaceControl.createDisplay(name, secure);
+ IBinder displayToken = DisplayControl.createDisplay(name, secure);
mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height,
refreshRate, deviceFlags, address, surface);
sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED);
@@ -621,7 +621,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
mSurface.release();
mSurface = null;
}
- SurfaceControl.destroyDisplay(getDisplayTokenLocked());
+ DisplayControl.destroyDisplay(getDisplayTokenLocked());
}
public void setNameLocked(String name) {
diff --git a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
index 6f890cda5964..dc1f4ddb19b9 100644
--- a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
+++ b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
@@ -561,7 +561,7 @@ class GnssNetworkConnectivityHandler {
mAGpsDataConnectionIpAddr = InetAddress.getByAddress(suplIpAddr);
if (DEBUG) Log.d(TAG, "IP address converted to: " + mAGpsDataConnectionIpAddr);
} catch (UnknownHostException e) {
- Log.e(TAG, "Bad IP Address: " + suplIpAddr, e);
+ Log.e(TAG, "Bad IP Address: " + Arrays.toString(suplIpAddr), e);
}
}
diff --git a/services/core/java/com/android/server/logcat/LogcatManagerService.java b/services/core/java/com/android/server/logcat/LogcatManagerService.java
index 04cacee32283..cbbb3362a387 100644
--- a/services/core/java/com/android/server/logcat/LogcatManagerService.java
+++ b/services/core/java/com/android/server/logcat/LogcatManagerService.java
@@ -16,6 +16,8 @@
package com.android.server.logcat;
+import static android.os.Process.getParentPid;
+
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -45,6 +47,7 @@ import com.android.server.SystemService;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -340,13 +343,6 @@ public final class LogcatManagerService extends SystemService {
* access
*/
private String getPackageName(LogAccessRequest request) {
- if (mActivityManagerInternal != null) {
- String packageName = mActivityManagerInternal.getPackageNameByPid(request.mPid);
- if (packageName != null) {
- return packageName;
- }
- }
-
PackageManager pm = mContext.getPackageManager();
if (pm == null) {
// Decline the logd access if PackageManager is null
@@ -355,15 +351,28 @@ public final class LogcatManagerService extends SystemService {
}
String[] packageNames = pm.getPackagesForUid(request.mUid);
-
if (ArrayUtils.isEmpty(packageNames)) {
// Decline the logd access if the app name is unknown
Slog.e(TAG, "Unknown calling package name, declining the logd access");
return null;
}
- String firstPackageName = packageNames[0];
+ if (mActivityManagerInternal != null) {
+ int pid = request.mPid;
+ String packageName = mActivityManagerInternal.getPackageNameByPid(pid);
+ while ((packageName == null || !ArrayUtils.contains(packageNames, packageName))
+ && pid != -1) {
+ pid = getParentPid(pid);
+ packageName = mActivityManagerInternal.getPackageNameByPid(pid);
+ }
+ if (packageName != null && ArrayUtils.contains(packageNames, packageName)) {
+ return packageName;
+ }
+ }
+
+ Arrays.sort(packageNames);
+ String firstPackageName = packageNames[0];
if (firstPackageName == null || firstPackageName.isEmpty()) {
// Decline the logd access if the package name from uid is unknown
Slog.e(TAG, "Unknown calling package name, declining the logd access");
diff --git a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
index c12dc8e9e92e..9a190316f4eb 100644
--- a/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
+++ b/services/core/java/com/android/server/media/MediaButtonReceiverHolder.java
@@ -32,7 +32,6 @@ import android.os.Handler;
import android.os.PowerWhitelistManager;
import android.os.UserHandle;
import android.text.TextUtils;
-import android.util.EventLog;
import android.util.Log;
import android.view.KeyEvent;
@@ -118,12 +117,6 @@ final class MediaButtonReceiverHolder {
int componentType = getComponentType(pendingIntent);
ComponentName componentName = getComponentName(pendingIntent, componentType);
if (componentName != null) {
- if (!TextUtils.equals(componentName.getPackageName(), sessionPackageName)) {
- EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet Logging.
- throw new IllegalArgumentException("ComponentName does not belong to "
- + "sessionPackageName. sessionPackageName = " + sessionPackageName
- + ", ComponentName pkg = " + componentName.getPackageName());
- }
return new MediaButtonReceiverHolder(userId, pendingIntent, componentName,
componentType);
}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 4f8771a3ddef..34cd6a012925 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -50,8 +50,6 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.SystemClock;
-import android.text.TextUtils;
-import android.util.EventLog;
import android.util.Log;
import android.view.KeyEvent;
@@ -914,7 +912,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
}
@Override
- public void setMediaButtonReceiver(PendingIntent pi) throws RemoteException {
+ public void setMediaButtonReceiver(PendingIntent pi, String sessionPackageName)
+ throws RemoteException {
final long token = Binder.clearCallingIdentity();
try {
if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER)
@@ -922,7 +921,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
return;
}
mMediaButtonReceiverHolder =
- MediaButtonReceiverHolder.create(mContext, mUserId, pi, mPackageName);
+ MediaButtonReceiverHolder.create(mContext, mUserId, pi, sessionPackageName);
mService.onMediaButtonReceiverChanged(MediaSessionRecord.this);
} finally {
Binder.restoreCallingIdentity(token);
@@ -933,15 +932,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient, MediaSessionR
public void setMediaButtonBroadcastReceiver(ComponentName receiver) throws RemoteException {
final long token = Binder.clearCallingIdentity();
try {
- //mPackageName has been verified in MediaSessionService.enforcePackageName().
- if (receiver != null && !TextUtils.equals(
- mPackageName, receiver.getPackageName())) {
- EventLog.writeEvent(0x534e4554, "238177121", -1, ""); // SafetyNet Logging.
- throw new IllegalArgumentException("receiver does not belong to "
- + "package name provided to MediaSessionRecord. Pkg = " + mPackageName
- + ", Receiver Pkg = " + receiver.getPackageName());
- }
-
if ((mPolicies & MediaSessionPolicyProvider.SESSION_POLICY_IGNORE_BUTTON_RECEIVER)
!= 0) {
return;
diff --git a/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java b/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
index 5599b0c07377..8ce7b57c55e0 100644
--- a/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
+++ b/services/core/java/com/android/server/net/watchlist/WatchlistLoggingHandler.java
@@ -36,7 +36,6 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.util.Slog;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.HexDump;
@@ -45,8 +44,8 @@ import java.io.File;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.GregorianCalendar;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
@@ -155,7 +154,7 @@ class WatchlistLoggingHandler extends Handler {
try {
final String[] packageNames = mPm.getPackagesForUid(uid);
if (packageNames == null || packageNames.length == 0) {
- Slog.e(TAG, "Couldn't find package: " + packageNames);
+ Slog.e(TAG, "Couldn't find package: " + Arrays.toString(packageNames));
return false;
}
ai = mPm.getApplicationInfo(packageNames[0], 0);
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 6cfe093df6d0..4b6543b54f2f 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -74,7 +74,6 @@ import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.dex.ArtManagerService;
import com.android.server.pm.dex.ArtStatsLogUtils;
import com.android.server.pm.dex.ArtStatsLogUtils.ArtStatsLogger;
-import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.DexoptOptions;
import com.android.server.pm.dex.DexoptUtils;
import com.android.server.pm.dex.PackageDexUsage;
@@ -787,10 +786,7 @@ public class PackageDexOptimizer {
*/
private String getRealCompilerFilter(ApplicationInfo info, String targetCompilerFilter,
boolean isUsedByOtherApps) {
- // When an app or priv app is configured to run out of box, only verify it.
- if (info.isEmbeddedDexUsed()
- || (info.isPrivilegedApp()
- && DexManager.isPackageSelectedToRunOob(info.packageName))) {
+ if (info.isEmbeddedDexUsed()) {
return "verify";
}
@@ -827,10 +823,7 @@ public class PackageDexOptimizer {
* handling the case where the package code is used by other apps.
*/
private String getRealCompilerFilter(AndroidPackage pkg, String targetCompilerFilter) {
- // When an app or priv app is configured to run out of box, only verify it.
- if (pkg.isUseEmbeddedDex()
- || (pkg.isPrivileged()
- && DexManager.isPackageSelectedToRunOob(pkg.getPackageName()))) {
+ if (pkg.isUseEmbeddedDex()) {
return "verify";
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
index e969d93465f8..330e3313883c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
+++ b/services/core/java/com/android/server/pm/PackageManagerInternalBase.java
@@ -727,6 +727,12 @@ abstract class PackageManagerInternalBase extends PackageManagerInternal {
return snapshot().checkUidSignaturesForAllUsers(uid1, uid2);
}
+ @Override
+ public void setPackageStoppedState(@NonNull String packageName, boolean stopped,
+ int userId) {
+ mService.setPackageStoppedState(snapshot(), packageName, stopped, userId);
+ }
+
@NonNull
@Override
@Deprecated
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index 297439f33a8b..8f89fdd40b32 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -321,4 +321,15 @@ public abstract class UserManagerInternal {
* {@link UserManager#isUserVisible()} in the given display.
*/
public abstract boolean isUserVisible(@UserIdInt int userId, int displayId);
+
+ /**
+ * Returns the display id assigned to the user, or {@code Display.INVALID_DISPLAY} if the
+ * user is not assigned to any display.
+ *
+ * <p>The current foreground user is associated with the main display, while other users would
+ * only assigned to a display if they were started with
+ * {@code ActivityManager.startUserInBackgroundOnSecondaryDisplay()}. If the user is a profile
+ * and is running, it's assigned to its parent display.
+ */
+ public abstract int getDisplayAssignedToUser(@UserIdInt int userId);
}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index d8b7fdab70f7..3b898f876072 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1731,6 +1731,18 @@ public class UserManagerService extends IUserManager.Stub {
return false;
}
+ // TODO(b/239982558): add unit test
+ private int getDisplayAssignedToUser(@UserIdInt int userId) {
+ if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) {
+ return Display.DEFAULT_DISPLAY;
+ }
+ synchronized (mUsersLock) {
+ return mUsersOnSecondaryDisplays == null
+ ? Display.INVALID_DISPLAY
+ : mUsersOnSecondaryDisplays.get(userId, Display.INVALID_DISPLAY);
+ }
+ }
+
private boolean isCurrentUserOrRunningProfileOfCurrentUser(@UserIdInt int userId) {
int currentUserId = Binder.withCleanCallingIdentity(() -> ActivityManager.getCurrentUser());
@@ -6695,6 +6707,11 @@ public class UserManagerService extends IUserManager.Stub {
public boolean isUserVisible(int userId, int displayId) {
return isUserVisibleOnDisplay(userId, displayId);
}
+
+ @Override
+ public int getDisplayAssignedToUser(int userId) {
+ return UserManagerService.this.getDisplayAssignedToUser(userId);
+ }
} // class LocalService
/**
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 17109e97ddf1..8c2da45da994 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -36,7 +36,6 @@ import android.os.FileUtils;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.storage.StorageManager;
import android.util.Log;
@@ -58,8 +57,6 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -81,10 +78,6 @@ public class DexManager {
private static final String TAG = "DexManager";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final String PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB = "pm.dexopt.priv-apps-oob";
- private static final String PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB_LIST =
- "pm.dexopt.priv-apps-oob-list";
-
// System server cannot load executable code outside system partitions.
// However it can load verification data - thus we pick the "verify" compiler filter.
private static final String SYSTEM_SERVER_COMPILER_FILTER = "verify";
@@ -910,45 +903,6 @@ public class DexManager {
}
/**
- * Returns whether the given package is in the list of privilaged apps that should run out of
- * box. This only makes sense if the feature is enabled. Note that when the the OOB list is
- * empty, all priv apps will run in OOB mode.
- */
- public static boolean isPackageSelectedToRunOob(String packageName) {
- return isPackageSelectedToRunOob(Arrays.asList(packageName));
- }
-
- /**
- * Returns whether any of the given packages are in the list of privilaged apps that should run
- * out of box. This only makes sense if the feature is enabled. Note that when the the OOB list
- * is empty, all priv apps will run in OOB mode.
- */
- public static boolean isPackageSelectedToRunOob(Collection<String> packageNamesInSameProcess) {
- return isPackageSelectedToRunOobInternal(
- SystemProperties.getBoolean(PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB, false),
- SystemProperties.get(PROPERTY_NAME_PM_DEXOPT_PRIV_APPS_OOB_LIST, "ALL"),
- packageNamesInSameProcess);
- }
-
- @VisibleForTesting
- /* package */ static boolean isPackageSelectedToRunOobInternal(boolean isEnabled,
- String whitelist, Collection<String> packageNamesInSameProcess) {
- if (!isEnabled) {
- return false;
- }
-
- if ("ALL".equals(whitelist)) {
- return true;
- }
- for (String oobPkgName : whitelist.split(",")) {
- if (packageNamesInSameProcess.contains(oobPkgName)) {
- return true;
- }
- }
- return false;
- }
-
- /**
* Generates log if the archive located at {@code fileName} has uncompressed dex file that can
* be direclty mapped.
*/
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 1a1de0341aa0..1bb476f6e4a1 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -185,6 +185,7 @@ import android.view.autofill.AutofillManagerInternal;
import com.android.internal.R;
import com.android.internal.accessibility.AccessibilityShortcutController;
import com.android.internal.accessibility.util.AccessibilityUtils;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.AssistUtils;
import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.internal.logging.MetricsLogger;
@@ -224,6 +225,7 @@ import java.io.PrintWriter;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.function.Supplier;
/**
* WindowManagerPolicy implementation for the Android phone UI. This
@@ -437,6 +439,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
};
+ private Supplier<GlobalActions> mGlobalActionsFactory;
private GlobalActions mGlobalActions;
private Handler mHandler;
@@ -914,7 +917,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
} else {
// handled by another power key policy.
- if (!mSingleKeyGestureDetector.isKeyIntercepted(KEYCODE_POWER)) {
+ if (mSingleKeyGestureDetector.isKeyIntercepted(KEYCODE_POWER)) {
+ Slog.d(TAG, "Skip power key gesture for other policy has handled it.");
mSingleKeyGestureDetector.reset();
}
}
@@ -928,11 +932,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Abort possibly stuck animations only when power key up without long press case.
mHandler.post(mWindowManagerFuncs::triggerAnimationFailsafe);
}
- } else {
- // handled by single key or another power key policy.
- if (!mSingleKeyGestureDetector.isKeyIntercepted(KEYCODE_POWER)) {
- mSingleKeyGestureDetector.reset();
- }
}
finishPowerKeyPress();
@@ -1544,7 +1543,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
void showGlobalActionsInternal() {
if (mGlobalActions == null) {
- mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
+ mGlobalActions = mGlobalActionsFactory.get();
}
final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
@@ -1868,11 +1867,45 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mDefaultDisplayPolicy = mDefaultDisplayRotation.getDisplayPolicy();
}
+ /** Point of injection for test dependencies. */
+ @VisibleForTesting
+ static class Injector {
+ private final Context mContext;
+ private final WindowManagerFuncs mWindowManagerFuncs;
+
+ Injector(Context context, WindowManagerFuncs funcs) {
+ mContext = context;
+ mWindowManagerFuncs = funcs;
+ }
+
+ Context getContext() {
+ return mContext;
+ }
+
+ WindowManagerFuncs getWindowManagerFuncs() {
+ return mWindowManagerFuncs;
+ }
+
+ AccessibilityShortcutController getAccessibilityShortcutController(
+ Context context, Handler handler, int initialUserId) {
+ return new AccessibilityShortcutController(context, handler, initialUserId);
+ }
+
+ Supplier<GlobalActions> getGlobalActionsFactory() {
+ return () -> new GlobalActions(mContext, mWindowManagerFuncs);
+ }
+ }
+
/** {@inheritDoc} */
@Override
- public void init(Context context, WindowManagerFuncs windowManagerFuncs) {
- mContext = context;
- mWindowManagerFuncs = windowManagerFuncs;
+ public void init(Context context, WindowManagerFuncs funcs) {
+ init(new Injector(context, funcs));
+ }
+
+ @VisibleForTesting
+ void init(Injector injector) {
+ mContext = injector.getContext();
+ mWindowManagerFuncs = injector.getWindowManagerFuncs();
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
mActivityTaskManagerInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
@@ -1887,8 +1920,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mHasFeatureLeanback = mPackageManager.hasSystemFeature(FEATURE_LEANBACK);
mHasFeatureAuto = mPackageManager.hasSystemFeature(FEATURE_AUTOMOTIVE);
mHasFeatureHdmiCec = mPackageManager.hasSystemFeature(FEATURE_HDMI_CEC);
- mAccessibilityShortcutController =
- new AccessibilityShortcutController(mContext, new Handler(), mCurrentUserId);
+ mAccessibilityShortcutController = injector.getAccessibilityShortcutController(
+ mContext, new Handler(), mCurrentUserId);
+ mGlobalActionsFactory = injector.getGlobalActionsFactory();
mLogger = new MetricsLogger();
mScreenOffSleepTokenAcquirer = mActivityTaskManagerInternal
@@ -1903,7 +1937,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
res.getBoolean(com.android.internal.R.bool.config_wakeOnBackKeyPress);
// Init display burn-in protection
- boolean burnInProtectionEnabled = context.getResources().getBoolean(
+ boolean burnInProtectionEnabled = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enableBurnInProtection);
// Allow a system property to override this. Used by developer settings.
boolean burnInProtectionDevMode =
@@ -1921,7 +1955,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
maxVertical = -4;
maxRadius = (isRoundWindow()) ? 6 : -1;
} else {
- Resources resources = context.getResources();
+ Resources resources = mContext.getResources();
minHorizontal = resources.getInteger(
com.android.internal.R.integer.config_burnInProtectionMinHorizontalOffset);
maxHorizontal = resources.getInteger(
@@ -1934,21 +1968,21 @@ public class PhoneWindowManager implements WindowManagerPolicy {
com.android.internal.R.integer.config_burnInProtectionMaxRadius);
}
mBurnInProtectionHelper = new BurnInProtectionHelper(
- context, minHorizontal, maxHorizontal, minVertical, maxVertical, maxRadius);
+ mContext, minHorizontal, maxHorizontal, minVertical, maxVertical, maxRadius);
}
mHandler = new PolicyHandler();
mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
mSettingsObserver = new SettingsObserver(mHandler);
mSettingsObserver.observe();
- mModifierShortcutManager = new ModifierShortcutManager(context);
- mUiMode = context.getResources().getInteger(
+ mModifierShortcutManager = new ModifierShortcutManager(mContext);
+ mUiMode = mContext.getResources().getInteger(
com.android.internal.R.integer.config_defaultUiModeType);
mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
mHomeIntent.addCategory(Intent.CATEGORY_HOME);
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- mEnableCarDockHomeCapture = context.getResources().getBoolean(
+ mEnableCarDockHomeCapture = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enableCarDockHomeLaunch);
mCarDockIntent = new Intent(Intent.ACTION_MAIN, null);
mCarDockIntent.addCategory(Intent.CATEGORY_CAR_DOCK);
@@ -1963,7 +1997,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mVrHeadsetHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+ mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"PhoneWindowManager.mBroadcastWakeLock");
mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
@@ -2035,9 +2069,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
readConfigurationDependentBehaviors();
- mDisplayFoldController = DisplayFoldController.create(context, DEFAULT_DISPLAY);
+ mDisplayFoldController = DisplayFoldController.create(mContext, DEFAULT_DISPLAY);
- mAccessibilityManager = (AccessibilityManager) context.getSystemService(
+ mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(
Context.ACCESSIBILITY_SERVICE);
// register for dock events
@@ -2047,7 +2081,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
filter.addAction(UiModeManager.ACTION_ENTER_DESK_MODE);
filter.addAction(UiModeManager.ACTION_EXIT_DESK_MODE);
filter.addAction(Intent.ACTION_DOCK_EVENT);
- Intent intent = context.registerReceiver(mDockReceiver, filter);
+ Intent intent = mContext.registerReceiver(mDockReceiver, filter);
if (intent != null) {
// Retrieve current sticky dock event broadcast.
mDefaultDisplayPolicy.setDockMode(intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
@@ -2058,13 +2092,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
filter = new IntentFilter();
filter.addAction(Intent.ACTION_DREAMING_STARTED);
filter.addAction(Intent.ACTION_DREAMING_STOPPED);
- context.registerReceiver(mDreamReceiver, filter);
+ mContext.registerReceiver(mDreamReceiver, filter);
// register for multiuser-relevant broadcasts
filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
- context.registerReceiver(mMultiuserReceiver, filter);
+ mContext.registerReceiver(mMultiuserReceiver, filter);
- mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
+ mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
com.android.internal.R.array.config_safeModeEnabledVibePattern);
diff --git a/services/core/java/com/android/server/power/LowPowerStandbyController.java b/services/core/java/com/android/server/power/LowPowerStandbyController.java
index 5964fa49f035..ebeb145526a4 100644
--- a/services/core/java/com/android/server/power/LowPowerStandbyController.java
+++ b/services/core/java/com/android/server/power/LowPowerStandbyController.java
@@ -201,6 +201,7 @@ public class LowPowerStandbyController {
mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
Settings.Global.LOW_POWER_STANDBY_ACTIVE_DURING_MAINTENANCE),
false, mSettingsObserver, UserHandle.USER_ALL);
+ initSettingsLocked();
updateSettingsLocked();
if (mIsEnabled) {
@@ -212,6 +213,23 @@ public class LowPowerStandbyController {
}
@GuardedBy("mLock")
+ private void initSettingsLocked() {
+ final ContentResolver resolver = mContext.getContentResolver();
+ if (mSupportedConfig) {
+ final int enabledSetting = Settings.Global.getInt(resolver,
+ Settings.Global.LOW_POWER_STANDBY_ENABLED, /* def= */ -1);
+
+ // If the ENABLED setting hasn't been assigned yet, set it to its default value.
+ // This ensures reading the setting reflects the enabled state, without having to know
+ // the default value for this device.
+ if (enabledSetting == -1) {
+ Settings.Global.putInt(resolver, Settings.Global.LOW_POWER_STANDBY_ENABLED,
+ /* value= */ mEnabledByDefaultConfig ? 1 : 0);
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
private void updateSettingsLocked() {
final ContentResolver resolver = mContext.getContentResolver();
mIsEnabled = mSupportedConfig && Settings.Global.getInt(resolver,
diff --git a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
index df902c2916ba..49ac559bf93f 100644
--- a/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/power/stats/BatteryExternalStatsWorker.java
@@ -663,6 +663,11 @@ public class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStat
BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS,
reason, 0);
+ if (measuredEnergyDeltas != null && !measuredEnergyDeltas.isEmpty()) {
+ mStats.recordMeasuredEnergyDetailsLocked(elapsedRealtime, uptime,
+ mMeasuredEnergySnapshot.getMeasuredEnergyDetails(measuredEnergyDeltas));
+ }
+
if ((updateFlags & UPDATE_CPU) != 0) {
if (useLatestStates) {
onBattery = mStats.isOnBatteryLocked();
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index 968f9161b3c1..5fdd006933ee 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -7404,6 +7404,16 @@ public class BatteryStatsImpl extends BatteryStats {
return names;
}
+ /**
+ * Adds measured energy delta to battery history.
+ */
+ @GuardedBy("this")
+ public void recordMeasuredEnergyDetailsLocked(long elapsedRealtimeMs,
+ long uptimeMs, MeasuredEnergyDetails measuredEnergyDetails) {
+ mHistory.recordMeasuredEnergyDetails(elapsedRealtimeMs, uptimeMs,
+ measuredEnergyDetails);
+ }
+
@GuardedBy("this")
@Override public long getStartClockTime() {
final long currentTimeMs = mClock.currentTimeMillis();
diff --git a/services/core/java/com/android/server/power/stats/MeasuredEnergySnapshot.java b/services/core/java/com/android/server/power/stats/MeasuredEnergySnapshot.java
index b55c79928e62..c8b4e3671eb3 100644
--- a/services/core/java/com/android/server/power/stats/MeasuredEnergySnapshot.java
+++ b/services/core/java/com/android/server/power/stats/MeasuredEnergySnapshot.java
@@ -23,19 +23,17 @@ import android.hardware.power.stats.EnergyConsumer;
import android.hardware.power.stats.EnergyConsumerAttribution;
import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
+import android.os.BatteryStats.MeasuredEnergyDetails;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.util.SparseLongArray;
-import com.android.internal.annotations.VisibleForTesting;
-
import java.io.PrintWriter;
/**
* Keeps snapshots of data from previously pulled EnergyConsumerResults.
*/
-@VisibleForTesting
public class MeasuredEnergySnapshot {
private static final String TAG = "MeasuredEnergySnapshot";
@@ -87,6 +85,8 @@ public class MeasuredEnergySnapshot {
*/
private final SparseArray<SparseLongArray> mAttributionSnapshots;
+ private MeasuredEnergyDetails mMeasuredEnergyDetails;
+
/**
* Constructor that initializes to the given id->EnergyConsumer map, indicating which consumers
* exist and what their details are.
@@ -128,6 +128,28 @@ public class MeasuredEnergySnapshot {
/** Map of {@link EnergyConsumerType#OTHER} ordinals to their {uid->chargeUC} maps. */
public @Nullable SparseLongArray[] otherUidChargesUC = null;
+
+ boolean isEmpty() {
+ return bluetoothChargeUC <= 0
+ && isEmpty(cpuClusterChargeUC)
+ && isEmpty(displayChargeUC)
+ && gnssChargeUC <= 0
+ && mobileRadioChargeUC <= 0
+ && wifiChargeUC <= 0
+ && isEmpty(otherTotalChargeUC);
+ }
+
+ private boolean isEmpty(long[] values) {
+ if (values == null) {
+ return true;
+ }
+ for (long value: values) {
+ if (value > 0) {
+ return false;
+ }
+ }
+ return true;
+ }
}
/**
@@ -394,4 +416,119 @@ public class MeasuredEnergySnapshot {
// since the last snapshot. Round off to the nearest whole long.
return (deltaEnergyUJ * MILLIVOLTS_PER_VOLT + (avgVoltageMV / 2)) / avgVoltageMV;
}
+
+ /**
+ * Converts the MeasuredEnergyDeltaData object to MeasuredEnergyDetails, which can
+ * be saved in battery history.
+ */
+ MeasuredEnergyDetails getMeasuredEnergyDetails(
+ MeasuredEnergySnapshot.MeasuredEnergyDeltaData delta) {
+ if (mMeasuredEnergyDetails == null) {
+ mMeasuredEnergyDetails = createMeasuredEnergyDetails();
+ }
+
+ final long[] chargeUC = mMeasuredEnergyDetails.chargeUC;
+ for (int i = 0; i < mMeasuredEnergyDetails.consumers.length; i++) {
+ MeasuredEnergyDetails.EnergyConsumer energyConsumer =
+ mMeasuredEnergyDetails.consumers[i];
+ switch (energyConsumer.type) {
+ case EnergyConsumerType.BLUETOOTH:
+ chargeUC[i] = delta.bluetoothChargeUC;
+ break;
+ case EnergyConsumerType.CPU_CLUSTER:
+ if (delta.cpuClusterChargeUC != null) {
+ chargeUC[i] = delta.cpuClusterChargeUC[energyConsumer.ordinal];
+ } else {
+ chargeUC[i] = UNAVAILABLE;
+ }
+ break;
+ case EnergyConsumerType.DISPLAY:
+ if (delta.displayChargeUC != null) {
+ chargeUC[i] = delta.displayChargeUC[energyConsumer.ordinal];
+ } else {
+ chargeUC[i] = UNAVAILABLE;
+ }
+ break;
+ case EnergyConsumerType.GNSS:
+ chargeUC[i] = delta.gnssChargeUC;
+ break;
+ case EnergyConsumerType.MOBILE_RADIO:
+ chargeUC[i] = delta.mobileRadioChargeUC;
+ break;
+ case EnergyConsumerType.WIFI:
+ chargeUC[i] = delta.wifiChargeUC;
+ break;
+ case EnergyConsumerType.OTHER:
+ if (delta.otherTotalChargeUC != null) {
+ chargeUC[i] = delta.otherTotalChargeUC[energyConsumer.ordinal];
+ } else {
+ chargeUC[i] = UNAVAILABLE;
+ }
+ break;
+ default:
+ chargeUC[i] = UNAVAILABLE;
+ break;
+ }
+ }
+ return mMeasuredEnergyDetails;
+ }
+
+ private MeasuredEnergyDetails createMeasuredEnergyDetails() {
+ MeasuredEnergyDetails details = new MeasuredEnergyDetails();
+ details.consumers =
+ new MeasuredEnergyDetails.EnergyConsumer[mEnergyConsumers.size()];
+ for (int i = 0; i < mEnergyConsumers.size(); i++) {
+ EnergyConsumer energyConsumer = mEnergyConsumers.valueAt(i);
+ MeasuredEnergyDetails.EnergyConsumer consumer =
+ new MeasuredEnergyDetails.EnergyConsumer();
+ consumer.type = energyConsumer.type;
+ consumer.ordinal = energyConsumer.ordinal;
+ switch (consumer.type) {
+ case EnergyConsumerType.BLUETOOTH:
+ consumer.name = "BLUETOOTH";
+ break;
+ case EnergyConsumerType.CPU_CLUSTER:
+ consumer.name = "CPU";
+ break;
+ case EnergyConsumerType.DISPLAY:
+ consumer.name = "DISPLAY";
+ break;
+ case EnergyConsumerType.GNSS:
+ consumer.name = "GNSS";
+ break;
+ case EnergyConsumerType.MOBILE_RADIO:
+ consumer.name = "MOBILE_RADIO";
+ break;
+ case EnergyConsumerType.WIFI:
+ consumer.name = "WIFI";
+ break;
+ case EnergyConsumerType.OTHER:
+ consumer.name = sanitizeCustomBucketName(energyConsumer.name);
+ break;
+ default:
+ consumer.name = "UNKNOWN";
+ break;
+ }
+ if (consumer.type != EnergyConsumerType.OTHER) {
+ boolean hasOrdinal = consumer.ordinal != 0;
+ if (!hasOrdinal) {
+ // See if any other EnergyConsumer of the same type has an ordinal
+ for (int j = 0; j < mEnergyConsumers.size(); j++) {
+ EnergyConsumer aConsumer = mEnergyConsumers.valueAt(j);
+ if (aConsumer.type == consumer.type && aConsumer.ordinal != 0) {
+ hasOrdinal = true;
+ break;
+ }
+ }
+ }
+ if (hasOrdinal) {
+ consumer.name = consumer.name + "/" + energyConsumer.ordinal;
+ }
+ }
+ details.consumers[i] = consumer;
+ }
+
+ details.chargeUC = new long[details.consumers.length];
+ return details;
+ }
}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index c04b19558770..804689a219b4 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -422,7 +422,7 @@ final class AccessibilityController {
if (mAccessibilityTracing.isTracingEnabled(FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK)) {
mAccessibilityTracing.logTrace(TAG + ".onSomeWindowResizedOrMoved",
FLAGS_WINDOWS_FOR_ACCESSIBILITY_CALLBACK,
- "displayIds={" + displayIds.toString() + "}", "".getBytes(), callingUid);
+ "displayIds={" + Arrays.toString(displayIds) + "}", "".getBytes(), callingUid);
}
// Not relevant for the display magnifier.
for (int i = 0; i < displayIds.length; i++) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index f8f94f655a16..63dcbf85ed32 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -79,6 +79,7 @@ import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO;
+import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY;
@@ -1582,13 +1583,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (newParent != null && isState(RESUMED)) {
newParent.setResumedActivity(this, "onParentChanged");
- if (mStartingWindow != null && mStartingData != null
- && mStartingData.mAssociatedTask == null && newParent.isEmbedded()) {
- // The starting window should keep covering its task when the activity is
- // reparented to a task fragment that may not fill the task bounds.
- associateStartingDataWithTask();
- attachStartingSurfaceToAssociatedTask();
- }
mImeInsetsFrozenUntilStartInput = false;
}
@@ -2679,14 +2673,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
+ /** Called when the starting window is added to this activity. */
void attachStartingWindow(@NonNull WindowState startingWindow) {
startingWindow.mStartingData = mStartingData;
mStartingWindow = startingWindow;
+ // The snapshot type may have called associateStartingDataWithTask().
if (mStartingData != null && mStartingData.mAssociatedTask != null) {
attachStartingSurfaceToAssociatedTask();
}
}
+ /** Makes starting window always fill the associated task. */
private void attachStartingSurfaceToAssociatedTask() {
// Associate the configuration of starting window with the task.
overrideConfigurationPropagation(mStartingWindow, mStartingData.mAssociatedTask);
@@ -2694,6 +2691,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mStartingData.mAssociatedTask.mSurfaceControl);
}
+ /** Called when the starting window is not added yet but its data is known to fill the task. */
private void associateStartingDataWithTask() {
mStartingData.mAssociatedTask = task;
task.forAllActivities(r -> {
@@ -2703,6 +2701,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
});
}
+ /** Associates and attaches an added starting window to the current task. */
+ void associateStartingWindowWithTaskIfNeeded() {
+ if (mStartingWindow == null || mStartingData == null
+ || mStartingData.mAssociatedTask != null) {
+ return;
+ }
+ associateStartingDataWithTask();
+ attachStartingSurfaceToAssociatedTask();
+ }
+
void removeStartingWindow() {
boolean prevEligibleForLetterboxEducation = isEligibleForLetterboxEducation();
@@ -8802,9 +8810,25 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* Returns the min aspect ratio of this activity.
*/
float getMinAspectRatio() {
- if (info.applicationInfo == null || !info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO) || (
- info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY)
- && !ActivityInfo.isFixedOrientationPortrait(getRequestedOrientation()))) {
+ if (info.applicationInfo == null) {
+ return info.getMinAspectRatio();
+ }
+
+ if (!info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO)) {
+ return info.getMinAspectRatio();
+ }
+
+ if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY)
+ && !ActivityInfo.isFixedOrientationPortrait(getRequestedOrientation())) {
+ return info.getMinAspectRatio();
+ }
+
+ if (info.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN)
+ && getParent().getConfiguration().orientation == ORIENTATION_PORTRAIT
+ && getParent().getWindowConfiguration().getWindowingMode()
+ == WINDOWING_MODE_FULLSCREEN) {
+ // We are using the parent configuration here as this is the most recent one that gets
+ // passed to onConfigurationChanged when a relevant change takes place
return info.getMinAspectRatio();
}
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 619d693068d4..f224cc7082f6 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1866,6 +1866,16 @@ class ActivityStarter {
final ActivityRecord targetTaskTop = newTask
? null : targetTask.getTopNonFinishingActivity();
if (targetTaskTop != null) {
+ // Removes the existing singleInstance activity in another task (if any) while
+ // launching a singleInstance activity on sourceRecord's task.
+ if (LAUNCH_SINGLE_INSTANCE == mLaunchMode && mSourceRecord != null
+ && targetTask == mSourceRecord.getTask()) {
+ final ActivityRecord activity = mRootWindowContainer.findActivity(mIntent,
+ mStartActivity.info, false);
+ if (activity != null && activity.getTask() != targetTask) {
+ activity.destroyIfPossible("Removes redundant singleInstance");
+ }
+ }
// Recycle the target task for this launch.
startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants);
if (startResult != START_SUCCESS) {
@@ -2449,6 +2459,7 @@ class ActivityStarter {
mInTask = null;
mInTaskFragment = null;
+ mAddingToTaskFragment = null;
mAddingToTask = false;
mSourceRootTask = null;
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 6ee018606d71..208fc6c30114 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -61,6 +61,7 @@ import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY;
import static android.view.WindowManager.DISPLAY_IME_POLICY_LOCAL;
import static android.view.WindowManager.LayoutParams;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
@@ -94,6 +95,7 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONTENT_RECOR
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
+import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WALLPAPER;
@@ -182,11 +184,13 @@ import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
+import android.os.PowerManager;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
+import android.os.WorkSource;
import android.provider.Settings;
import android.util.ArraySet;
import android.util.DisplayMetrics;
@@ -701,10 +705,33 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
*/
private boolean mInEnsureActivitiesVisible = false;
- // Used to indicate that the movement of child tasks to top will not move the display to top as
- // well and thus won't change the top resumed / focused record
+ /**
+ * Used to indicate that the movement of child tasks to top will not move the display to top as
+ * well and thus won't change the top resumed / focused record
+ */
boolean mDontMoveToTop;
+ /** Used for windows that want to keep the screen awake. */
+ private PowerManager.WakeLock mHoldScreenWakeLock;
+
+ /** The current window causing mHoldScreenWakeLock to be held. */
+ private WindowState mHoldScreenWindow;
+
+ /**
+ * Used during updates to temporarily store what will become the next value for
+ * mHoldScreenWindow.
+ */
+ private WindowState mTmpHoldScreenWindow;
+
+ /** Last window that obscures all windows below. */
+ private WindowState mObscuringWindow;
+
+ /** Last window which obscured a window holding the screen locked. */
+ private WindowState mLastWakeLockObscuringWindow;
+
+ /** Last window to hold the screen locked. */
+ private WindowState mLastWakeLockHoldingWindow;
+
/**
* The helper of policy controller.
*
@@ -917,7 +944,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
if (isDisplayed && w.isObscuringDisplay()) {
// This window completely covers everything behind it, so we want to leave all
// of them as undimmed (for performance reasons).
- root.mObscuringWindow = w;
+ mObscuringWindow = w;
mTmpApplySurfaceChangesTransactionState.obscured = true;
}
@@ -931,6 +958,15 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
if (w.mHasSurface && isDisplayed) {
+ if ((w.mAttrs.flags & FLAG_KEEP_SCREEN_ON) != 0) {
+ mTmpHoldScreenWindow = w;
+ } else if (w == mLastWakeLockHoldingWindow) {
+ ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON,
+ "handleNotObscuredLocked: %s was holding screen wakelock but no longer "
+ + "has FLAG_KEEP_SCREEN_ON!!! called by%s",
+ w, Debug.getCallers(10));
+ }
+
final int type = w.mAttrs.type;
if (type == TYPE_SYSTEM_DIALOG
|| type == TYPE_SYSTEM_ERROR
@@ -1050,6 +1086,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
calculatePrivacyIndicatorBoundsForRotation(mDisplayInfo.rotation));
initializeDisplayBaseInfo();
+ mHoldScreenWakeLock = mWmService.mPowerManager.newWakeLock(
+ PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE,
+ TAG_WM + "/displayId:" + mDisplayId, mDisplayId);
+ mHoldScreenWakeLock.setReferenceCounted(false);
+
mAppTransition = new AppTransition(mWmService.mContext, mWmService, this);
mAppTransition.registerListenerLocked(mWmService.mActivityManagerAppTransitionNotifier);
mAppTransition.registerListenerLocked(mFixedRotationTransitionListener);
@@ -1110,6 +1151,37 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this);
}
+ private void beginHoldScreenUpdate() {
+ mTmpHoldScreenWindow = null;
+ mObscuringWindow = null;
+ }
+
+ private void finishHoldScreenUpdate() {
+ final boolean hold = mTmpHoldScreenWindow != null;
+ if (hold && mTmpHoldScreenWindow != mHoldScreenWindow) {
+ mHoldScreenWakeLock.setWorkSource(new WorkSource(mTmpHoldScreenWindow.mSession.mUid));
+ }
+ mHoldScreenWindow = mTmpHoldScreenWindow;
+ mTmpHoldScreenWindow = null;
+
+ final boolean state = mHoldScreenWakeLock.isHeld();
+ if (hold != state) {
+ if (hold) {
+ ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to %s",
+ mHoldScreenWindow);
+ mLastWakeLockHoldingWindow = mHoldScreenWindow;
+ mLastWakeLockObscuringWindow = null;
+ mHoldScreenWakeLock.acquire();
+ } else {
+ ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by %s",
+ mObscuringWindow);
+ mLastWakeLockHoldingWindow = null;
+ mLastWakeLockObscuringWindow = mObscuringWindow;
+ mHoldScreenWakeLock.release();
+ }
+ }
+ }
+
@Override
void migrateToNewSurfaceControl(Transaction t) {
t.remove(mSurfaceControl);
@@ -3456,6 +3528,16 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
pw.println();
+ pw.print(prefix + "mHoldScreenWindow="); pw.print(mHoldScreenWindow);
+ pw.println();
+ pw.print(prefix + "mObscuringWindow="); pw.print(mObscuringWindow);
+ pw.println();
+ pw.print(prefix + "mLastWakeLockHoldingWindow="); pw.print(mLastWakeLockHoldingWindow);
+ pw.println();
+ pw.print(prefix + "mLastWakeLockObscuringWindow=");
+ pw.println(mLastWakeLockObscuringWindow);
+
+ pw.println();
mWallpaperController.dump(pw, " ");
if (mSystemGestureExclusionListeners.getRegisteredCallbackCount() > 0) {
@@ -4675,6 +4757,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
void applySurfaceChangesTransaction() {
final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked;
+ beginHoldScreenUpdate();
+
mTmpUpdateAllDrawn.clear();
if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
@@ -4750,6 +4834,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
// can now be shown.
activity.updateAllDrawn();
}
+
+ finishHoldScreenUpdate();
}
private void getBounds(Rect out, @Rotation int rotation) {
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 508e6dc77a61..d4eac8d3ad4b 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -362,6 +362,7 @@ public class DisplayPolicy {
private WindowState mTopFullscreenOpaqueWindowState;
private boolean mTopIsFullscreen;
private int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
+ private boolean mForceConsumeSystemBars;
private boolean mForceShowSystemBars;
private boolean mShowingDream;
@@ -1561,6 +1562,13 @@ public class DisplayPolicy {
}
/**
+ * @return true if the system bars are forced to be consumed
+ */
+ public boolean areSystemBarsForcedConsumedLw() {
+ return mForceConsumeSystemBars;
+ }
+
+ /**
* @return true if the system bars are forced to stay visible
*/
public boolean areSystemBarsForcedShownLw() {
@@ -2462,6 +2470,10 @@ public class DisplayPolicy {
// We need to force showing system bars when the multi-window or freeform root task is
// visible.
mForceShowSystemBars = multiWindowTaskVisible || freeformRootTaskVisible;
+ // We need to force the consumption of the system bars if they are force shown or if they
+ // are controlled by a remote insets controller.
+ mForceConsumeSystemBars = mForceShowSystemBars
+ || mDisplayContent.getInsetsPolicy().remoteInsetsControllerControlsSystemBars(win);
mDisplayContent.getInsetsPolicy().updateBarControlTarget(win);
final boolean topAppHidesStatusBar = topAppHidesStatusBar();
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 077f8b55e5e6..b3f35487f3a5 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -28,7 +28,6 @@ import static android.content.res.Configuration.EMPTY;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
-import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
@@ -176,15 +175,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
private Object mLastWindowFreezeSource = null;
- private Session mHoldScreen = null;
private float mScreenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
private long mUserActivityTimeout = -1;
private boolean mUpdateRotation = false;
- // Following variables are for debugging screen wakelock only.
- // Last window that requires screen wakelock
- WindowState mHoldScreenWindow = null;
- // Last window that obscures all windows below
- WindowState mObscuringWindow = null;
// Only set while traversing the default display based on its content.
// Affects the behavior of mirroring on secondary displays.
private boolean mObscureApplicationContentOnSecondaryDisplays = false;
@@ -801,7 +794,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/);
}
- mHoldScreen = null;
mScreenBrightnessOverride = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mUserActivityTimeout = -1;
mObscureApplicationContentOnSecondaryDisplays = false;
@@ -914,7 +906,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
}
- mWmService.setHoldScreenLocked(mHoldScreen);
if (!mWmService.mDisplayFrozen) {
final float brightnessOverride = mScreenBrightnessOverride < PowerManager.BRIGHTNESS_MIN
|| mScreenBrightnessOverride > PowerManager.BRIGHTNESS_MAX
@@ -994,9 +985,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
private void applySurfaceChangesTransaction() {
- mHoldScreenWindow = null;
- mObscuringWindow = null;
-
// TODO(multi-display): Support these features on secondary screens.
final DisplayContent defaultDc = mDefaultDisplay;
final DisplayInfo defaultInfo = defaultDc.getDisplayInfo();
@@ -1071,15 +1059,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
}
if (w.mHasSurface && canBeSeen) {
- if ((attrFlags & FLAG_KEEP_SCREEN_ON) != 0) {
- mHoldScreen = w.mSession;
- mHoldScreenWindow = w;
- } else if (w == mWmService.mLastWakeLockHoldingWindow) {
- ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON,
- "handleNotObscuredLocked: %s was holding screen wakelock but no longer "
- + "has FLAG_KEEP_SCREEN_ON!!! called by%s",
- w, Debug.getCallers(10));
- }
if (!syswin && w.mAttrs.screenBrightness >= 0
&& Float.isNaN(mScreenBrightnessOverride)) {
mScreenBrightnessOverride = w.mAttrs.screenBrightness;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index e38f5fe61888..659e37bb3de7 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -60,10 +60,7 @@ import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
import static android.view.WindowManager.TRANSIT_NONE;
-import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
@@ -1436,6 +1433,13 @@ class Task extends TaskFragment {
final TaskFragment childTaskFrag = child.asTaskFragment();
if (childTaskFrag != null && childTaskFrag.asTask() == null) {
childTaskFrag.setMinDimensions(mMinWidth, mMinHeight);
+
+ // The starting window should keep covering its task when a pure TaskFragment is added
+ // because its bounds may not fill the task.
+ final ActivityRecord top = getTopMostActivity();
+ if (top != null) {
+ top.associateStartingWindowWithTaskIfNeeded();
+ }
}
}
@@ -4966,23 +4970,17 @@ class Task extends TaskFragment {
dc.prepareAppTransition(TRANSIT_NONE);
mTaskSupervisor.mNoAnimActivities.add(r);
} else {
- int transit = TRANSIT_OLD_ACTIVITY_OPEN;
- if (newTask) {
- if (r.mLaunchTaskBehind) {
- transit = TRANSIT_OLD_TASK_OPEN_BEHIND;
- } else {
- // If a new task is being launched, then mark the existing top activity as
- // supporting picture-in-picture while pausing only if the starting activity
- // would not be considered an overlay on top of the current activity
- // (eg. not fullscreen, or the assistant)
- enableEnterPipOnTaskSwitch(pipCandidate,
- null /* toFrontTask */, r, options);
- transit = TRANSIT_OLD_TASK_OPEN;
- }
- }
dc.prepareAppTransition(TRANSIT_OPEN);
mTaskSupervisor.mNoAnimActivities.remove(r);
}
+ if (newTask && !r.mLaunchTaskBehind) {
+ // If a new task is being launched, then mark the existing top activity as
+ // supporting picture-in-picture while pausing only if the starting activity
+ // would not be considered an overlay on top of the current activity
+ // (eg. not fullscreen, or the assistant)
+ enableEnterPipOnTaskSwitch(pipCandidate,
+ null /* toFrontTask */, r, options);
+ }
boolean doShow = true;
if (newTask) {
// Even though this activity is starting fresh, we still need
diff --git a/services/core/java/com/android/server/wm/TaskPersister.java b/services/core/java/com/android/server/wm/TaskPersister.java
index b8d2febd5dd4..09fd90030f0c 100644
--- a/services/core/java/com/android/server/wm/TaskPersister.java
+++ b/services/core/java/com/android/server/wm/TaskPersister.java
@@ -53,6 +53,7 @@ import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -424,7 +425,7 @@ public class TaskPersister implements PersisterQueue.Listener {
private static void removeObsoleteFiles(ArraySet<Integer> persistentTaskIds, File[] files) {
if (DEBUG) Slog.d(TAG, "removeObsoleteFiles: persistentTaskIds=" + persistentTaskIds +
- " files=" + files);
+ " files=" + Arrays.toString(files));
if (files == null) {
Slog.e(TAG, "File error accessing recents directory (directory doesn't exist?).");
return;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8025cb296b32..3f98ea59a0c0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -103,7 +103,6 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_BOOT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_IME;
-import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_KEEP_SCREEN_ON;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
@@ -218,7 +217,6 @@ import android.os.SystemProperties;
import android.os.SystemService;
import android.os.Trace;
import android.os.UserHandle;
-import android.os.WorkSource;
import android.provider.DeviceConfigInterface;
import android.provider.Settings;
import android.service.vr.IVrManager;
@@ -620,10 +618,6 @@ public class WindowManagerService extends IWindowManager.Stub
boolean mBootAnimationStopped = false;
long mBootWaitForWindowsStartTime = -1;
- // Following variables are for debugging screen wakelock only.
- WindowState mLastWakeLockHoldingWindow = null;
- WindowState mLastWakeLockObscuringWindow = null;
-
/** Dump of the windows and app tokens at the time of the last ANR. Cleared after
* LAST_ANR_LIFETIME_DURATION_MSECS */
String mLastANRState;
@@ -991,10 +985,6 @@ public class WindowManagerService extends IWindowManager.Stub
private boolean mHasWideColorGamutSupport;
private boolean mHasHdrSupport;
- /** Who is holding the screen on. */
- private Session mHoldingScreenOn;
- private PowerManager.WakeLock mHoldingScreenWakeLock;
-
/** Whether or not a layout can cause a wake up when theater mode is enabled. */
boolean mAllowTheaterModeWakeFromLayout;
@@ -1326,10 +1316,6 @@ public class WindowManagerService extends IWindowManager.Stub
mSettingsObserver = new SettingsObserver();
- mHoldingScreenWakeLock = mPowerManager.newWakeLock(
- PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
- mHoldingScreenWakeLock.setReferenceCounted(false);
-
mSurfaceAnimationRunner = new SurfaceAnimationRunner(mTransactionFactory,
mPowerManagerInternal);
@@ -1808,7 +1794,7 @@ public class WindowManagerService extends IWindowManager.Stub
prepareNoneTransitionForRelaunching(activity);
}
- if (displayPolicy.areSystemBarsForcedShownLw()) {
+ if (displayPolicy.areSystemBarsForcedConsumedLw()) {
res |= WindowManagerGlobal.ADD_FLAG_ALWAYS_CONSUME_SYSTEM_BARS;
}
@@ -2527,7 +2513,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (win.mActivityRecord != null) {
win.mActivityRecord.updateReportedVisibilityLocked();
}
- if (displayPolicy.areSystemBarsForcedShownLw()) {
+ if (displayPolicy.areSystemBarsForcedConsumedLw()) {
result |= WindowManagerGlobal.RELAYOUT_RES_CONSUME_ALWAYS_SYSTEM_BARS;
}
if (!win.isGoneForLayout()) {
@@ -6013,34 +5999,6 @@ public class WindowManagerService extends IWindowManager.Stub
});
}
- void setHoldScreenLocked(final Session newHoldScreen) {
- final boolean hold = newHoldScreen != null;
-
- if (hold && mHoldingScreenOn != newHoldScreen) {
- mHoldingScreenWakeLock.setWorkSource(new WorkSource(newHoldScreen.mUid));
- }
- mHoldingScreenOn = newHoldScreen;
-
- final boolean state = mHoldingScreenWakeLock.isHeld();
- if (hold != state) {
- if (hold) {
- ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON, "Acquiring screen wakelock due to %s",
- mRoot.mHoldScreenWindow);
- mLastWakeLockHoldingWindow = mRoot.mHoldScreenWindow;
- mLastWakeLockObscuringWindow = null;
- mHoldingScreenWakeLock.acquire();
- mPolicy.keepScreenOnStartedLw();
- } else {
- ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON, "Releasing screen wakelock, obscured by %s",
- mRoot.mObscuringWindow);
- mLastWakeLockHoldingWindow = null;
- mLastWakeLockObscuringWindow = mRoot.mObscuringWindow;
- mPolicy.keepScreenOnStoppedLw();
- mHoldingScreenWakeLock.release();
- }
- }
- }
-
void requestTraversal() {
mWindowPlacerLocked.requestTraversal();
}
@@ -6674,9 +6632,6 @@ public class WindowManagerService extends IWindowManager.Stub
pw.print(mLastFinishedFreezeSource);
}
pw.println();
- pw.print(" mLastWakeLockHoldingWindow=");pw.print(mLastWakeLockHoldingWindow);
- pw.print(" mLastWakeLockObscuringWindow="); pw.print(mLastWakeLockObscuringWindow);
- pw.println();
mInputManagerCallback.dump(pw, " ");
mTaskSnapshotController.dump(pw, " ");
@@ -8896,7 +8851,7 @@ public class WindowManagerService extends IWindowManager.Stub
: overrideScale;
outInsetsState.scale(1f / compatScale);
}
- return dc.getDisplayPolicy().areSystemBarsForcedShownLw();
+ return dc.getDisplayPolicy().areSystemBarsForcedConsumedLw();
}
} finally {
Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 34a4bf1d9c2a..5fefc3762c0d 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -29,6 +29,7 @@ import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_LAUNCH_TASK;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_PENDING_INTENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_INSETS_PROVIDER;
+import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REMOVE_TASK;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT;
import static android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REPARENT_ACTIVITY_TO_TASK_FRAGMENT;
@@ -703,6 +704,12 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
@Nullable ITaskFragmentOrganizer organizer, @Nullable Transition finishTransition) {
final int type = hop.getType();
switch (type) {
+ case HIERARCHY_OP_TYPE_REMOVE_TASK: {
+ final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
+ final Task task = wc != null ? wc.asTask() : null;
+ task.remove(true, "Applying remove task Hierarchy Op");
+ break;
+ }
case HIERARCHY_OP_TYPE_SET_LAUNCH_ROOT: {
final WindowContainer wc = WindowContainer.fromBinder(hop.getContainer());
final Task task = wc != null ? wc.asTask() : null;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 346930311068..2e7e78db9e05 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3917,7 +3917,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
final boolean forceRelayout = syncWithBuffers || isDragResizeChanged;
final DisplayContent displayContent = getDisplayContent();
final boolean alwaysConsumeSystemBars =
- displayContent.getDisplayPolicy().areSystemBarsForcedShownLw();
+ displayContent.getDisplayPolicy().areSystemBarsForcedConsumedLw();
final int displayId = displayContent.getDisplayId();
if (isDragResizeChanged) {
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 2ee5fb01efb3..aa589024fdc6 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -228,7 +228,5 @@ class WindowSurfacePlacer {
public void dump(PrintWriter pw, String prefix) {
pw.println(prefix + "mTraversalScheduled=" + mTraversalScheduled);
- pw.println(prefix + "mHoldScreenWindow=" + mService.mRoot.mHoldScreenWindow);
- pw.println(prefix + "mObscuringWindow=" + mService.mRoot.mObscuringWindow);
}
}
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 40789964f4e1..5d6ffd8b8ead 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -37,6 +37,7 @@ cc_library_static {
"com_android_server_ConsumerIrService.cpp",
"com_android_server_companion_virtual_InputController.cpp",
"com_android_server_devicepolicy_CryptoTestHelper.cpp",
+ "com_android_server_display_DisplayControl.cpp",
"com_android_server_connectivity_Vpn.cpp",
"com_android_server_gpu_GpuService.cpp",
"com_android_server_HardwarePropertiesManagerService.cpp",
@@ -89,6 +90,7 @@ cc_library_static {
cc_defaults {
name: "libservices.core-libs",
+ defaults: ["android.hardware.graphics.common-ndk_shared"],
shared_libs: [
"libadb_pairing_server",
"libadb_pairing_connection",
@@ -158,7 +160,6 @@ cc_defaults {
"android.hardware.graphics.bufferqueue@1.0",
"android.hardware.graphics.bufferqueue@2.0",
"android.hardware.graphics.common@1.2",
- "android.hardware.graphics.common-V3-ndk",
"android.hardware.graphics.mapper@4.0",
"android.hardware.input.processor-V1-ndk",
"android.hardware.ir@1.0",
diff --git a/services/core/jni/com_android_server_display_DisplayControl.cpp b/services/core/jni/com_android_server_display_DisplayControl.cpp
new file mode 100644
index 000000000000..61f2b1411a0b
--- /dev/null
+++ b/services/core/jni/com_android_server_display_DisplayControl.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android_util_Binder.h>
+#include <gui/SurfaceComposerClient.h>
+#include <jni.h>
+#include <nativehelper/ScopedUtfChars.h>
+
+namespace android {
+
+static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj, jboolean secure) {
+ ScopedUtfChars name(env, nameObj);
+ sp<IBinder> token(SurfaceComposerClient::createDisplay(String8(name.c_str()), bool(secure)));
+ return javaObjectForIBinder(env, token);
+}
+
+static void nativeDestroyDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
+ sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+ if (token == NULL) return;
+ SurfaceComposerClient::destroyDisplay(token);
+}
+
+// ----------------------------------------------------------------------------
+
+static const JNINativeMethod sDisplayMethods[] = {
+ // clang-format off
+ {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;",
+ (void*)nativeCreateDisplay },
+ {"nativeDestroyDisplay", "(Landroid/os/IBinder;)V",
+ (void*)nativeDestroyDisplay },
+ // clang-format on
+};
+
+int register_com_android_server_display_DisplayControl(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "com/android/server/display/DisplayControl",
+ sDisplayMethods, NELEM(sDisplayMethods));
+}
+
+} // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 0cd949457cd1..00bef0935308 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -64,6 +64,7 @@ int register_android_server_sensor_SensorService(JavaVM* vm, JNIEnv* env);
int register_android_server_companion_virtual_InputController(JNIEnv* env);
int register_android_server_app_GameManagerService(JNIEnv* env);
int register_com_android_server_wm_TaskFpsCallbackController(JNIEnv* env);
+int register_com_android_server_display_DisplayControl(JNIEnv* env);
};
using namespace android;
@@ -120,5 +121,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_server_companion_virtual_InputController(env);
register_android_server_app_GameManagerService(env);
register_com_android_server_wm_TaskFpsCallbackController(env);
+ register_com_android_server_display_DisplayControl(env);
return JNI_VERSION_1_4;
}
diff --git a/services/core/xsd/display-device-config/autobrightness.xsd b/services/core/xsd/display-device-config/autobrightness.xsd
new file mode 100644
index 000000000000..477625a36cbd
--- /dev/null
+++ b/services/core/xsd/display-device-config/autobrightness.xsd
@@ -0,0 +1,33 @@
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<xs:schema version="2.0"
+ elementFormDefault="qualified"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:complexType name="autoBrightness">
+ <xs:sequence>
+ <!-- Sets the debounce for autoBrightness brightening in millis-->
+ <xs:element name="brighteningLightDebounceMillis" type="xs:nonNegativeInteger"
+ minOccurs="0" maxOccurs="1">
+ <xs:annotation name="final"/>
+ </xs:element>
+ <!-- Sets the debounce for autoBrightness darkening in millis-->
+ <xs:element name="darkeningLightDebounceMillis" type="xs:nonNegativeInteger"
+ minOccurs="0" maxOccurs="1">
+ <xs:annotation name="final"/>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+</xs:schema> \ No newline at end of file
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index 98f83d8c0d09..bea5e2c2de74 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -23,6 +23,7 @@
<xs:schema version="2.0"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
+ <xs:include schemaLocation="autobrightness.xsd" />
<xs:element name="displayConfiguration">
<xs:complexType>
<xs:sequence>
@@ -342,74 +343,4 @@
<xs:annotation name="final"/>
</xs:element>
</xs:complexType>
-
- <xs:complexType name="autoBrightness">
- <xs:sequence>
- <!-- Sets the debounce for autoBrightness brightening in millis-->
- <xs:element name="brighteningLightDebounceMillis" type="xs:nonNegativeInteger"
- minOccurs="0" maxOccurs="1">
- <xs:annotation name="final"/>
- </xs:element>
- <!-- Sets the debounce for autoBrightness darkening in millis-->
- <xs:element name="darkeningLightDebounceMillis" type="xs:nonNegativeInteger"
- minOccurs="0" maxOccurs="1">
- <xs:annotation name="final"/>
- </xs:element>
- <!-- Sets the brightness mapping of the desired screen brightness in nits to the
- corresponding lux for the current display -->
- <xs:element name="displayBrightnessMapping" type="displayBrightnessMapping"
- minOccurs="0" maxOccurs="1">
- <xs:annotation name="final"/>
- </xs:element>
- </xs:sequence>
- </xs:complexType>
-
- <!-- Represents the brightness mapping of the desired screen brightness in nits to the
- corresponding lux for the current display -->
- <xs:complexType name="displayBrightnessMapping">
- <xs:sequence>
- <!-- Sets the list of display brightness points, each representing the desired screen
- brightness in nits to the corresponding lux for the current display
-
- The N entries of this array define N + 1 control points as follows:
- (1-based arrays)
-
- Point 1: (0, nits[1]): currentLux <= 0
- Point 2: (lux[1], nits[2]): 0 < currentLux <= lux[1]
- Point 3: (lux[2], nits[3]): lux[2] < currentLux <= lux[3]
- ...
- Point N+1: (lux[N], nits[N+1]): lux[N] < currentLux
-
- The control points must be strictly increasing. Each control point
- corresponds to an entry in the brightness backlight values arrays.
- For example, if currentLux == lux[1] (first element of the levels array)
- then the brightness will be determined by nits[2] (second element
- of the brightness values array).
- -->
- <xs:element name="displayBrightnessPoint" type="displayBrightnessPoint"
- minOccurs="1" maxOccurs="unbounded">
- <xs:annotation name="final"/>
- </xs:element>
- </xs:sequence>
- </xs:complexType>
-
- <!-- Represents a point in the display brightness mapping, representing the lux level from the
- light sensor to the desired screen brightness in nits at this level -->
- <xs:complexType name="displayBrightnessPoint">
- <xs:sequence>
- <!-- The lux level from the light sensor. This must be a non-negative integer -->
- <xs:element name="lux" type="xs:nonNegativeInteger"
- minOccurs="1" maxOccurs="1">
- <xs:annotation name="final"/>
- </xs:element>
-
- <!-- Desired screen brightness in nits corresponding to the suggested lux values.
- The display brightness is defined as the measured brightness of an all-white image.
- This must be a non-negative integer -->
- <xs:element name="nits" type="xs:nonNegativeInteger"
- minOccurs="1" maxOccurs="1">
- <xs:annotation name="final"/>
- </xs:element>
- </xs:sequence>
- </xs:complexType>
</xs:schema>
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index e5d26177b725..e9a926946764 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -5,10 +5,8 @@ package com.android.server.display.config {
ctor public AutoBrightness();
method public final java.math.BigInteger getBrighteningLightDebounceMillis();
method public final java.math.BigInteger getDarkeningLightDebounceMillis();
- method public final com.android.server.display.config.DisplayBrightnessMapping getDisplayBrightnessMapping();
method public final void setBrighteningLightDebounceMillis(java.math.BigInteger);
method public final void setDarkeningLightDebounceMillis(java.math.BigInteger);
- method public final void setDisplayBrightnessMapping(com.android.server.display.config.DisplayBrightnessMapping);
}
public class BrightnessThresholds {
@@ -45,19 +43,6 @@ package com.android.server.display.config {
method public java.util.List<com.android.server.display.config.Density> getDensity();
}
- public class DisplayBrightnessMapping {
- ctor public DisplayBrightnessMapping();
- method public final java.util.List<com.android.server.display.config.DisplayBrightnessPoint> getDisplayBrightnessPoint();
- }
-
- public class DisplayBrightnessPoint {
- ctor public DisplayBrightnessPoint();
- method public final java.math.BigInteger getLux();
- method public final java.math.BigInteger getNits();
- method public final void setLux(java.math.BigInteger);
- method public final void setNits(java.math.BigInteger);
- }
-
public class DisplayConfiguration {
ctor public DisplayConfiguration();
method @NonNull public final com.android.server.display.config.Thresholds getAmbientBrightnessChangeThresholds();
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index d3222901db1e..3c6866205fda 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -205,6 +205,7 @@ public final class ProfcollectForwardingService extends SystemService {
.setRequiresDeviceIdle(true)
.setRequiresCharging(true)
.setPeriodic(BG_PROCESS_PERIOD)
+ .setPriority(JobInfo.PRIORITY_MIN)
.build());
}
diff --git a/services/tests/mockingservicestests/jni/Android.bp b/services/tests/mockingservicestests/jni/Android.bp
index f454ac7e9e4b..f1dc1fa1a108 100644
--- a/services/tests/mockingservicestests/jni/Android.bp
+++ b/services/tests/mockingservicestests/jni/Android.bp
@@ -10,6 +10,8 @@ package {
cc_library_shared {
name: "libmockingservicestestjni",
+ defaults: ["android.hardware.graphics.common-ndk_shared"],
+
cflags: [
"-Wall",
"-Werror",
@@ -48,7 +50,6 @@ cc_library_shared {
"android.hardware.graphics.bufferqueue@1.0",
"android.hardware.graphics.bufferqueue@2.0",
"android.hardware.graphics.common@1.2",
- "android.hardware.graphics.common-V3-ndk",
"android.hardware.graphics.mapper@4.0",
"android.hidl.token@1.0-utils",
],
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
new file mode 100644
index 000000000000..130b02d3989e
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.app.Activity;
+import android.app.AppOpsManager;
+import android.app.BroadcastOptions;
+import android.app.IApplicationThread;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManagerInternal;
+import android.content.pm.ResolveInfo;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.Log;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.server.LocalServices;
+import com.android.server.am.ActivityManagerService.Injector;
+import com.android.server.appop.AppOpsService;
+import com.android.server.wm.ActivityTaskManagerService;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Common tests for {@link BroadcastQueue} implementations.
+ */
+@MediumTest
+@RunWith(Parameterized.class)
+public class BroadcastQueueTest {
+ private static final String TAG = "BroadcastQueueTest";
+
+ @Rule
+ public final ApplicationExitInfoTest.ServiceThreadRule
+ mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule();
+
+ private final Impl mImpl;
+
+ private enum Impl {
+ DEFAULT
+ }
+
+ private Context mContext;
+ private HandlerThread mHandlerThread;
+
+ @Mock
+ private AppOpsService mAppOpsService;
+ @Mock
+ private PackageManagerInternal mPackageManagerInt;
+
+ private ActivityManagerService mAms;
+ private BroadcastQueue mQueue;
+
+ @Parameters(name = "impl={0}")
+ public static Collection<Object[]> data() {
+ return Arrays.asList(new Object[][] { {Impl.DEFAULT} });
+ }
+
+ public BroadcastQueueTest(Impl impl) {
+ mImpl = impl;
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ mHandlerThread = new HandlerThread(TAG);
+ mHandlerThread.start();
+
+ LocalServices.removeServiceForTest(PackageManagerInternal.class);
+ LocalServices.addService(PackageManagerInternal.class, mPackageManagerInt);
+ doReturn(new ComponentName("", "")).when(mPackageManagerInt).getSystemUiServiceComponent();
+ doNothing().when(mPackageManagerInt).setPackageStoppedState(any(), anyBoolean(), anyInt());
+
+ final ActivityManagerService realAms = new ActivityManagerService(
+ new TestInjector(mContext), mServiceThreadRule.getThread());
+ realAms.mActivityTaskManager = new ActivityTaskManagerService(mContext);
+ realAms.mActivityTaskManager.initialize(null, null, mContext.getMainLooper());
+ realAms.mAtmInternal = spy(realAms.mActivityTaskManager.getAtmInternal());
+ realAms.mPackageManagerInt = mPackageManagerInt;
+ mAms = spy(realAms);
+
+ final BroadcastConstants constants = new BroadcastConstants(
+ Settings.Global.BROADCAST_FG_CONSTANTS);
+ final BroadcastSkipPolicy emptySkipPolicy = new BroadcastSkipPolicy(mAms) {
+ public boolean shouldSkip(BroadcastRecord r, ResolveInfo info) {
+ return false;
+ }
+ public boolean shouldSkip(BroadcastRecord r, BroadcastFilter filter) {
+ return false;
+ }
+ };
+
+ if (mImpl == Impl.DEFAULT) {
+ mQueue = new BroadcastQueueImpl(mAms, mHandlerThread.getThreadHandler(), TAG,
+ constants, emptySkipPolicy, false);
+ } else {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private class TestInjector extends Injector {
+ TestInjector(Context context) {
+ super(context);
+ }
+
+ @Override
+ public AppOpsService getAppOpsService(File file, Handler handler) {
+ return mAppOpsService;
+ }
+
+ @Override
+ public Handler getUiHandler(ActivityManagerService service) {
+ return mHandlerThread.getThreadHandler();
+ }
+ }
+
+ private ProcessRecord makeActiveProcessRecord(String packageName) throws Exception {
+ final ProcessRecord r = new ProcessRecord(mAms, makeApplicationInfo(packageName), null,
+ getUidForPackage(packageName));
+ final IApplicationThread thread = mock(IApplicationThread.class);
+ final IBinder threadBinder = new Binder();
+ doReturn(threadBinder).when(thread).asBinder();
+ r.makeActive(thread, mAms.mProcessStats);
+
+ doReturn(r).when(mAms).getProcessRecordLocked(eq(r.info.processName), eq(r.info.uid));
+
+ doAnswer((invocation) -> {
+ Log.v(TAG, "Delivering finishReceiverLocked() for "
+ + Arrays.toString(invocation.getArguments()));
+ mQueue.finishReceiverLocked(threadBinder, Activity.RESULT_OK,
+ null, null, false, false);
+ return null;
+ }).when(thread).scheduleReceiver(any(), any(), any(), anyInt(), any(), any(), anyBoolean(),
+ anyInt(), anyInt());
+
+ return r;
+ }
+
+ private ApplicationInfo makeApplicationInfo(String packageName) {
+ final ApplicationInfo ai = new ApplicationInfo();
+ ai.packageName = packageName;
+ ai.uid = getUidForPackage(packageName);
+ return ai;
+ }
+
+ private ResolveInfo makeManifestReceiver(String packageName, String name) {
+ final ResolveInfo ri = new ResolveInfo();
+ ri.activityInfo = new ActivityInfo();
+ ri.activityInfo.packageName = packageName;
+ ri.activityInfo.name = name;
+ ri.activityInfo.applicationInfo = makeApplicationInfo(packageName);
+ return ri;
+ }
+
+ private BroadcastRecord makeBroadcastRecord(Intent intent, ProcessRecord callerApp,
+ List receivers) {
+ return makeBroadcastRecord(intent, callerApp, BroadcastOptions.makeBasic(), receivers);
+ }
+
+ private BroadcastRecord makeBroadcastRecord(Intent intent, ProcessRecord callerApp,
+ BroadcastOptions options, List receivers) {
+ return new BroadcastRecord(mQueue, intent, callerApp, callerApp.info.packageName, null,
+ callerApp.getPid(), callerApp.info.uid, false, null, null, null, null,
+ AppOpsManager.OP_NONE, options, receivers, null, Activity.RESULT_OK, null, null,
+ false, false, false, UserHandle.USER_SYSTEM, false, null, false, null);
+ }
+
+ private ArgumentMatcher<Intent> filterEqualsIgnoringComponent(Intent intent) {
+ final Intent intentClean = new Intent(intent);
+ intentClean.setComponent(null);
+ return (test) -> {
+ final Intent testClean = new Intent(test);
+ testClean.setComponent(null);
+ return intentClean.filterEquals(testClean);
+ };
+ }
+
+ private void waitForIdle() throws Exception {
+ for (int i = 0; i < 100; i++) {
+ if (mQueue.isIdle()) break;
+ SystemClock.sleep(100);
+ }
+ assertTrue(mQueue.isIdle());
+ }
+
+ private static final String PACKAGE_RED = "com.example.red";
+ private static final String PACKAGE_GREEN = "com.example.green";
+ private static final String PACKAGE_BLUE = "com.example.blue";
+
+ private static final String CLASS_RED = "com.example.red.Red";
+ private static final String CLASS_GREEN = "com.example.green.Green";
+ private static final String CLASS_BLUE = "com.example.blue.Blue";
+
+ private static int getUidForPackage(String packageName) {
+ switch (packageName) {
+ case PACKAGE_RED: return android.os.Process.FIRST_APPLICATION_UID + 1;
+ case PACKAGE_GREEN: return android.os.Process.FIRST_APPLICATION_UID + 2;
+ case PACKAGE_BLUE: return android.os.Process.FIRST_APPLICATION_UID + 3;
+ default: throw new IllegalArgumentException();
+ }
+ }
+
+ @Test
+ public void testSimple_Manifest_Warm() throws Exception {
+ final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
+ final ProcessRecord receiverApp = makeActiveProcessRecord(PACKAGE_GREEN);
+
+ final Intent intent = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
+ mQueue.enqueueBroadcastLocked(makeBroadcastRecord(intent, callerApp,
+ List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN))));
+
+ waitForIdle();
+ verify(receiverApp.getThread()).scheduleReceiver(
+ argThat(filterEqualsIgnoringComponent(intent)), any(), any(), anyInt(), any(),
+ any(), eq(false), eq(UserHandle.USER_SYSTEM), anyInt());
+ }
+
+ @Test
+ public void testSimple_Manifest_Warm_Multiple() throws Exception {
+ final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
+
+ final ProcessRecord receiverGreenApp = makeActiveProcessRecord(PACKAGE_GREEN);
+ final ProcessRecord receiverBlueApp = makeActiveProcessRecord(PACKAGE_BLUE);
+
+ final Intent timezone = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
+ mQueue.enqueueBroadcastLocked(makeBroadcastRecord(timezone, callerApp,
+ List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN),
+ makeManifestReceiver(PACKAGE_BLUE, CLASS_BLUE))));
+
+ final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ mQueue.enqueueBroadcastLocked(makeBroadcastRecord(airplane, callerApp,
+ List.of(makeManifestReceiver(PACKAGE_BLUE, CLASS_BLUE))));
+
+ waitForIdle();
+ verify(receiverGreenApp.getThread()).scheduleReceiver(
+ argThat(filterEqualsIgnoringComponent(timezone)), any(), any(), anyInt(), any(),
+ any(), eq(false), eq(UserHandle.USER_SYSTEM), anyInt());
+ verify(receiverBlueApp.getThread()).scheduleReceiver(
+ argThat(filterEqualsIgnoringComponent(timezone)), any(), any(), anyInt(), any(),
+ any(), eq(false), eq(UserHandle.USER_SYSTEM), anyInt());
+ verify(receiverBlueApp.getThread()).scheduleReceiver(
+ argThat(filterEqualsIgnoringComponent(airplane)), any(), any(), anyInt(), any(),
+ any(), eq(false), eq(UserHandle.USER_SYSTEM), anyInt());
+ }
+
+ // TODO: verify registered receiver in warm app
+ // TODO: verify manifest receiver in cold app
+
+ // TODO: verify mixing multiple manifest and registered receivers of same broadcast
+ // TODO: verify delivery of 3 distinct broadcasts
+}
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 60ddeeb497a8..7755552bcad2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -149,12 +149,6 @@ public class LocalDisplayAdapterTest {
.thenReturn(mockArray);
when(mMockedResources.obtainTypedArray(R.array.config_roundedCornerBottomRadiusArray))
.thenReturn(mockArray);
- when(mMockedResources.obtainTypedArray(
- com.android.internal.R.array.config_autoBrightnessDisplayValuesNits))
- .thenReturn(mockArray);
- when(mMockedResources.obtainTypedArray(
- com.android.internal.R.array.config_autoBrightnessLevels))
- .thenReturn(mockArray);
}
@After
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java
index 9d269719db64..fb9cbb00255c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/dex/DexManagerTests.java
@@ -61,7 +61,6 @@ import org.mockito.quality.Strictness;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -1029,44 +1028,4 @@ public class DexManagerTests {
return mPackageInfo.applicationInfo.splitSourceDirs[length - 1];
}
}
-
- private boolean shouldPackageRunOob(boolean isDefaultEnabled, String whitelist,
- Collection<String> packageNamesInSameProcess) {
- return DexManager.isPackageSelectedToRunOobInternal(
- isDefaultEnabled, whitelist, packageNamesInSameProcess);
- }
-
- @Test
- public void testOobPackageSelectionDefault() {
- // Feature is off by default, not overriden
- assertFalse(shouldPackageRunOob(false, "ALL", null));
- }
-
- @Test
- public void testOobPackageSelectionWhitelist() {
- // Various allowlist of apps to run in OOB mode.
- final String kWhitelistApp0 = "com.priv.app0";
- final String kWhitelistApp1 = "com.priv.app1";
- final String kWhitelistApp2 = "com.priv.app2";
- final String kWhitelistApp1AndApp2 = "com.priv.app1,com.priv.app2";
-
- // Packages that shares the targeting process.
- final Collection<String> runningPackages = Arrays.asList("com.priv.app1", "com.priv.app2");
-
- // Feature is off, allowlist does not matter
- assertFalse(shouldPackageRunOob(false, kWhitelistApp0, runningPackages));
- assertFalse(shouldPackageRunOob(false, kWhitelistApp1, runningPackages));
- assertFalse(shouldPackageRunOob(false, "", runningPackages));
- assertFalse(shouldPackageRunOob(false, "ALL", runningPackages));
-
- // Feature is on, app not in allowlist
- assertFalse(shouldPackageRunOob(true, kWhitelistApp0, runningPackages));
- assertFalse(shouldPackageRunOob(true, "", runningPackages));
-
- // Feature is on, app in allowlist
- assertTrue(shouldPackageRunOob(true, kWhitelistApp1, runningPackages));
- assertTrue(shouldPackageRunOob(true, kWhitelistApp2, runningPackages));
- assertTrue(shouldPackageRunOob(true, kWhitelistApp1AndApp2, runningPackages));
- assertTrue(shouldPackageRunOob(true, "ALL", runningPackages));
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
index 59b69f9ffebf..233caf9c7761 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java
@@ -837,7 +837,7 @@ public class MotionEventInjectorTest {
@Override
public void describeTo(Description description) {
- description.appendText("Contains points " + points);
+ description.appendText("Contains points " + Arrays.toString(points));
}
};
}
diff --git a/services/tests/servicestests/src/com/android/server/ambientcontext/AmbientContextManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/ambientcontext/AmbientContextManagerServiceTest.java
index 6bb494d3a92a..c75abf84fb89 100644
--- a/services/tests/servicestests/src/com/android/server/ambientcontext/AmbientContextManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ambientcontext/AmbientContextManagerServiceTest.java
@@ -21,8 +21,8 @@ import static com.google.common.truth.Truth.assertThat;
import android.app.PendingIntent;
import android.app.ambientcontext.AmbientContextEvent;
import android.app.ambientcontext.AmbientContextEventRequest;
+import android.app.ambientcontext.IAmbientContextObserver;
import android.content.Intent;
-import android.os.RemoteCallback;
import android.os.UserHandle;
import androidx.test.InstrumentationRegistry;
@@ -30,6 +30,8 @@ import androidx.test.filters.SmallTest;
import org.junit.Test;
+import java.util.List;
+
/**
* Unit test for {@link AmbientContextManagerService}.
* atest FrameworksServicesTests:AmbientContextManagerServiceTest
@@ -48,12 +50,22 @@ public class AmbientContextManagerServiceTest {
PendingIntent pendingIntent = PendingIntent.getBroadcast(
InstrumentationRegistry.getTargetContext(), 0,
intent, PendingIntent.FLAG_IMMUTABLE);
+ IAmbientContextObserver observer = new IAmbientContextObserver.Stub() {
+ @Override
+ public void onEvents(List<AmbientContextEvent> events) {
+ }
+
+ @Override
+ public void onRegistrationComplete(int statusCode) {
+ }
+ };
AmbientContextManagerService.ClientRequest clientRequest =
new AmbientContextManagerService.ClientRequest(USER_ID, request,
- pendingIntent, new RemoteCallback(result -> {}));
+ pendingIntent.getCreatorPackage(), observer);
assertThat(clientRequest.getRequest()).isEqualTo(request);
assertThat(clientRequest.getPackageName()).isEqualTo(SYSTEM_PACKAGE_NAME);
+ assertThat(clientRequest.getObserver()).isEqualTo(observer);
assertThat(clientRequest.hasUserId(USER_ID)).isTrue();
assertThat(clientRequest.hasUserId(-1)).isFalse();
assertThat(clientRequest.hasUserIdAndPackageName(USER_ID, SYSTEM_PACKAGE_NAME)).isTrue();
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
index e6acc904d811..dd7aeb72f7d2 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
@@ -40,8 +40,6 @@ import com.android.internal.logging.InstanceId;
import com.android.internal.statusbar.ISessionListener;
import com.android.internal.statusbar.IStatusBarService;
-import com.google.common.collect.ImmutableList;
-
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -89,33 +87,64 @@ public class BiometricContextProviderTest {
@Test
public void testIsAod() throws RemoteException {
- mListener.onDozeChanged(true);
+ mListener.onDozeChanged(true /* isDozing */, false /* isAwake */);
assertThat(mProvider.isAod()).isTrue();
- mListener.onDozeChanged(false);
+ mListener.onDozeChanged(false /* isDozing */, false /* isAwake */);
assertThat(mProvider.isAod()).isFalse();
when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(false);
- mListener.onDozeChanged(true);
+ mListener.onDozeChanged(true /* isDozing */, false /* isAwake */);
assertThat(mProvider.isAod()).isFalse();
- mListener.onDozeChanged(false);
+ mListener.onDozeChanged(false /* isDozing */, false /* isAwake */);
assertThat(mProvider.isAod()).isFalse();
}
@Test
+ public void testIsAwake() throws RemoteException {
+ mListener.onDozeChanged(false /* isDozing */, true /* isAwake */);
+ assertThat(mProvider.isAwake()).isTrue();
+ mListener.onDozeChanged(false /* isDozing */, false /* isAwake */);
+ assertThat(mProvider.isAwake()).isFalse();
+ mListener.onDozeChanged(true /* isDozing */, true /* isAwake */);
+ assertThat(mProvider.isAwake()).isTrue();
+ mListener.onDozeChanged(true /* isDozing */, false /* isAwake */);
+ assertThat(mProvider.isAwake()).isFalse();
+ }
+
+ @Test
public void testSubscribesToAod() throws RemoteException {
- final List<Boolean> expected = ImmutableList.of(true, false, true, true, false);
final List<Boolean> actual = new ArrayList<>();
mProvider.subscribe(mOpContext, ctx -> {
assertThat(ctx).isSameInstanceAs(mOpContext);
+ assertThat(mProvider.isAod()).isEqualTo(ctx.isAod);
+ assertThat(mProvider.isAwake()).isFalse();
actual.add(ctx.isAod);
});
- for (boolean v : expected) {
- mListener.onDozeChanged(v);
+ for (boolean v : List.of(true, false, true, true, false, false)) {
+ mListener.onDozeChanged(v /* isDozing */, false /* isAwake */);
+ }
+
+ assertThat(actual).containsExactly(true, false, true, false).inOrder();
+ }
+
+ @Test
+ public void testSubscribesToAwake() throws RemoteException {
+ final List<Boolean> actual = new ArrayList<>();
+
+ mProvider.subscribe(mOpContext, ctx -> {
+ assertThat(ctx).isSameInstanceAs(mOpContext);
+ assertThat(ctx.isAod).isFalse();
+ assertThat(mProvider.isAod()).isFalse();
+ actual.add(mProvider.isAwake());
+ });
+
+ for (boolean v : List.of(true, false, true, true, false, false)) {
+ mListener.onDozeChanged(false /* isDozing */, v /* isAwake */);
}
- assertThat(actual).containsExactlyElementsIn(expected).inOrder();
+ assertThat(actual).containsExactly(true, false, true, false).inOrder();
}
@Test
@@ -124,13 +153,13 @@ public class BiometricContextProviderTest {
mProvider.subscribe(mOpContext, emptyConsumer);
mProvider.unsubscribe(mOpContext);
- mListener.onDozeChanged(true);
+ mListener.onDozeChanged(true /* isDozing */, false /* isAwake */);
final Consumer<OperationContext> nonEmptyConsumer = mock(Consumer.class);
mProvider.subscribe(mOpContext, nonEmptyConsumer);
- mListener.onDozeChanged(false);
+ mListener.onDozeChanged(false /* isDozing */, false /* isAwake */);
mProvider.unsubscribe(mOpContext);
- mListener.onDozeChanged(true);
+ mListener.onDozeChanged(true /* isDozing */, false /* isAwake */);
verify(emptyConsumer, never()).accept(any());
verify(nonEmptyConsumer).accept(same(mOpContext));
@@ -171,7 +200,7 @@ public class BiometricContextProviderTest {
@Test
public void testUpdate() throws RemoteException {
- mListener.onDozeChanged(false);
+ mListener.onDozeChanged(false /* isDozing */, false /* isAwake */);
OperationContext context = mProvider.updateContext(mOpContext, false /* crypto */);
// default state when nothing has been set
@@ -186,7 +215,7 @@ public class BiometricContextProviderTest {
final int id = 40 + type;
final boolean aod = (type & 1) == 0;
- mListener.onDozeChanged(aod);
+ mListener.onDozeChanged(aod /* isDozing */, false /* isAwake */);
mSessionListener.onSessionStarted(type, InstanceId.fakeInstanceId(id));
context = mProvider.updateContext(mOpContext, false /* crypto */);
assertThat(context).isSameInstanceAs(mOpContext);
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
index 1ed52fc6a40a..dea4d4fb7c64 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
@@ -26,8 +26,8 @@ import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.same;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -96,6 +96,7 @@ public class FingerprintAuthenticationClientTest {
InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();
+
@Mock
private ISession mHal;
@Mock
@@ -213,21 +214,41 @@ public class FingerprintAuthenticationClientTest {
}
@Test
- public void luxProbeWhenFingerDown() throws RemoteException {
+ public void luxProbeWhenAwake() throws RemoteException {
+ when(mBiometricContext.isAwake()).thenReturn(false, true, false);
+ when(mBiometricContext.isAod()).thenReturn(false);
final FingerprintAuthenticationClient client = createClient();
client.start(mCallback);
- client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR);
- verify(mLuxProbe).enable();
+ verify(mHal).authenticateWithContext(eq(OP_ID), mOperationContextCaptor.capture());
+ OperationContext opContext = mOperationContextCaptor.getValue();
+ verify(mBiometricContext).subscribe(eq(opContext), mContextInjector.capture());
- client.onAcquired(2, 0);
+ mContextInjector.getValue().accept(opContext);
+ verify(mLuxProbe, never()).enable();
+
+ reset(mLuxProbe);
+ mContextInjector.getValue().accept(opContext);
+ verify(mLuxProbe).enable();
verify(mLuxProbe, never()).disable();
- client.onPointerUp();
+ mContextInjector.getValue().accept(opContext);
verify(mLuxProbe).disable();
+ }
- client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR);
- verify(mLuxProbe, times(2)).enable();
+ @Test
+ public void luxProbeDisabledOnAod() throws RemoteException {
+ when(mBiometricContext.isAwake()).thenReturn(false);
+ when(mBiometricContext.isAod()).thenReturn(true);
+ final FingerprintAuthenticationClient client = createClient();
+ client.start(mCallback);
+
+ verify(mHal).authenticateWithContext(eq(OP_ID), mOperationContextCaptor.capture());
+ OperationContext opContext = mOperationContextCaptor.getValue();
+ verify(mBiometricContext).subscribe(eq(opContext), mContextInjector.capture());
+
+ mContextInjector.getValue().accept(opContext);
+ verify(mLuxProbe, never()).enable();
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
index 97fe9ea41e3d..92e1f27ab624 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
@@ -64,6 +64,7 @@ import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import java.util.ArrayList;
import java.util.function.Consumer;
@Presubmit
@@ -196,21 +197,22 @@ public class FingerprintEnrollClientTest {
}
@Test
- public void luxProbeWhenFingerDown() throws RemoteException {
+ public void luxProbeWhenStarted() throws RemoteException {
final FingerprintEnrollClient client = createClient();
client.start(mCallback);
- client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR);
verify(mLuxProbe).enable();
client.onAcquired(2, 0);
+ client.onPointerUp();
+ client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR);
verify(mLuxProbe, never()).disable();
+ verify(mLuxProbe, never()).destroy();
- client.onPointerUp();
- verify(mLuxProbe).disable();
+ client.onEnrollResult(new Fingerprint("f", 30 /* fingerId */, 14 /* deviceId */),
+ 0 /* remaining */);
- client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR);
- verify(mLuxProbe, times(2)).enable();
+ verify(mLuxProbe).destroy();
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
index 261b882319d8..03ea6137074d 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -19,19 +19,16 @@ package com.android.server.display;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.anyFloat;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
-import android.content.res.TypedArray;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -55,16 +52,22 @@ public final class DisplayDeviceConfigTest {
private Resources mResources;
@Before
- public void setUp() {
+ public void setUp() throws IOException {
MockitoAnnotations.initMocks(this);
when(mContext.getResources()).thenReturn(mResources);
mockDeviceConfigs();
+ try {
+ Path tempFile = Files.createTempFile("display_config", ".tmp");
+ Files.write(tempFile, getContent().getBytes(StandardCharsets.UTF_8));
+ mDisplayDeviceConfig = new DisplayDeviceConfig(mContext);
+ mDisplayDeviceConfig.initFromFile(tempFile.toFile());
+ } catch (IOException e) {
+ throw new IOException("Failed to setup the display device config.", e);
+ }
}
@Test
- public void testConfigValuesFromDisplayConfig() throws IOException {
- setupDisplayDeviceConfigFromDisplayConfigFile();
-
+ public void testConfigValues() {
assertEquals(mDisplayDeviceConfig.getAmbientHorizonLong(), 5000);
assertEquals(mDisplayDeviceConfig.getAmbientHorizonShort(), 50);
assertEquals(mDisplayDeviceConfig.getBrightnessRampDecreaseMaxMillis(), 3000);
@@ -85,24 +88,10 @@ public final class DisplayDeviceConfigTest {
assertEquals(mDisplayDeviceConfig.getScreenDarkeningMinThreshold(), 0.002, 0.000001f);
assertEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLightDebounce(), 2000);
assertEquals(mDisplayDeviceConfig.getAutoBrightnessDarkeningLightDebounce(), 1000);
- assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(), new
- float[]{50.0f, 80.0f}, 0.0f);
- assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsNits(), new
- float[]{45.0f, 75.0f}, 0.0f);
- // Todo(brup): Add asserts for BrightnessThrottlingData, DensityMapping,
- // HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor.
- }
- @Test
- public void testConfigValuesFromDeviceConfig() {
- setupDisplayDeviceConfigFromDeviceConfigFile();
- assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(), new
- float[]{0.0f, 110.0f, 500.0f}, 0.0f);
- assertArrayEquals(mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsNits(), new
- float[]{2.0f, 200.0f, 600.0f}, 0.0f);
// Todo(brup): Add asserts for BrightnessThrottlingData, DensityMapping,
// HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor.
-
+ // Also add test for the case where optional display configs are null
}
private String getContent() {
@@ -125,16 +114,6 @@ public final class DisplayDeviceConfigTest {
+ "<autoBrightness>\n"
+ "<brighteningLightDebounceMillis>2000</brighteningLightDebounceMillis>\n"
+ "<darkeningLightDebounceMillis>1000</darkeningLightDebounceMillis>\n"
- + "<displayBrightnessMapping>\n"
- + "<displayBrightnessPoint>\n"
- + "<lux>50</lux>\n"
- + "<nits>45</nits>\n"
- + "</displayBrightnessPoint>\n"
- + "<displayBrightnessPoint>\n"
- + "<lux>80</lux>\n"
- + "<nits>75</nits>\n"
- + "</displayBrightnessPoint>\n"
- + "</displayBrightnessMapping>\n"
+ "</autoBrightness>\n"
+ "<highBrightnessMode enabled=\"true\">\n"
+ "<transitionPoint>0.62</transitionPoint>\n"
@@ -206,64 +185,4 @@ public final class DisplayDeviceConfigTest {
when(mResources.getFloat(com.android.internal.R.dimen
.config_screenBrightnessSettingMaximumFloat)).thenReturn(1.0f);
}
-
- private void setupDisplayDeviceConfigFromDisplayConfigFile() throws IOException {
- Path tempFile = Files.createTempFile("display_config", ".tmp");
- Files.write(tempFile, getContent().getBytes(StandardCharsets.UTF_8));
- mDisplayDeviceConfig = new DisplayDeviceConfig(mContext);
- mDisplayDeviceConfig.initFromFile(tempFile.toFile());
- }
-
- private void setupDisplayDeviceConfigFromDeviceConfigFile() {
- TypedArray screenBrightnessNits = createFloatTypedArray(new float[]{2.0f, 250.0f, 650.0f});
- when(mResources.obtainTypedArray(
- com.android.internal.R.array.config_screenBrightnessNits))
- .thenReturn(screenBrightnessNits);
- TypedArray screenBrightnessBacklight = createFloatTypedArray(new
- float[]{0.0f, 120.0f, 255.0f});
- when(mResources.obtainTypedArray(
- com.android.internal.R.array.config_screenBrightnessBacklight))
- .thenReturn(screenBrightnessBacklight);
- when(mResources.getIntArray(com.android.internal.R.array
- .config_screenBrightnessBacklight)).thenReturn(new int[]{0, 120, 255});
-
- when(mResources.getIntArray(com.android.internal.R.array
- .config_autoBrightnessLevels)).thenReturn(new int[]{30, 80});
- when(mResources.getIntArray(com.android.internal.R.array
- .config_autoBrightnessDisplayValuesNits)).thenReturn(new int[]{25, 55});
-
- TypedArray screenBrightnessLevelNits = createFloatTypedArray(new
- float[]{2.0f, 200.0f, 600.0f});
- when(mResources.obtainTypedArray(
- com.android.internal.R.array.config_autoBrightnessDisplayValuesNits))
- .thenReturn(screenBrightnessLevelNits);
- TypedArray screenBrightnessLevelLux = createFloatTypedArray(new
- float[]{0.0f, 110.0f, 500.0f});
- when(mResources.obtainTypedArray(
- com.android.internal.R.array.config_autoBrightnessLevels))
- .thenReturn(screenBrightnessLevelLux);
-
- mDisplayDeviceConfig = DisplayDeviceConfig.create(mContext, true);
-
- }
-
- private TypedArray createFloatTypedArray(float[] vals) {
- TypedArray mockArray = mock(TypedArray.class);
- when(mockArray.length()).thenAnswer(invocation -> {
- return vals.length;
- });
- when(mockArray.getFloat(anyInt(), anyFloat())).thenAnswer(invocation -> {
- final float def = (float) invocation.getArguments()[1];
- if (vals == null) {
- return def;
- }
- int idx = (int) invocation.getArguments()[0];
- if (idx >= 0 && idx < vals.length) {
- return vals[idx];
- } else {
- return def;
- }
- });
- return mockArray;
- }
}
diff --git a/services/tests/servicestests/src/com/android/server/logcat/LogcatManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/logcat/LogcatManagerServiceTest.java
index f33001774263..6a27f391ac5b 100644
--- a/services/tests/servicestests/src/com/android/server/logcat/LogcatManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/logcat/LogcatManagerServiceTest.java
@@ -16,6 +16,8 @@
package com.android.server.logcat;
+import static android.os.Process.INVALID_UID;
+
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -28,6 +30,7 @@ import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.content.ContextWrapper;
+import android.content.pm.PackageManager;
import android.os.ILogd;
import android.os.Looper;
import android.os.UserHandle;
@@ -69,6 +72,8 @@ public class LogcatManagerServiceTest {
@Mock
private ActivityManagerInternal mActivityManagerInternalMock;
@Mock
+ private PackageManager mPackageManagerMock;
+ @Mock
private ILogd mLogdMock;
private LogcatManagerService mService;
@@ -81,10 +86,17 @@ public class LogcatManagerServiceTest {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternalMock);
+ when(mActivityManagerInternalMock.getInstrumentationSourceUid(anyInt()))
+ .thenReturn(INVALID_UID);
+
mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
mClock = new OffsettableClock.Stopped();
mTestLooper = new TestLooper(mClock::now);
-
+ when(mContextSpy.getPackageManager()).thenReturn(mPackageManagerMock);
+ when(mPackageManagerMock.getPackagesForUid(APP1_UID)).thenReturn(
+ new String[]{APP1_PACKAGE_NAME});
+ when(mPackageManagerMock.getPackagesForUid(APP2_UID)).thenReturn(
+ new String[]{APP2_PACKAGE_NAME});
when(mActivityManagerInternalMock.getPackageNameByPid(APP1_PID)).thenReturn(
APP1_PACKAGE_NAME);
when(mActivityManagerInternalMock.getPackageNameByPid(APP2_PID)).thenReturn(
@@ -136,6 +148,20 @@ public class LogcatManagerServiceTest {
}
@Test
+ public void test_RequestFromBackground_ApprovedIfInstrumented() throws Exception {
+ when(mActivityManagerInternalMock.getInstrumentationSourceUid(APP1_UID))
+ .thenReturn(APP1_UID);
+ when(mActivityManagerInternalMock.getUidProcessState(APP1_UID)).thenReturn(
+ ActivityManager.PROCESS_STATE_RECEIVER);
+ mService.getBinderService().startThread(APP1_UID, APP1_GID, APP1_PID, FD1);
+ mTestLooper.dispatchAll();
+
+ verify(mLogdMock).approve(APP1_UID, APP1_GID, APP1_PID, FD1);
+ verify(mLogdMock, never()).decline(APP1_UID, APP1_GID, APP1_PID, FD1);
+ verify(mContextSpy, never()).startActivityAsUser(any(), any());
+ }
+
+ @Test
public void test_RequestFromForegroundService_DeclinedWithoutPrompt() throws Exception {
when(mActivityManagerInternalMock.getUidProcessState(APP1_UID)).thenReturn(
ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
index 5c9348525861..047fcd6ed108 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsHistoryTest.java
@@ -16,11 +16,17 @@
package com.android.server.power.stats;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
import android.content.Context;
+import android.os.BatteryManager;
+import android.os.BatteryStats;
+import android.os.BatteryStats.MeasuredEnergyDetails;
import android.os.Parcel;
import android.util.Log;
@@ -28,15 +34,19 @@ import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.os.BatteryStatsHistory;
+import com.android.internal.os.BatteryStatsHistoryIterator;
import com.android.internal.os.Clock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.io.File;
import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -51,6 +61,9 @@ public class BatteryStatsHistoryTest {
private File mSystemDir;
private File mHistoryDir;
private final Clock mClock = new MockClock();
+ private BatteryStatsHistory mHistory;
+ @Mock
+ private BatteryStatsHistory.HistoryStepDetailsCalculator mStepDetailsCalculator;
@Before
public void setUp() {
@@ -65,55 +78,56 @@ public class BatteryStatsHistoryTest {
}
}
mHistoryDir.delete();
+ mHistory = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024,
+ mStepDetailsCalculator, mClock);
+
+ when(mStepDetailsCalculator.getHistoryStepDetails())
+ .thenReturn(new BatteryStats.HistoryStepDetails());
}
@Test
public void testConstruct() {
- BatteryStatsHistory history = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024,
- null, mClock);
- createActiveFile(history);
- verifyFileNumbers(history, Arrays.asList(0));
- verifyActiveFile(history, "0.bin");
+ createActiveFile(mHistory);
+ verifyFileNumbers(mHistory, Arrays.asList(0));
+ verifyActiveFile(mHistory, "0.bin");
}
@Test
public void testStartNextFile() {
- BatteryStatsHistory history = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024,
- null, mClock);
List<Integer> fileList = new ArrayList<>();
fileList.add(0);
- createActiveFile(history);
+ createActiveFile(mHistory);
// create file 1 to 31.
for (int i = 1; i < 32; i++) {
fileList.add(i);
- history.startNextFile();
- createActiveFile(history);
- verifyFileNumbers(history, fileList);
- verifyActiveFile(history, i + ".bin");
+ mHistory.startNextFile();
+ createActiveFile(mHistory);
+ verifyFileNumbers(mHistory, fileList);
+ verifyActiveFile(mHistory, i + ".bin");
}
// create file 32
- history.startNextFile();
- createActiveFile(history);
+ mHistory.startNextFile();
+ createActiveFile(mHistory);
fileList.add(32);
fileList.remove(0);
// verify file 0 is deleted.
verifyFileDeleted("0.bin");
- verifyFileNumbers(history, fileList);
- verifyActiveFile(history, "32.bin");
+ verifyFileNumbers(mHistory, fileList);
+ verifyActiveFile(mHistory, "32.bin");
// create file 33
- history.startNextFile();
- createActiveFile(history);
+ mHistory.startNextFile();
+ createActiveFile(mHistory);
// verify file 1 is deleted
fileList.add(33);
fileList.remove(0);
verifyFileDeleted("1.bin");
- verifyFileNumbers(history, fileList);
- verifyActiveFile(history, "33.bin");
+ verifyFileNumbers(mHistory, fileList);
+ verifyActiveFile(mHistory, "33.bin");
- assertEquals(0, history.getHistoryUsedSize());
+ assertEquals(0, mHistory.getHistoryUsedSize());
// create a new BatteryStatsHistory object, it will pick up existing history files.
BatteryStatsHistory history2 = new BatteryStatsHistory(mHistoryBuffer, mSystemDir, 32, 1024,
@@ -168,4 +182,74 @@ public class BatteryStatsHistoryTest {
Log.e(TAG, "Error creating history file " + file.getPath(), e);
}
}
+
+ @Test
+ public void testRecordMeasuredEnergyDetails() {
+ mHistory.forceRecordAllHistory();
+ mHistory.startRecordingHistory(0, 0, /* reset */ true);
+ mHistory.setBatteryState(true /* charging */, BatteryManager.BATTERY_STATUS_CHARGING, 80,
+ 1234);
+
+ MeasuredEnergyDetails details = new MeasuredEnergyDetails();
+ MeasuredEnergyDetails.EnergyConsumer consumer1 =
+ new MeasuredEnergyDetails.EnergyConsumer();
+ consumer1.type = 42;
+ consumer1.ordinal = 0;
+ consumer1.name = "A";
+
+ MeasuredEnergyDetails.EnergyConsumer consumer2 =
+ new MeasuredEnergyDetails.EnergyConsumer();
+ consumer2.type = 777;
+ consumer2.ordinal = 0;
+ consumer2.name = "B/0";
+
+ MeasuredEnergyDetails.EnergyConsumer consumer3 =
+ new MeasuredEnergyDetails.EnergyConsumer();
+ consumer3.type = 777;
+ consumer3.ordinal = 1;
+ consumer3.name = "B/1";
+
+ MeasuredEnergyDetails.EnergyConsumer consumer4 =
+ new MeasuredEnergyDetails.EnergyConsumer();
+ consumer4.type = 314;
+ consumer4.ordinal = 1;
+ consumer4.name = "C";
+
+ details.consumers =
+ new MeasuredEnergyDetails.EnergyConsumer[]{consumer1, consumer2, consumer3,
+ consumer4};
+ details.chargeUC = new long[details.consumers.length];
+ for (int i = 0; i < details.chargeUC.length; i++) {
+ details.chargeUC[i] = 100L * i;
+ }
+ details.chargeUC[3] = BatteryStats.POWER_DATA_UNAVAILABLE;
+
+ mHistory.recordMeasuredEnergyDetails(200, 200, details);
+
+ BatteryStatsHistoryIterator iterator = mHistory.iterate();
+ BatteryStats.HistoryItem item = new BatteryStats.HistoryItem();
+ assertThat(iterator.next(item)).isTrue(); // First item contains current time only
+
+ assertThat(iterator.next(item)).isTrue();
+
+ String dump = toString(item, /* checkin */ false);
+ assertThat(dump).contains("+200ms");
+ assertThat(dump).contains("ext=E");
+ assertThat(dump).contains("Energy: A=0 B/0=100 B/1=200");
+ assertThat(dump).doesNotContain("C=");
+
+ String checkin = toString(item, /* checkin */ true);
+ assertThat(checkin).contains("XE");
+ assertThat(checkin).contains("A=0,B/0=100,B/1=200");
+ assertThat(checkin).doesNotContain("C=");
+ }
+
+ private String toString(BatteryStats.HistoryItem item, boolean checkin) {
+ BatteryStats.HistoryPrinter printer = new BatteryStats.HistoryPrinter();
+ StringWriter writer = new StringWriter();
+ PrintWriter pw = new PrintWriter(writer);
+ printer.printNextItem(pw, item, 0, checkin, /* verbose */ true);
+ pw.flush();
+ return writer.toString();
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/MeasuredEnergySnapshotTest.java b/services/tests/servicestests/src/com/android/server/power/stats/MeasuredEnergySnapshotTest.java
index 8a0f9247dffb..122f7eb86ac8 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/MeasuredEnergySnapshotTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/MeasuredEnergySnapshotTest.java
@@ -26,6 +26,7 @@ import android.hardware.power.stats.EnergyConsumer;
import android.hardware.power.stats.EnergyConsumerAttribution;
import android.hardware.power.stats.EnergyConsumerResult;
import android.hardware.power.stats.EnergyConsumerType;
+import android.os.BatteryStats;
import android.util.SparseArray;
import android.util.SparseLongArray;
@@ -236,6 +237,17 @@ public final class MeasuredEnergySnapshotTest {
assertEquals(0, snapshot.getOtherOrdinalNames().length);
}
+ @Test
+ public void getMeasuredEnergyDetails() {
+ final MeasuredEnergySnapshot snapshot = new MeasuredEnergySnapshot(ALL_ID_CONSUMER_MAP);
+ snapshot.updateAndGetDelta(RESULTS_0, VOLTAGE_0);
+ MeasuredEnergyDeltaData delta = snapshot.updateAndGetDelta(RESULTS_1, VOLTAGE_1);
+ BatteryStats.MeasuredEnergyDetails details = snapshot.getMeasuredEnergyDetails(delta);
+ assertThat(details.consumers).hasLength(4);
+ assertThat(details.chargeUC).isEqualTo(new long[]{2667, 3200000, 0, 0});
+ assertThat(details.toString()).isEqualTo("DISPLAY=2667 HPU=3200000 GPU=0 IPU &_=0");
+ }
+
private static EnergyConsumer createEnergyConsumer(int id, int ord, byte type, String name) {
final EnergyConsumer ec = new EnergyConsumer();
ec.id = id;
diff --git a/services/tests/wmtests/src/com/android/server/policy/CombinationKeyTests.java b/services/tests/wmtests/src/com/android/server/policy/CombinationKeyTests.java
new file mode 100644
index 000000000000..62875e5863b3
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/policy/CombinationKeyTests.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.policy;
+
+import static android.view.KeyEvent.KEYCODE_POWER;
+import static android.view.KeyEvent.KEYCODE_VOLUME_DOWN;
+import static android.view.KeyEvent.KEYCODE_VOLUME_UP;
+
+import static com.android.server.policy.PhoneWindowManager.POWER_VOLUME_UP_BEHAVIOR_GLOBAL_ACTIONS;
+import static com.android.server.policy.PhoneWindowManager.POWER_VOLUME_UP_BEHAVIOR_MUTE;
+
+import android.view.ViewConfiguration;
+
+import androidx.test.filters.MediumTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test class for combination key shortcuts.
+ *
+ * Build/Install/Run:
+ * atest WmTests:CombinationKeyTests
+ */
+@MediumTest
+@RunWith(AndroidJUnit4.class)
+public class CombinationKeyTests extends ShortcutKeyTestBase {
+ private static final long A11Y_KEY_HOLD_MILLIS = 3500;
+
+ /**
+ * Power-VolDown to take screenshot.
+ */
+ @Test
+ public void testPowerVolumeDown() {
+ sendKeyCombination(new int[]{KEYCODE_POWER, KEYCODE_VOLUME_DOWN},
+ ViewConfiguration.get(mContext).getScreenshotChordKeyTimeout());
+ mPhoneWindowManager.assertTakeScreenshotCalled();
+ }
+
+ /**
+ * Power-VolUp to show global actions or mute audio. (Phone default behavior)
+ */
+ @Test
+ public void testPowerVolumeUp() {
+ // Show global actions.
+ mPhoneWindowManager.overridePowerVolumeUp(POWER_VOLUME_UP_BEHAVIOR_GLOBAL_ACTIONS);
+ sendKeyCombination(new int[]{KEYCODE_POWER, KEYCODE_VOLUME_UP}, 0);
+ mPhoneWindowManager.assertShowGlobalActionsCalled();
+
+ // Mute audio (hold over 100ms).
+ mPhoneWindowManager.overridePowerVolumeUp(POWER_VOLUME_UP_BEHAVIOR_MUTE);
+ sendKeyCombination(new int[]{KEYCODE_POWER, KEYCODE_VOLUME_UP}, 100);
+ mPhoneWindowManager.assertVolumeMute();
+ }
+
+ /**
+ * VolDown-VolUp and hold 3 secs to enable accessibility service.
+ */
+ @Test
+ public void testVolumeDownVolumeUp() {
+ sendKeyCombination(new int[]{KEYCODE_VOLUME_DOWN, KEYCODE_VOLUME_UP}, A11Y_KEY_HOLD_MILLIS);
+ mPhoneWindowManager.assertAccessibilityKeychordCalled();
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/policy/KeyCombinationTests.java b/services/tests/wmtests/src/com/android/server/policy/KeyCombinationManagerTests.java
index cf571815b4cb..4c698571db16 100644
--- a/services/tests/wmtests/src/com/android/server/policy/KeyCombinationTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/KeyCombinationManagerTests.java
@@ -43,11 +43,11 @@ import java.util.concurrent.TimeUnit;
* Test class for {@link KeyCombinationManager}.
*
* Build/Install/Run:
- * atest KeyCombinationTests
+ * atest KeyCombinationManagerTests
*/
@SmallTest
-public class KeyCombinationTests {
+public class KeyCombinationManagerTests {
private KeyCombinationManager mKeyCombinationManager;
private final CountDownLatch mAction1Triggered = new CountDownLatch(1);
@@ -228,4 +228,4 @@ public class KeyCombinationTests {
mKeyCombinationManager.interceptKey(firstKeyDown, true);
assertTrue(mKeyCombinationManager.getKeyInterceptTimeout(KEYCODE_VOLUME_UP) > eventTime);
}
-} \ No newline at end of file
+}
diff --git a/services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java
new file mode 100644
index 000000000000..49af2c1dc681
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/policy/PowerKeyGestureTests.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.policy;
+
+import static android.view.KeyEvent.KEYCODE_POWER;
+import static android.view.KeyEvent.KEYCODE_VOLUME_UP;
+
+import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_ASSISTANT;
+import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_GLOBAL_ACTIONS;
+
+import android.provider.Settings;
+import android.view.Display;
+
+import org.junit.Test;
+
+/**
+ * Test class for power key gesture.
+ *
+ * Build/Install/Run:
+ * atest WmTests:PowerKeyGestureTests
+ */
+public class PowerKeyGestureTests extends ShortcutKeyTestBase {
+ /**
+ * Power single press to turn screen on/off.
+ */
+ @Test
+ public void testPowerSinglePress() {
+ sendKey(KEYCODE_POWER);
+ mPhoneWindowManager.assertPowerSleep();
+
+ // turn screen on when begin from non-interactive.
+ mPhoneWindowManager.overrideDisplayState(Display.STATE_OFF);
+ sendKey(KEYCODE_POWER);
+ mPhoneWindowManager.assertPowerWakeUp();
+ mPhoneWindowManager.assertNoPowerSleep();
+ }
+
+ /**
+ * Power double press to trigger camera.
+ */
+ @Test
+ public void testPowerDoublePress() {
+ sendKey(KEYCODE_POWER);
+ sendKey(KEYCODE_POWER);
+ mPhoneWindowManager.assertCameraLaunch();
+ }
+
+ /**
+ * Power long press to show assistant or global actions.
+ */
+ @Test
+ public void testPowerLongPress() {
+ // Show assistant.
+ mPhoneWindowManager.overrideLongPressOnPower(LONG_PRESS_POWER_ASSISTANT);
+ sendKey(KEYCODE_POWER, true);
+ mPhoneWindowManager.assertAssistLaunch();
+
+ // Show global actions.
+ mPhoneWindowManager.overrideLongPressOnPower(LONG_PRESS_POWER_GLOBAL_ACTIONS);
+ sendKey(KEYCODE_POWER, true);
+ mPhoneWindowManager.assertShowGlobalActionsCalled();
+ }
+
+ /**
+ * Ignore power press if combination key already triggered.
+ */
+ @Test
+ public void testIgnoreSinglePressWhenCombinationKeyTriggered() {
+ sendKeyCombination(new int[]{KEYCODE_POWER, KEYCODE_VOLUME_UP}, 0);
+ mPhoneWindowManager.assertNoPowerSleep();
+ }
+
+ /**
+ * When a phone call is active, and INCALL_POWER_BUTTON_BEHAVIOR_HANGUP is enabled, then the
+ * power button should only stop phone call. The screen should not be turned off (power sleep
+ * should not be activated).
+ */
+ @Test
+ public void testIgnoreSinglePressWhenEndCall() {
+ mPhoneWindowManager.overrideIncallPowerBehavior(
+ Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP);
+ sendKey(KEYCODE_POWER);
+ mPhoneWindowManager.assertNoPowerSleep();
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
new file mode 100644
index 000000000000..6368f4748b26
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/policy/ShortcutKeyTestBase.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.policy;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.KeyEvent.KEYCODE_ALT_LEFT;
+import static android.view.KeyEvent.KEYCODE_ALT_RIGHT;
+import static android.view.KeyEvent.KEYCODE_CTRL_LEFT;
+import static android.view.KeyEvent.KEYCODE_CTRL_RIGHT;
+import static android.view.KeyEvent.KEYCODE_META_LEFT;
+import static android.view.KeyEvent.KEYCODE_META_RIGHT;
+import static android.view.KeyEvent.KEYCODE_SHIFT_LEFT;
+import static android.view.KeyEvent.KEYCODE_SHIFT_RIGHT;
+import static android.view.KeyEvent.META_ALT_LEFT_ON;
+import static android.view.KeyEvent.META_ALT_ON;
+import static android.view.KeyEvent.META_ALT_RIGHT_ON;
+import static android.view.KeyEvent.META_CTRL_LEFT_ON;
+import static android.view.KeyEvent.META_CTRL_ON;
+import static android.view.KeyEvent.META_CTRL_RIGHT_ON;
+import static android.view.KeyEvent.META_META_LEFT_ON;
+import static android.view.KeyEvent.META_META_ON;
+import static android.view.KeyEvent.META_META_RIGHT_ON;
+import static android.view.KeyEvent.META_SHIFT_LEFT_ON;
+import static android.view.KeyEvent.META_SHIFT_ON;
+import static android.view.KeyEvent.META_SHIFT_RIGHT_ON;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.android.server.policy.WindowManagerPolicy.ACTION_PASS_TO_USER;
+
+import static java.util.Collections.unmodifiableMap;
+
+import android.content.Context;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.util.ArrayMap;
+import android.view.InputDevice;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.ViewConfiguration;
+
+import org.junit.After;
+import org.junit.Before;
+
+import java.util.Map;
+
+class ShortcutKeyTestBase {
+ TestPhoneWindowManager mPhoneWindowManager;
+ final Context mContext = getInstrumentation().getTargetContext();
+
+ /** Modifier key to meta state */
+ private static final Map<Integer, Integer> MODIFIER;
+ static {
+ final Map<Integer, Integer> map = new ArrayMap<>();
+ map.put(KEYCODE_CTRL_LEFT, META_CTRL_LEFT_ON | META_CTRL_ON);
+ map.put(KEYCODE_CTRL_RIGHT, META_CTRL_RIGHT_ON | META_CTRL_ON);
+ map.put(KEYCODE_ALT_LEFT, META_ALT_LEFT_ON | META_ALT_ON);
+ map.put(KEYCODE_ALT_RIGHT, META_ALT_RIGHT_ON | META_ALT_ON);
+ map.put(KEYCODE_SHIFT_LEFT, META_SHIFT_LEFT_ON | META_SHIFT_ON);
+ map.put(KEYCODE_SHIFT_RIGHT, META_SHIFT_RIGHT_ON | META_SHIFT_ON);
+ map.put(KEYCODE_META_LEFT, META_META_LEFT_ON | META_META_ON);
+ map.put(KEYCODE_META_RIGHT, META_META_RIGHT_ON | META_META_ON);
+
+ MODIFIER = unmodifiableMap(map);
+ }
+
+ @Before
+ public void setUp() {
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+
+ mPhoneWindowManager = new TestPhoneWindowManager(mContext);
+ }
+
+ @After
+ public void tearDown() {
+ mPhoneWindowManager.tearDown();
+ }
+
+ void sendKeyCombination(int[] keyCodes, long duration) {
+ final long downTime = SystemClock.uptimeMillis();
+ final int count = keyCodes.length;
+ final KeyEvent[] events = new KeyEvent[count];
+ int metaState = 0;
+ for (int i = 0; i < count; i++) {
+ final int keyCode = keyCodes[i];
+ final KeyEvent event = new KeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode,
+ 0 /*repeat*/, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/,
+ 0 /*flags*/, InputDevice.SOURCE_KEYBOARD);
+ event.setDisplayId(DEFAULT_DISPLAY);
+ events[i] = event;
+ // The order is important here, metaState could be updated and applied to the next key.
+ metaState |= MODIFIER.getOrDefault(keyCode, 0);
+ }
+
+ for (KeyEvent event: events) {
+ interceptKey(event);
+ }
+
+ try {
+ Thread.sleep(duration);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+
+ for (KeyEvent event: events) {
+ final long eventTime = SystemClock.uptimeMillis();
+ final int keyCode = event.getKeyCode();
+ final KeyEvent upEvent = new KeyEvent(downTime, eventTime, KeyEvent.ACTION_UP, keyCode,
+ 0, metaState, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/, 0 /*flags*/,
+ InputDevice.SOURCE_KEYBOARD);
+ interceptKey(upEvent);
+ metaState &= ~MODIFIER.getOrDefault(keyCode, 0);
+ }
+ }
+
+ void sendKey(int keyCode) {
+ sendKey(keyCode, false);
+ }
+
+ void sendKey(int keyCode, boolean longPress) {
+ final long downTime = SystemClock.uptimeMillis();
+ final KeyEvent event = new KeyEvent(downTime, downTime, KeyEvent.ACTION_DOWN, keyCode,
+ 0 /*repeat*/, 0 /*metaState*/, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/,
+ 0 /*flags*/, InputDevice.SOURCE_KEYBOARD);
+ event.setDisplayId(DEFAULT_DISPLAY);
+ interceptKey(event);
+
+ if (longPress) {
+ final long nextDownTime = downTime + ViewConfiguration.getLongPressTimeout();
+ final KeyEvent nextDownevent = new KeyEvent(downTime, nextDownTime,
+ KeyEvent.ACTION_DOWN, keyCode, 1 /*repeat*/, 0 /*metaState*/,
+ KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/,
+ KeyEvent.FLAG_LONG_PRESS /*flags*/, InputDevice.SOURCE_KEYBOARD);
+ interceptKey(nextDownevent);
+ }
+
+ final long eventTime = longPress
+ ? SystemClock.uptimeMillis() + ViewConfiguration.getLongPressTimeout()
+ : SystemClock.uptimeMillis();
+ final KeyEvent upEvent = new KeyEvent(downTime, eventTime, KeyEvent.ACTION_UP, keyCode,
+ 0 /*repeat*/, 0 /*metaState*/, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /*scancode*/,
+ 0 /*flags*/, InputDevice.SOURCE_KEYBOARD);
+ interceptKey(upEvent);
+ }
+
+ private void interceptKey(KeyEvent keyEvent) {
+ int actions = mPhoneWindowManager.interceptKeyBeforeQueueing(keyEvent);
+ if ((actions & ACTION_PASS_TO_USER) != 0) {
+ if (0 == mPhoneWindowManager.interceptKeyBeforeDispatching(keyEvent)) {
+ mPhoneWindowManager.dispatchUnhandledKey(keyEvent);
+ }
+ }
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
new file mode 100644
index 000000000000..ee11ac8caf53
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.policy;
+
+import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.STATE_ON;
+import static android.view.WindowManagerPolicyConstants.FLAG_INTERACTIVE;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyLong;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
+import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_ASSISTANT;
+import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_GLOBAL_ACTIONS;
+import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_GO_TO_VOICE_ASSIST;
+import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_NOTHING;
+import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_SHUT_OFF;
+import static com.android.server.policy.PhoneWindowManager.LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
+import static com.android.server.policy.PhoneWindowManager.POWER_VOLUME_UP_BEHAVIOR_MUTE;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.withSettings;
+
+import android.app.ActivityManagerInternal;
+import android.app.AppOpsManager;
+import android.app.NotificationManager;
+import android.app.SearchManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManagerInternal;
+import android.hardware.input.InputManagerInternal;
+import android.media.AudioManagerInternal;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.PowerManager;
+import android.os.PowerManagerInternal;
+import android.os.Vibrator;
+import android.service.dreams.DreamManagerInternal;
+import android.telecom.TelecomManager;
+import android.view.Display;
+import android.view.KeyEvent;
+import android.view.autofill.AutofillManagerInternal;
+
+import com.android.dx.mockito.inline.extended.StaticMockitoSession;
+import com.android.internal.accessibility.AccessibilityShortcutController;
+import com.android.server.GestureLauncherService;
+import com.android.server.LocalServices;
+import com.android.server.vr.VrManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
+import com.android.server.wm.DisplayPolicy;
+import com.android.server.wm.DisplayRotation;
+import com.android.server.wm.WindowManagerInternal;
+
+import org.mockito.Mock;
+import org.mockito.MockSettings;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.function.Supplier;
+
+class TestPhoneWindowManager {
+ private static final long SHORTCUT_KEY_DELAY_MILLIS = 150;
+
+ private PhoneWindowManager mPhoneWindowManager;
+ private Context mContext;
+
+ @Mock private WindowManagerInternal mWindowManagerInternal;
+ @Mock private ActivityManagerInternal mActivityManagerInternal;
+ @Mock private ActivityTaskManagerInternal mActivityTaskManagerInternal;
+ @Mock private InputManagerInternal mInputManagerInternal;
+ @Mock private DreamManagerInternal mDreamManagerInternal;
+ @Mock private PowerManagerInternal mPowerManagerInternal;
+ @Mock private DisplayManagerInternal mDisplayManagerInternal;
+ @Mock private AppOpsManager mAppOpsManager;
+ @Mock private DisplayManager mDisplayManager;
+ @Mock private PackageManager mPackageManager;
+ @Mock private TelecomManager mTelecomManager;
+ @Mock private NotificationManager mNotificationManager;
+ @Mock private Vibrator mVibrator;
+ @Mock private PowerManager mPowerManager;
+ @Mock private WindowManagerPolicy.WindowManagerFuncs mWindowManagerFuncsImpl;
+ @Mock private AudioManagerInternal mAudioManagerInternal;
+ @Mock private SearchManager mSearchManager;
+
+ @Mock private Display mDisplay;
+ @Mock private DisplayRotation mDisplayRotation;
+ @Mock private DisplayPolicy mDisplayPolicy;
+ @Mock private WindowManagerPolicy.ScreenOnListener mScreenOnListener;
+ @Mock private GestureLauncherService mGestureLauncherService;
+ @Mock private GlobalActions mGlobalActions;
+ @Mock private AccessibilityShortcutController mAccessibilityShortcutController;
+
+ private StaticMockitoSession mMockitoSession;
+ private HandlerThread mHandlerThread;
+ private Handler mHandler;
+
+ private class TestInjector extends PhoneWindowManager.Injector {
+ TestInjector(Context context, WindowManagerPolicy.WindowManagerFuncs funcs) {
+ super(context, funcs);
+ }
+
+ AccessibilityShortcutController getAccessibilityShortcutController(
+ Context context, Handler handler, int initialUserId) {
+ return mAccessibilityShortcutController;
+ }
+
+ Supplier<GlobalActions> getGlobalActionsFactory() {
+ return () -> mGlobalActions;
+ }
+ }
+
+ TestPhoneWindowManager(Context context) {
+ MockitoAnnotations.initMocks(this);
+ mHandlerThread = new HandlerThread("fake window manager");
+ mHandlerThread.start();
+ mHandler = new Handler(mHandlerThread.getLooper());
+ mHandler.runWithScissors(()-> setUp(context), 0 /* timeout */);
+ }
+
+ private void setUp(Context context) {
+ mPhoneWindowManager = spy(new PhoneWindowManager());
+ mContext = spy(context);
+
+ // Use stubOnly() to reduce memory usage if it doesn't need verification.
+ final MockSettings spyStubOnly = withSettings().stubOnly()
+ .defaultAnswer(CALLS_REAL_METHODS);
+ // Return mocked services: LocalServices.getService
+ mMockitoSession = mockitoSession()
+ .mockStatic(LocalServices.class, spyStubOnly)
+ .startMocking();
+
+ doReturn(mWindowManagerInternal).when(
+ () -> LocalServices.getService(eq(WindowManagerInternal.class)));
+ doReturn(mActivityManagerInternal).when(
+ () -> LocalServices.getService(eq(ActivityManagerInternal.class)));
+ doReturn(mActivityTaskManagerInternal).when(
+ () -> LocalServices.getService(eq(ActivityTaskManagerInternal.class)));
+ doReturn(mInputManagerInternal).when(
+ () -> LocalServices.getService(eq(InputManagerInternal.class)));
+ doReturn(mDreamManagerInternal).when(
+ () -> LocalServices.getService(eq(DreamManagerInternal.class)));
+ doReturn(mPowerManagerInternal).when(
+ () -> LocalServices.getService(eq(PowerManagerInternal.class)));
+ doReturn(mDisplayManagerInternal).when(
+ () -> LocalServices.getService(eq(DisplayManagerInternal.class)));
+ doReturn(mGestureLauncherService).when(
+ () -> LocalServices.getService(eq(GestureLauncherService.class)));
+ doReturn(null).when(() -> LocalServices.getService(eq(VrManagerInternal.class)));
+ doReturn(null).when(() -> LocalServices.getService(eq(AutofillManagerInternal.class)));
+
+ doReturn(mAppOpsManager).when(mContext).getSystemService(eq(AppOpsManager.class));
+ doReturn(mDisplayManager).when(mContext).getSystemService(eq(DisplayManager.class));
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(false).when(mPackageManager).hasSystemFeature(any());
+ try {
+ doThrow(new PackageManager.NameNotFoundException("test")).when(mPackageManager)
+ .getActivityInfo(any(), anyInt());
+ doReturn(new String[] { "testPackage" }).when(mPackageManager)
+ .canonicalToCurrentPackageNames(any());
+ } catch (PackageManager.NameNotFoundException ignored) { }
+
+ doReturn(mTelecomManager).when(mContext).getSystemService(eq(Context.TELECOM_SERVICE));
+ doReturn(mNotificationManager).when(mContext)
+ .getSystemService(eq(NotificationManager.class));
+ doReturn(mVibrator).when(mContext).getSystemService(eq(Context.VIBRATOR_SERVICE));
+
+ final PowerManager.WakeLock wakeLock = mock(PowerManager.WakeLock.class);
+ doReturn(wakeLock).when(mPowerManager).newWakeLock(anyInt(), anyString());
+ doReturn(mPowerManager).when(mContext).getSystemService(eq(Context.POWER_SERVICE));
+ doReturn(true).when(mPowerManager).isInteractive();
+
+ doReturn(mDisplay).when(mDisplayManager).getDisplay(eq(DEFAULT_DISPLAY));
+ doReturn(STATE_ON).when(mDisplay).getState();
+ doReturn(true).when(mDisplayPolicy).isAwake();
+ doNothing().when(mDisplayPolicy).takeScreenshot(anyInt(), anyInt());
+ doReturn(mDisplayPolicy).when(mDisplayRotation).getDisplayPolicy();
+ doReturn(mScreenOnListener).when(mDisplayPolicy).getScreenOnListener();
+ mPhoneWindowManager.setDefaultDisplay(new WindowManagerPolicy.DisplayContentInfo() {
+ @Override
+ public DisplayRotation getDisplayRotation() {
+ return mDisplayRotation;
+ }
+ @Override
+ public Display getDisplay() {
+ return mDisplay;
+ }
+ });
+
+ doNothing().when(mPhoneWindowManager).initializeHdmiState();
+ doNothing().when(mPhoneWindowManager).updateSettings();
+ doNothing().when(mPhoneWindowManager).screenTurningOn(anyInt(), any());
+ doNothing().when(mPhoneWindowManager).screenTurnedOn(anyInt());
+ doNothing().when(mPhoneWindowManager).startedWakingUp(anyInt());
+ doNothing().when(mPhoneWindowManager).finishedWakingUp(anyInt());
+
+ mPhoneWindowManager.init(new TestInjector(mContext, mWindowManagerFuncsImpl));
+ mPhoneWindowManager.systemReady();
+ mPhoneWindowManager.systemBooted();
+
+ overrideLaunchAccessibility();
+ }
+
+ void tearDown() {
+ mHandlerThread.quitSafely();
+ mMockitoSession.finishMocking();
+ }
+
+ // Override accessibility setting and perform function.
+ private void overrideLaunchAccessibility() {
+ doReturn(true).when(mAccessibilityShortcutController)
+ .isAccessibilityShortcutAvailable(anyBoolean());
+ doNothing().when(mAccessibilityShortcutController).performAccessibilityShortcut();
+ }
+
+ int interceptKeyBeforeQueueing(KeyEvent event) {
+ return mPhoneWindowManager.interceptKeyBeforeQueueing(event, FLAG_INTERACTIVE);
+ }
+
+ long interceptKeyBeforeDispatching(KeyEvent event) {
+ return mPhoneWindowManager.interceptKeyBeforeDispatching(null /*focusedToken*/,
+ event, FLAG_INTERACTIVE);
+ }
+
+ void dispatchUnhandledKey(KeyEvent event) {
+ mPhoneWindowManager.dispatchUnhandledKey(null /*focusedToken*/, event, FLAG_INTERACTIVE);
+ }
+
+ void waitForIdle() {
+ mHandler.runWithScissors(() -> { }, 0 /* timeout */);
+ }
+
+ /**
+ * Below functions will override the setting or the policy behavior.
+ */
+ void overridePowerVolumeUp(int behavior) {
+ mPhoneWindowManager.mPowerVolUpBehavior = behavior;
+
+ // override mRingerToggleChord as mute so we could trigger the behavior.
+ if (behavior == POWER_VOLUME_UP_BEHAVIOR_MUTE) {
+ mPhoneWindowManager.mRingerToggleChord = VOLUME_HUSH_MUTE;
+ doReturn(mAudioManagerInternal).when(
+ () -> LocalServices.getService(eq(AudioManagerInternal.class)));
+ }
+ }
+
+ // Override assist perform function.
+ void overrideLongPressOnPower(int behavior) {
+ mPhoneWindowManager.mLongPressOnPowerBehavior = behavior;
+
+ switch (behavior) {
+ case LONG_PRESS_POWER_NOTHING:
+ case LONG_PRESS_POWER_GLOBAL_ACTIONS:
+ case LONG_PRESS_POWER_SHUT_OFF:
+ case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
+ case LONG_PRESS_POWER_GO_TO_VOICE_ASSIST:
+ break;
+ case LONG_PRESS_POWER_ASSISTANT:
+ doNothing().when(mPhoneWindowManager).sendCloseSystemWindows();
+ doReturn(true).when(mPhoneWindowManager).isUserSetupComplete();
+ doReturn(mContext).when(mContext).createContextAsUser(any(), anyInt());
+ doReturn(mSearchManager).when(mContext)
+ .getSystemService(eq(Context.SEARCH_SERVICE));
+ mPhoneWindowManager.mLongPressOnPowerAssistantTimeoutMs = 500;
+ break;
+ }
+ }
+
+ void overrideDisplayState(int state) {
+ doReturn(state).when(mDisplay).getState();
+ Mockito.reset(mPowerManager);
+ }
+
+ void overrideIncallPowerBehavior(int behavior) {
+ mPhoneWindowManager.mIncallPowerBehavior = behavior;
+ setPhoneCallIsInProgress();
+ }
+
+ void setPhoneCallIsInProgress() {
+ // Let device has an ongoing phone call.
+ doReturn(false).when(mTelecomManager).isRinging();
+ doReturn(true).when(mTelecomManager).isInCall();
+ doReturn(true).when(mTelecomManager).endCall();
+ }
+
+ /**
+ * Below functions will check the policy behavior could be invoked.
+ */
+ void assertTakeScreenshotCalled() {
+ waitForIdle();
+ verify(mDisplayPolicy, timeout(SHORTCUT_KEY_DELAY_MILLIS))
+ .takeScreenshot(anyInt(), anyInt());
+ }
+
+ void assertShowGlobalActionsCalled() {
+ waitForIdle();
+ verify(mPhoneWindowManager).showGlobalActions();
+ verify(mGlobalActions, timeout(SHORTCUT_KEY_DELAY_MILLIS))
+ .showDialog(anyBoolean(), anyBoolean());
+ verify(mPowerManager, timeout(SHORTCUT_KEY_DELAY_MILLIS))
+ .userActivity(anyLong(), anyBoolean());
+ }
+
+ void assertVolumeMute() {
+ waitForIdle();
+ verify(mAudioManagerInternal, timeout(SHORTCUT_KEY_DELAY_MILLIS))
+ .silenceRingerModeInternal(eq("volume_hush"));
+ }
+
+ void assertAccessibilityKeychordCalled() {
+ waitForIdle();
+ verify(mAccessibilityShortcutController,
+ timeout(SHORTCUT_KEY_DELAY_MILLIS)).performAccessibilityShortcut();
+ }
+
+ void assertPowerSleep() {
+ waitForIdle();
+ verify(mPowerManager,
+ timeout(SHORTCUT_KEY_DELAY_MILLIS)).goToSleep(anyLong(), anyInt(), anyInt());
+ }
+
+ void assertPowerWakeUp() {
+ waitForIdle();
+ verify(mPowerManager,
+ timeout(SHORTCUT_KEY_DELAY_MILLIS)).wakeUp(anyLong(), anyInt(), anyString());
+ }
+
+ void assertNoPowerSleep() {
+ waitForIdle();
+ verify(mPowerManager, never()).goToSleep(anyLong(), anyInt(), anyInt());
+ }
+
+ void assertCameraLaunch() {
+ waitForIdle();
+ // GestureLauncherService should receive interceptPowerKeyDown twice.
+ verify(mGestureLauncherService, times(2))
+ .interceptPowerKeyDown(any(), anyBoolean(), any());
+ }
+
+ void assertAssistLaunch() {
+ waitForIdle();
+ verify(mSearchManager, timeout(SHORTCUT_KEY_DELAY_MILLIS)).launchAssist(any());
+ }
+}
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 44494831eb68..25c8f145bd62 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2869,6 +2869,7 @@ public class ActivityRecordTests extends WindowTestsBase {
mAtm, null /* fragmentToken */, false /* createdByOrganizer */);
fragmentSetup.accept(taskFragment1, new Rect(0, 0, width / 2, height));
task.addChild(taskFragment1, POSITION_TOP);
+ assertEquals(task, activity1.mStartingData.mAssociatedTask);
final TaskFragment taskFragment2 = new TaskFragment(
mAtm, null /* fragmentToken */, false /* createdByOrganizer */);
@@ -2890,7 +2891,6 @@ public class ActivityRecordTests extends WindowTestsBase {
eq(task.mSurfaceControl));
assertEquals(activity1.mStartingData, startingWindow.mStartingData);
assertEquals(task.mSurfaceControl, startingWindow.getAnimationLeashParent());
- assertEquals(task, activity1.mStartingData.mAssociatedTask);
assertEquals(taskFragment1.getBounds(), activity1.getBounds());
// The activity was resized by task fragment, but starting window must still cover the task.
assertEquals(taskBounds, activity1.mStartingWindow.getBounds());
@@ -2898,7 +2898,6 @@ public class ActivityRecordTests extends WindowTestsBase {
// The starting window is only removed when all embedded activities are drawn.
final WindowState activityWindow = mock(WindowState.class);
activity1.onFirstWindowDrawn(activityWindow);
- assertNotNull(activity1.mStartingWindow);
activity2.onFirstWindowDrawn(activityWindow);
assertNull(activity1.mStartingWindow);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 6d33aaffdf24..17387061a86e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -1640,6 +1640,75 @@ public class SizeCompatTests extends WindowTestsBase {
}
@Test
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN})
+ public void testOverrideMinAspectRatioExcludePortraitFullscreen() {
+ setUpDisplaySizeWithApp(2600, 1600);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.33f);
+
+ // Create a size compat activity on the same task.
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setTask(mTask)
+ .setComponent(ComponentName.createRelative(mContext,
+ SizeCompatTests.class.getName()))
+ .setUid(android.os.Process.myUid())
+ .build();
+
+ // Non-resizable portrait activity
+ prepareUnresizable(activity, 0f, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+
+ // At first, OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_FULLSCREEN does not apply, because the
+ // display is in landscape
+ assertEquals(1600, activity.getBounds().height());
+ assertEquals(1600 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
+ activity.getBounds().width(), 0.5);
+
+ rotateDisplay(activity.mDisplayContent, ROTATION_90);
+ prepareUnresizable(activity, /* maxAspect */ 0, SCREEN_ORIENTATION_PORTRAIT);
+
+ // Now the display is in portrait fullscreen, so the override is applied making the content
+ // fullscreen
+ assertEquals(activity.getBounds(), activity.mDisplayContent.getBounds());
+ }
+
+ @Test
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE,
+ ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN})
+ public void testOverrideMinAspectRatioExcludePortraitFullscreenNotApplied() {
+ // In this test, the activity is not in fullscreen, so the override is not applied
+ setUpDisplaySizeWithApp(2600, 1600);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ mActivity.mWmService.mLetterboxConfiguration.setFixedOrientationLetterboxAspectRatio(1.33f);
+
+ // Create a size compat activity on the same task.
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setTask(mTask)
+ .setComponent(ComponentName.createRelative(mContext,
+ SizeCompatTests.class.getName()))
+ .setUid(android.os.Process.myUid())
+ .build();
+
+ final TestSplitOrganizer organizer =
+ new TestSplitOrganizer(mAtm, activity.getDisplayContent());
+
+ // Move first activity to split screen which takes half of the screen.
+ organizer.mPrimary.setBounds(0, 0, 1300, 1600);
+ organizer.putTaskToPrimary(mTask, true);
+
+ // Non-resizable portrait activity
+ prepareUnresizable(activity, /* maxAspect */ 0, SCREEN_ORIENTATION_PORTRAIT);
+
+ // OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_FULLSCREEN does not apply here because the
+ // display is not in fullscreen, so OVERRIDE_MIN_ASPECT_RATIO_LARGE applies instead
+ assertEquals(1600, activity.getBounds().height());
+ assertEquals(1600 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
+ activity.getBounds().width(), 0.5);
+ }
+
+ @Test
public void testSplitAspectRatioForUnresizableLandscapeApps() {
// Set up a display in portrait and ignoring orientation request.
int screenWidth = 1400;
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index ab7e8eab28c3..9e6c4c58371b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -235,6 +235,7 @@ public class SystemServicesTestRule implements TestRule {
doReturn(pm).when(mContext).getSystemService(eq(Context.POWER_SERVICE));
mStubbedWakeLock = createStubbedWakeLock(false /* needVerification */);
doReturn(mStubbedWakeLock).when(pm).newWakeLock(anyInt(), anyString());
+ doReturn(mStubbedWakeLock).when(pm).newWakeLock(anyInt(), anyString(), anyInt());
// DisplayManagerInternal
final DisplayManagerInternal dmi = mock(DisplayManagerInternal.class);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTransactionTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTransactionTests.java
new file mode 100644
index 000000000000..d2552718f218
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTransactionTests.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.atLeast;
+
+import android.content.Intent;
+import android.platform.test.annotations.Presubmit;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
+
+import androidx.annotation.NonNull;
+import androidx.test.filters.SmallTest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test class for {@link WindowContainerTransaction}.
+ *
+ * Build/Install/Run:
+ * atest WmTests:WindowContainerTransactionTests
+ */
+@SmallTest
+@Presubmit
+@RunWith(WindowTestRunner.class)
+public class WindowContainerTransactionTests extends WindowTestsBase {
+
+ @Test
+ public void testRemoveTask() {
+ final Task rootTask = createTask(mDisplayContent);
+ final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
+ final ActivityRecord activity = createActivityRecord(mDisplayContent, task);
+
+ WindowContainerTransaction wct = new WindowContainerTransaction();
+ WindowContainerToken token = task.getTaskInfo().token;
+ wct.removeTask(token);
+ applyTransaction(wct);
+
+ // There is still an activity to be destroyed, so the task is not removed immediately.
+ assertNotNull(task.getParent());
+ assertTrue(rootTask.hasChild());
+ assertTrue(task.hasChild());
+ assertTrue(activity.finishing);
+
+ activity.destroyed("testRemoveContainer");
+ // Assert that the container was removed after the activity is destroyed.
+ assertNull(task.getParent());
+ assertEquals(0, task.getChildCount());
+ assertNull(activity.getParent());
+ verify(mAtm.getLockTaskController(), atLeast(1)).clearLockedTask(task);
+ verify(mAtm.getLockTaskController(), atLeast(1)).clearLockedTask(rootTask);
+ }
+
+ private Task createTask(int taskId) {
+ return new Task.Builder(mAtm)
+ .setTaskId(taskId)
+ .setIntent(new Intent())
+ .setRealActivity(ActivityBuilder.getDefaultComponent())
+ .setEffectiveUid(10050)
+ .buildInner();
+ }
+
+ private void applyTransaction(@NonNull WindowContainerTransaction t) {
+ if (!t.isEmpty()) {
+ mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
+ }
+ }
+}
diff --git a/services/usage/java/com/android/server/usage/AppTimeLimitController.java b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
index f169926fb3ac..1b34b817def1 100644
--- a/services/usage/java/com/android/server/usage/AppTimeLimitController.java
+++ b/services/usage/java/com/android/server/usage/AppTimeLimitController.java
@@ -772,7 +772,7 @@ public class AppTimeLimitController {
observerApp.appUsageGroups.append(observerId, group);
if (DEBUG) {
- Slog.d(TAG, "addObserver " + observed + " for " + timeLimit);
+ Slog.d(TAG, "addObserver " + Arrays.toString(observed) + " for " + timeLimit);
}
user.addUsageGroup(group);
@@ -881,7 +881,7 @@ public class AppTimeLimitController {
observerApp.appUsageLimitGroups.append(observerId, group);
if (DEBUG) {
- Slog.d(TAG, "addObserver " + observed + " for " + timeLimit);
+ Slog.d(TAG, "addObserver " + Arrays.toString(observed) + " for " + timeLimit);
}
user.addUsageGroup(group);
diff --git a/telecomm/java/android/telecom/DisconnectCause.java b/telecomm/java/android/telecom/DisconnectCause.java
index 0f034ad6a45e..b003f59d5e81 100644
--- a/telecomm/java/android/telecom/DisconnectCause.java
+++ b/telecomm/java/android/telecom/DisconnectCause.java
@@ -88,8 +88,8 @@ public final class DisconnectCause implements Parcelable {
public static final String REASON_WIFI_ON_BUT_WFC_OFF = "REASON_WIFI_ON_BUT_WFC_OFF";
/**
- * Reason code (returned via {@link #getReason()}), which indicates that the video telephony
- * call was disconnected because IMS access is blocked.
+ * Reason code (returned via {@link #getReason()}), which indicates that the call was
+ * disconnected because IMS access is blocked.
*/
public static final String REASON_IMS_ACCESS_BLOCKED = "REASON_IMS_ACCESS_BLOCKED";
diff --git a/telephony/common/com/google/android/mms/pdu/PduParser.java b/telephony/common/com/google/android/mms/pdu/PduParser.java
index 677fe2f188a9..62eac7ac942a 100755
--- a/telephony/common/com/google/android/mms/pdu/PduParser.java
+++ b/telephony/common/com/google/android/mms/pdu/PduParser.java
@@ -793,7 +793,7 @@ public class PduParser {
try {
if (LOCAL_LOGV) {
Log.v(LOG_TAG, "parseHeaders: CONTENT_TYPE: " + headerField +
- contentType.toString());
+ Arrays.toString(contentType));
}
headers.setTextString(contentType, PduHeaders.CONTENT_TYPE);
} catch(NullPointerException e) {
diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java
index d978f5701eca..212aaaed46b2 100644
--- a/telephony/java/android/telephony/PhysicalChannelConfig.java
+++ b/telephony/java/android/telephony/PhysicalChannelConfig.java
@@ -433,7 +433,8 @@ public final class PhysicalChannelConfig implements Parcelable {
return Objects.hash(
mCellConnectionStatus, mCellBandwidthDownlinkKhz, mCellBandwidthUplinkKhz,
mNetworkType, mFrequencyRange, mDownlinkChannelNumber, mUplinkChannelNumber,
- mContextIds, mPhysicalCellId, mBand, mDownlinkFrequency, mUplinkFrequency);
+ Arrays.hashCode(mContextIds), mPhysicalCellId, mBand, mDownlinkFrequency,
+ mUplinkFrequency);
}
public static final
diff --git a/telephony/java/android/telephony/SignalThresholdInfo.java b/telephony/java/android/telephony/SignalThresholdInfo.java
index ae7d20929d58..3c1824539d1f 100644
--- a/telephony/java/android/telephony/SignalThresholdInfo.java
+++ b/telephony/java/android/telephony/SignalThresholdInfo.java
@@ -574,8 +574,8 @@ public final class SignalThresholdInfo implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(mRan, mSignalMeasurementType, mHysteresisMs, mHysteresisDb, mThresholds,
- mIsEnabled);
+ return Objects.hash(mRan, mSignalMeasurementType, mHysteresisMs, mHysteresisDb,
+ Arrays.hashCode(mThresholds), mIsEnabled);
}
public static final @NonNull Parcelable.Creator<SignalThresholdInfo> CREATOR =
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index cbd03c7f653a..d670e5592c42 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -1935,7 +1935,7 @@ public final class SmsManager {
+ " at calling enableCellBroadcastRangeForSubscriber. subId = " + subId);
}
} catch (RemoteException ex) {
- Rlog.d(TAG, "enableCellBroadcastRange: " + ex.getStackTrace());
+ Rlog.d(TAG, "enableCellBroadcastRange: ", ex);
// ignore it
}
@@ -1996,7 +1996,7 @@ public final class SmsManager {
+ " at calling disableCellBroadcastRangeForSubscriber. subId = " + subId);
}
} catch (RemoteException ex) {
- Rlog.d(TAG, "disableCellBroadcastRange: " + ex.getStackTrace());
+ Rlog.d(TAG, "disableCellBroadcastRange: ", ex);
// ignore it
}
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index c36eb2f9cf65..cb985bf2cda5 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -967,9 +967,9 @@ public class SubscriptionInfo implements Parcelable {
public int hashCode() {
return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded,
mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc, mCountryIso, mCardString,
- mCardId, mDisplayName, mCarrierName, mNativeAccessRules, mIsGroupDisabled,
- mCarrierId, mProfileClass, mGroupOwner, mAreUiccApplicationsEnabled, mPortIndex,
- mUsageSetting);
+ mCardId, mDisplayName, mCarrierName, Arrays.hashCode(mNativeAccessRules),
+ mIsGroupDisabled, mCarrierId, mProfileClass, mGroupOwner,
+ mAreUiccApplicationsEnabled, mPortIndex, mUsageSetting);
}
@Override
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index e0c529848aae..19f2a9bc67a3 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -171,7 +171,7 @@ public final class TelephonyScanManager {
ci[i] = (CellInfo) parcelables[i];
}
executor.execute(() -> {
- Rlog.d(TAG, "onResults: " + ci.toString());
+ Rlog.d(TAG, "onResults: " + Arrays.toString(ci));
callback.onResults(Arrays.asList(ci));
});
} catch (Exception e) {
diff --git a/tests/HandwritingIme/src/com/google/android/test/handwritingime/HandwritingIme.java b/tests/HandwritingIme/src/com/google/android/test/handwritingime/HandwritingIme.java
index 8b69db707d41..dc34cb6d6a53 100644
--- a/tests/HandwritingIme/src/com/google/android/test/handwritingime/HandwritingIme.java
+++ b/tests/HandwritingIme/src/com/google/android/test/handwritingime/HandwritingIme.java
@@ -15,21 +15,25 @@
*/
package com.google.android.test.handwritingime;
+import android.R;
import android.annotation.Nullable;
import android.graphics.PointF;
import android.graphics.RectF;
import android.inputmethodservice.InputMethodService;
-import android.os.Bundle;
import android.util.Log;
-import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
-import android.view.inputmethod.CursorAnchorInfo;
+import android.view.inputmethod.DeleteGesture;
+import android.view.inputmethod.HandwritingGesture;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InsertGesture;
+import android.view.inputmethod.SelectGesture;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.FrameLayout;
+import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.Toast;
@@ -39,19 +43,19 @@ public class HandwritingIme extends InputMethodService {
public static final int HEIGHT_DP = 100;
-
private static final int OP_NONE = 0;
private static final int OP_SELECT = 1;
private static final int OP_DELETE = 2;
- private static final int OP_DELETE_SPACE = 3;
- private static final int OP_INSERT = 4;
+ private static final int OP_INSERT = 3;
private Window mInkWindow;
private InkView mInk;
static final String TAG = "HandwritingIme";
private int mRichGestureMode = OP_NONE;
+ private int mRichGestureGranularity = -1;
private Spinner mRichGestureModeSpinner;
+ private Spinner mRichGestureGranularitySpinner;
private PointF mRichGestureStartPoint;
@@ -86,13 +90,45 @@ public class HandwritingIme extends InputMethodService {
switch (event.getAction()) {
case MotionEvent.ACTION_UP: {
if (areRichGesturesEnabled()) {
- Bundle bundle = new Bundle();
- bundle.putInt("operation", mRichGestureMode);
- bundle.putFloat("left", mRichGestureStartPoint.x);
- bundle.putFloat("top", mRichGestureStartPoint.y);
- bundle.putFloat("right", event.getX());
- bundle.putFloat("bottom", event.getY());
- performPrivateCommand("android.widget.RichGesture", bundle);
+ HandwritingGesture gesture = null;
+ switch(mRichGestureMode) {
+ case OP_SELECT:
+ SelectGesture.Builder builder = new SelectGesture.Builder();
+ builder.setGranularity(mRichGestureGranularity)
+ .setSelectionArea(new RectF(mRichGestureStartPoint.x,
+ mRichGestureStartPoint.y, event.getX(), event.getY()))
+ .setFallbackText("fallback text");
+ gesture = builder.build();
+ break;
+ case OP_DELETE:
+ DeleteGesture.Builder builder1 = new DeleteGesture.Builder();
+ builder1.setGranularity(mRichGestureGranularity)
+ .setDeletionArea(new RectF(mRichGestureStartPoint.x,
+ mRichGestureStartPoint.y, event.getX(), event.getY()))
+ .setFallbackText("fallback text");
+ gesture = builder1.build();
+ break;
+ case OP_INSERT:
+ InsertGesture.Builder builder2 = new InsertGesture.Builder();
+ builder2.setInsertionPoint(
+ new PointF(mRichGestureStartPoint.x, mRichGestureStartPoint.y))
+ .setTextToInsert(" ")
+ .setFallbackText("fallback text");
+ gesture = builder2.build();
+
+ }
+ if (gesture == null) {
+ // This shouldn't happen
+ Log.e(TAG, "Unrecognized gesture mode: " + mRichGestureMode);
+ return;
+ }
+ InputConnection ic = getCurrentInputConnection();
+ if (getCurrentInputStarted() && ic != null) {
+ ic.performHandwritingGesture(gesture, null, null);
+ } else {
+ // This shouldn't happen
+ Log.e(TAG, "No active InputConnection");
+ }
Log.d(TAG, "Sending RichGesture " + mRichGestureMode + " (Screen) Left: "
+ mRichGestureStartPoint.x + ", Top: " + mRichGestureStartPoint.y
@@ -123,8 +159,15 @@ public class HandwritingIme extends InputMethodService {
view.addView(inner, new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT, height));
- view.addView(getRichGestureActionsSpinner());
- inner.setBackgroundColor(getColor(R.color.abc_tint_spinner));
+ LinearLayout layout = new LinearLayout(this);
+ layout.setLayoutParams(new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
+ layout.setOrientation(LinearLayout.VERTICAL);
+ layout.addView(getRichGestureActionsSpinner());
+ layout.addView(getRichGestureGranularitySpinner());
+
+ view.addView(layout);
+ inner.setBackgroundColor(getColor(R.color.holo_green_light));
return view;
}
@@ -133,14 +176,12 @@ public class HandwritingIme extends InputMethodService {
if (mRichGestureModeSpinner != null) {
return mRichGestureModeSpinner;
}
- //get the spinner from the xml.
mRichGestureModeSpinner = new Spinner(this);
mRichGestureModeSpinner.setPadding(100, 0, 100, 0);
mRichGestureModeSpinner.setTooltipText("Handwriting IME mode");
String[] items =
new String[] { "Handwriting IME - Rich gesture disabled", "Rich gesture SELECT",
- "Rich gesture DELETE", "Rich gesture DELETE SPACE",
- "Rich gesture INSERT" };
+ "Rich gesture DELETE", "Rich gesture INSERT" };
ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_dropdown_item, items);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
@@ -149,17 +190,52 @@ public class HandwritingIme extends InputMethodService {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
mRichGestureMode = position;
+ mRichGestureGranularitySpinner.setEnabled(
+ mRichGestureMode != OP_INSERT && mRichGestureMode != OP_NONE);
Log.d(TAG, "Setting RichGesture Mode " + mRichGestureMode);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
mRichGestureMode = OP_NONE;
+ mRichGestureGranularitySpinner.setEnabled(false);
}
});
+ mRichGestureModeSpinner.setSelection(0); // default disabled
return mRichGestureModeSpinner;
}
+ private View getRichGestureGranularitySpinner() {
+ if (mRichGestureGranularitySpinner != null) {
+ return mRichGestureGranularitySpinner;
+ }
+ mRichGestureGranularitySpinner = new Spinner(this);
+ mRichGestureGranularitySpinner.setPadding(100, 0, 100, 0);
+ mRichGestureGranularitySpinner.setTooltipText(" Granularity");
+ String[] items =
+ new String[] { "Granularity - UNDEFINED",
+ "Granularity - WORD", "Granularity - CHARACTER"};
+ ArrayAdapter<String> adapter = new ArrayAdapter<>(this,
+ android.R.layout.simple_spinner_dropdown_item, items);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ mRichGestureGranularitySpinner.setAdapter(adapter);
+ mRichGestureGranularitySpinner.setOnItemSelectedListener(
+ new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ mRichGestureGranularity = position;
+ Log.d(TAG, "Setting RichGesture Granularity " + mRichGestureGranularity);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ mRichGestureGranularity = 0;
+ }
+ });
+ mRichGestureGranularitySpinner.setSelection(1);
+ return mRichGestureGranularitySpinner;
+ }
+
public void onPrepareStylusHandwriting() {
Log.d(TAG, "onPrepareStylusHandwriting ");
if (mInk == null) {
@@ -190,15 +266,6 @@ public class HandwritingIme extends InputMethodService {
return false;
}
- boolean performPrivateCommand(String action, Bundle bundle) {
- if (!getCurrentInputStarted()) {
- Log.e(TAG, "Input hasnt started, can't performPrivateCommand");
- return false;
- }
-
- return getCurrentInputConnection().performPrivateCommand(action, bundle);
- }
-
private boolean areRichGesturesEnabled() {
return mRichGestureMode != OP_NONE;
}
diff --git a/tests/HandwritingIme/src/com/google/android/test/handwritingime/InkView.java b/tests/HandwritingIme/src/com/google/android/test/handwritingime/InkView.java
index c9e429b6f4c8..94b1f863f197 100644
--- a/tests/HandwritingIme/src/com/google/android/test/handwritingime/InkView.java
+++ b/tests/HandwritingIme/src/com/google/android/test/handwritingime/InkView.java
@@ -30,7 +30,7 @@ import android.view.WindowManager;
import android.view.WindowMetrics;
class InkView extends View {
- private static final long FINISH_TIMEOUT = 600;
+ private static final long FINISH_TIMEOUT = 1500;
private final HandwritingIme.HandwritingFinisher mHwCanceller;
private final HandwritingIme.StylusConsumer mConsumer;
private final int mTopInset;
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
index db4898492ac5..661dd845757b 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
@@ -33,6 +33,8 @@ import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
+import java.util.Arrays;
+
public class MainInteractionSession extends VoiceInteractionSession
implements View.OnClickListener {
static final String TAG = "MainInteractionSession";
@@ -403,7 +405,7 @@ public class MainInteractionSession extends VoiceInteractionSession
@Override
public void onRequestPickOption(PickOptionRequest request) {
Log.i(TAG, "onPickOption: prompt=" + request.getVoicePrompt() + " options="
- + request.getOptions() + " extras=" + request.getExtras());
+ + Arrays.toString(request.getOptions()) + " extras=" + request.getExtras());
mConfirmButton.setText("Pick Option");
mPendingRequest = request;
setPrompt(request.getVoicePrompt());
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java
index 733f602f6c14..8ae7186461d3 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/StartVoiceInteractionActivity.java
@@ -24,6 +24,8 @@ import android.view.View;
import android.widget.Button;
import android.widget.TextView;
+import java.util.Arrays;
+
public class StartVoiceInteractionActivity extends Activity implements View.OnClickListener {
static final String TAG = "LocalVoiceInteractionActivity";
@@ -187,7 +189,8 @@ public class StartVoiceInteractionActivity extends Activity implements View.OnCl
}
@Override
public void onPickOptionResult(boolean finished, Option[] selections, Bundle result) {
- Log.i(TAG, "Pick result: finished=" + finished + " selections=" + selections
+ Log.i(TAG, "Pick result: finished=" + finished
+ + " selections=" + Arrays.toString(selections)
+ " result=" + result);
StringBuilder sb = new StringBuilder();
if (finished) {
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
index ada0e21e059a..4fc3a15ac38d 100644
--- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
@@ -28,6 +28,8 @@ import android.view.View;
import android.widget.Button;
import android.widget.TextView;
+import java.util.Arrays;
+
public class TestInteractionActivity extends Activity implements View.OnClickListener {
static final String TAG = "TestInteractionActivity";
@@ -240,7 +242,8 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis
}
@Override
public void onPickOptionResult(boolean finished, Option[] selections, Bundle result) {
- Log.i(TAG, "Pick result: finished=" + finished + " selections=" + selections
+ Log.i(TAG, "Pick result: finished=" + finished
+ + " selections=" + Arrays.toString(selections)
+ " result=" + result);
StringBuilder sb = new StringBuilder();
if (finished) {
diff --git a/tools/aapt2/Debug.cpp b/tools/aapt2/Debug.cpp
index dfa229173373..f9e52b491413 100644
--- a/tools/aapt2/Debug.cpp
+++ b/tools/aapt2/Debug.cpp
@@ -33,6 +33,7 @@
#include "ValueVisitor.h"
#include "android-base/logging.h"
#include "android-base/stringprintf.h"
+#include "androidfw/ResourceTypes.h"
#include "idmap2/Policies.h"
#include "text/Printer.h"
#include "util/Util.h"
@@ -515,7 +516,8 @@ class XmlPrinter : public xml::ConstVisitor {
}
void Visit(const xml::Text* text) override {
- printer_->Println(StringPrintf("T: '%s'", text->text.c_str()));
+ printer_->Println(
+ StringPrintf("T: '%s'", android::ResTable::normalizeForOutput(text->text.c_str()).c_str()));
}
private:
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index 46a846bce35f..4fb7ed19ed20 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -369,9 +369,13 @@ class PackageFlattener {
bool sparse_encode = use_sparse_entries_;
- // Only sparse encode if the entries will be read on platforms O+.
- sparse_encode =
- sparse_encode && (context_->GetMinSdkVersion() >= SDK_O || config.sdkVersion >= SDK_O);
+ if (context_->GetMinSdkVersion() == 0 && config.sdkVersion == 0) {
+ // Sparse encode if sdk version is not set in context and config.
+ } else {
+ // Otherwise, only sparse encode if the entries will be read on platforms S_V2+.
+ sparse_encode = sparse_encode &&
+ (context_->GetMinSdkVersion() >= SDK_S_V2 || config.sdkVersion >= SDK_S_V2);
+ }
// Only sparse encode if the offsets are representable in 2 bytes.
sparse_encode =
diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp
index e48fca61fef8..f551bf61dc06 100644
--- a/tools/aapt2/format/binary/TableFlattener_test.cpp
+++ b/tools/aapt2/format/binary/TableFlattener_test.cpp
@@ -330,7 +330,7 @@ TEST_F(TableFlattenerTest, FlattenSparseEntryWithMinSdkO) {
std::unique_ptr<IAaptContext> context = test::ContextBuilder()
.SetCompilationPackage("android")
.SetPackageId(0x01)
- .SetMinSdkVersion(SDK_O)
+ .SetMinSdkVersion(SDK_S_V2)
.Build();
const ConfigDescription sparse_config = test::ParseConfigOrDie("en-rGB");
@@ -376,7 +376,26 @@ TEST_F(TableFlattenerTest, FlattenSparseEntryWithConfigSdkVersionO) {
.SetMinSdkVersion(SDK_LOLLIPOP)
.Build();
- const ConfigDescription sparse_config = test::ParseConfigOrDie("en-rGB-v26");
+ const ConfigDescription sparse_config = test::ParseConfigOrDie("en-rGB-v32");
+ auto table_in = BuildTableWithSparseEntries(context.get(), sparse_config, 0.25f);
+
+ TableFlattenerOptions options;
+ options.use_sparse_entries = true;
+
+ std::string no_sparse_contents;
+ ASSERT_TRUE(Flatten(context.get(), {}, table_in.get(), &no_sparse_contents));
+
+ std::string sparse_contents;
+ ASSERT_TRUE(Flatten(context.get(), options, table_in.get(), &sparse_contents));
+
+ EXPECT_GT(no_sparse_contents.size(), sparse_contents.size());
+}
+
+TEST_F(TableFlattenerTest, FlattenSparseEntryWithSdkVersionNotSet) {
+ std::unique_ptr<IAaptContext> context =
+ test::ContextBuilder().SetCompilationPackage("android").SetPackageId(0x01).Build();
+
+ const ConfigDescription sparse_config = test::ParseConfigOrDie("en-rGB");
auto table_in = BuildTableWithSparseEntries(context.get(), sparse_config, 0.25f);
TableFlattenerOptions options;
@@ -389,6 +408,27 @@ TEST_F(TableFlattenerTest, FlattenSparseEntryWithConfigSdkVersionO) {
ASSERT_TRUE(Flatten(context.get(), options, table_in.get(), &sparse_contents));
EXPECT_GT(no_sparse_contents.size(), sparse_contents.size());
+
+ // Attempt to parse the sparse contents.
+
+ ResourceTable sparse_table;
+ BinaryResourceParser parser(context->GetDiagnostics(), &sparse_table, Source("test.arsc"),
+ sparse_contents.data(), sparse_contents.size());
+ ASSERT_TRUE(parser.Parse());
+
+ auto value = test::GetValueForConfig<BinaryPrimitive>(&sparse_table, "android:string/foo_0",
+ sparse_config);
+ ASSERT_THAT(value, NotNull());
+ EXPECT_EQ(0u, value->value.data);
+
+ ASSERT_THAT(test::GetValueForConfig<BinaryPrimitive>(&sparse_table, "android:string/foo_1",
+ sparse_config),
+ IsNull());
+
+ value = test::GetValueForConfig<BinaryPrimitive>(&sparse_table, "android:string/foo_4",
+ sparse_config);
+ ASSERT_THAT(value, NotNull());
+ EXPECT_EQ(4u, value->value.data);
}
TEST_F(TableFlattenerTest, DoNotUseSparseEntryForDenseConfig) {