summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java60
-rw-r--r--apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java41
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java4
-rw-r--r--core/api/test-current.txt7
-rw-r--r--core/java/android/app/admin/DevicePolicyCache.java15
-rw-r--r--core/java/android/app/admin/DevicePolicyIdentifiers.java4
-rw-r--r--core/java/android/view/IRemoteAnimationRunner.aidl2
-rw-r--r--core/java/android/view/ImeFocusController.java8
-rw-r--r--core/java/android/view/ViewRootImpl.java8
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java65
-rw-r--r--core/java/android/view/inputmethod/TextBoundsInfo.java1
-rw-r--r--core/java/android/widget/Editor.java12
-rw-r--r--core/java/com/android/internal/accessibility/util/AccessibilityUtils.java29
-rw-r--r--core/java/com/android/internal/widget/NotificationActionListLayout.java29
-rw-r--r--core/res/AndroidManifest.xml16
-rw-r--r--core/res/res/values/config.xml3
-rw-r--r--core/res/res/values/dimens.xml4
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/RadioServiceUserControllerTest.java27
-rw-r--r--core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java43
-rw-r--r--core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java44
-rw-r--r--core/tests/coretests/src/android/app/activity/ActivityThreadTest.java2
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java34
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java10
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/LegacyTransitions.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java19
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java19
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java12
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt12
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt12
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt6
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java7
-rw-r--r--media/java/android/media/MediaCodecInfo.java45
-rw-r--r--media/java/android/media/soundtrigger/SoundTriggerManager.java68
-rw-r--r--media/jni/android_media_MediaPlayer.cpp8
-rw-r--r--packages/CredentialManager/res/values/strings.xml12
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java104
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiStatusTrackerTest.java211
-rw-r--r--packages/SystemUI/Android.bp3
-rw-r--r--packages/SystemUI/AndroidManifest.xml16
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt8
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationDelegate.kt2
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt166
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt1
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt9
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt12
-rw-r--r--packages/SystemUI/res/layout/screen_record_dialog.xml6
-rw-r--r--packages/SystemUI/res/layout/screen_share_dialog.xml4
-rw-r--r--packages/SystemUI/res/values/strings.xml100
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java23
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java27
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java54
-rw-r--r--packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/OWNERS3
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt137
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/PackageUpdateMonitor.kt76
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamLogger.kt30
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/DreamLog.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/table/LogProxy.kt67
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt47
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt55
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenrecord/MediaProjectionPermissionDialog.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt87
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LegacyNotificationShelfControllerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java86
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java23
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt21
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/OWNERS1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/accessibility/SystemActionsTest.java126
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt15
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt193
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/controller/PackageUpdateMonitorTest.kt114
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt80
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt21
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/log/table/FakeLogProxy.kt56
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt145
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDeviceManagerTest.kt21
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt21
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java247
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt133
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java370
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java27
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt20
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt16
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java13
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java13
-rw-r--r--services/accessibility/java/com/android/server/accessibility/ProxyManager.java46
-rw-r--r--services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java7
-rw-r--r--services/autofill/java/com/android/server/autofill/Helper.java39
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java18
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java23
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/DisplayHelper.java68
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/FillUi.java9
-rw-r--r--services/autofill/java/com/android/server/autofill/ui/SaveUi.java9
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java2
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java2
-rw-r--r--services/core/java/com/android/server/am/BroadcastProcessQueue.java41
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueueModernImpl.java24
-rw-r--r--services/core/java/com/android/server/broadcastradio/RadioServiceUserController.java18
-rw-r--r--services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java7
-rw-r--r--services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java2
-rw-r--r--services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java7
-rw-r--r--services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java3
-rw-r--r--services/core/java/com/android/server/cpu/CpuMonitorService.java11
-rw-r--r--services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java13
-rw-r--r--services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java4
-rw-r--r--services/core/java/com/android/server/pm/LauncherAppsService.java9
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java5
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java93
-rw-r--r--services/core/java/com/android/server/wm/AbsAppSnapshotController.java12
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java6
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java12
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java8
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java6
-rw-r--r--services/core/java/com/android/server/wm/RemoteAnimationController.java9
-rw-r--r--services/core/java/com/android/server/wm/Transition.java53
-rw-r--r--services/core/java/com/android/server/wm/TransitionController.java15
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java8
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java19
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java3
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java234
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java9
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java19
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java61
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java71
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java12
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java25
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/ProxyAccessibilityServiceConnectionTest.java23
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java527
-rw-r--r--services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java86
-rw-r--r--services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java19
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java16
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java11
-rw-r--r--services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java42
-rw-r--r--telecomm/java/android/telecom/TelecomManager.java4
-rw-r--r--telephony/java/android/telephony/data/ApnSetting.java10
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt7
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt7
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt28
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt5
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTestCfArm.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt3
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTestCfArm.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdCfArm.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt1
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt7
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt1
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTestCfArm.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt10
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt2
294 files changed, 4514 insertions, 1895 deletions
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index b732da29b754..19a47669b0dd 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -24,11 +24,9 @@ import static org.junit.Assume.assumeTrue;
import android.annotation.NonNull;
import android.app.ActivityManager;
-import android.app.ActivityTaskManager;
import android.app.AppGlobals;
import android.app.IActivityManager;
import android.app.IStopUserCallback;
-import android.app.WaitResult;
import android.app.WallpaperManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -69,6 +67,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
/**
* Perf tests for user life cycle events.
@@ -101,7 +100,6 @@ public class UserLifecycleTests {
private static final long TIMEOUT_MAX_TEST_TIME_MS = 24 * 60_000;
private static final int TIMEOUT_IN_SECOND = 30;
- private static final int CHECK_USER_REMOVED_INTERVAL_MS = 200;
/** Name of users/profiles in the test. Users with this name may be freely removed. */
private static final String TEST_USER_NAME = "UserLifecycleTests_test_user";
@@ -1261,15 +1259,13 @@ public class UserLifecycleTests {
* <p> This should always be used for profiles since profiles cannot be started in foreground.
*/
private void startUserInBackgroundAndWaitForUnlock(int userId) {
- final ProgressWaiter waiter = new ProgressWaiter();
- boolean success = false;
try {
- mIam.startUserInBackgroundWithListener(userId, waiter);
- success = waiter.waitForFinish(TIMEOUT_IN_SECOND);
- } catch (RemoteException e) {
- Log.e(TAG, "startUserInBackgroundAndWaitForUnlock failed", e);
+ attestTrue("Failed to start user " + userId + " in background.",
+ ShellHelper.runShellCommandWithTimeout("am start-user -w " + userId,
+ TIMEOUT_IN_SECOND).startsWith("Success:"));
+ } catch (TimeoutException e) {
+ fail("Could not start user " + userId + " in " + TIMEOUT_IN_SECOND + " seconds");
}
- attestTrue("Failed to start user " + userId + " in background.", success);
}
/** Starts the given user in the foreground. */
@@ -1389,14 +1385,20 @@ public class UserLifecycleTests {
* Launches the given package in the given user.
* Make sure the keyguard has been dismissed prior to calling.
*/
- private void startApp(int userId, String packageName) throws RemoteException {
- final Context context = InstrumentationRegistry.getContext();
- final WaitResult result = ActivityTaskManager.getService().startActivityAndWait(null,
- context.getPackageName(), context.getAttributionTag(),
- context.getPackageManager().getLaunchIntentForPackage(packageName), null, null,
- null, 0, 0, null, null, userId);
- attestTrue("User " + userId + " failed to start " + packageName,
- result.result == ActivityManager.START_SUCCESS);
+ private void startApp(int userId, String packageName) {
+ final String failMessage = "User " + userId + " failed to start " + packageName;
+ final String component = InstrumentationRegistry.getContext().getPackageManager()
+ .getLaunchIntentForPackage(packageName).getComponent().flattenToShortString();
+ try {
+ final String result = ShellHelper.runShellCommandWithTimeout(
+ "am start -W -n " + component + " --user " + userId, TIMEOUT_IN_SECOND);
+ assertTrue(failMessage + ", component=" + component + ", result=" + result,
+ result.contains("Status: ok")
+ && !result.contains("Warning:")
+ && !result.contains("Error:"));
+ } catch (TimeoutException e) {
+ fail(failMessage + " in " + TIMEOUT_IN_SECOND + " seconds");
+ }
}
private class ProgressWaiter extends IProgressListener.Stub {
@@ -1471,17 +1473,11 @@ public class UserLifecycleTests {
private void removeUser(int userId) throws RemoteException {
stopUserAfterWaitingForBroadcastIdle(userId, true);
try {
- mUm.removeUser(userId);
- final long startTime = System.currentTimeMillis();
- final long timeoutInMs = TIMEOUT_IN_SECOND * 1000;
- while (mUm.getUserInfo(userId) != null &&
- System.currentTimeMillis() - startTime < timeoutInMs) {
- TimeUnit.MILLISECONDS.sleep(CHECK_USER_REMOVED_INTERVAL_MS);
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- } catch (Exception e) {
- // Ignore
+ ShellHelper.runShellCommandWithTimeout("pm remove-user -w " + userId,
+ TIMEOUT_IN_SECOND);
+ } catch (TimeoutException e) {
+ Log.e(TAG, String.format("Could not remove user %d in %d seconds",
+ userId, TIMEOUT_IN_SECOND), e);
}
if (mUm.getUserInfo(userId) != null) {
mUsersToRemove.add(userId);
@@ -1544,7 +1540,11 @@ public class UserLifecycleTests {
}
private void waitForBroadcastIdle() {
- ShellHelper.runShellCommand("am wait-for-broadcast-idle");
+ try {
+ ShellHelper.runShellCommandWithTimeout("am wait-for-broadcast-idle", TIMEOUT_IN_SECOND);
+ } catch (TimeoutException e) {
+ Log.e(TAG, "Ending waitForBroadcastIdle because it is taking too long", e);
+ }
}
private void sleep(long ms) {
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java b/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java
index 7b52576c1abd..a35899ad541b 100644
--- a/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/ShellHelper.java
@@ -24,6 +24,10 @@ import androidx.annotation.NonNull;
import androidx.test.InstrumentationRegistry;
import java.io.FileInputStream;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
/**
* Provides Shell-based utilities such as running a command.
@@ -31,6 +35,43 @@ import java.io.FileInputStream;
public final class ShellHelper {
/**
+ * Runs a Shell command with a timeout, returning a trimmed response.
+ */
+ @NonNull
+ public static String runShellCommandWithTimeout(@NonNull String command, long timeoutInSecond)
+ throws TimeoutException {
+ AtomicReference<Exception> exception = new AtomicReference<>(null);
+ AtomicReference<String> result = new AtomicReference<>(null);
+
+ CountDownLatch latch = new CountDownLatch(1);
+
+ new Thread(() -> {
+ try {
+ result.set(runShellCommandRaw(command));
+ } catch (Exception e) {
+ exception.set(e);
+ } finally {
+ latch.countDown();
+ }
+ }).start();
+
+ try {
+ if (!latch.await(timeoutInSecond, TimeUnit.SECONDS)) {
+ throw new TimeoutException("Command: '" + command + "' could not run in "
+ + timeoutInSecond + " seconds");
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+
+ if (exception.get() != null) {
+ throw new AndroidRuntimeException(exception.get());
+ }
+
+ return result.get();
+ }
+
+ /**
* Runs a Shell command, returning a trimmed response.
*/
@NonNull
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
index 430a1e25e123..4d646de2e529 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/Alarm.java
@@ -292,6 +292,10 @@ class Alarm {
return "permission";
case EXACT_ALLOW_REASON_POLICY_PERMISSION:
return "policy_permission";
+ case EXACT_ALLOW_REASON_LISTENER:
+ return "listener";
+ case EXACT_ALLOW_REASON_PRIORITIZED:
+ return "prioritized";
case EXACT_ALLOW_REASON_NOT_APPLICABLE:
return "N/A";
default:
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index ae63816945e1..332c53cb224f 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -536,6 +536,12 @@ package android.app.admin {
field @NonNull public static final android.app.admin.DeviceAdminAuthority DEVICE_ADMIN_AUTHORITY;
}
+ public final class DevicePolicyIdentifiers {
+ field public static final String PERMITTED_INPUT_METHODS_POLICY = "permittedInputMethods";
+ field public static final String PERSONAL_APPS_SUSPENDED_POLICY = "personalAppsSuspended";
+ field public static final String SCREEN_CAPTURE_DISABLED_POLICY = "screenCaptureDisabled";
+ }
+
public class DevicePolicyManager {
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public void acknowledgeNewUserDisclaimer();
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public void calculateHasIncompatibleAccounts();
@@ -3783,6 +3789,7 @@ package android.view.inputmethod {
method @NonNull @RequiresPermission(value=android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, conditional=true) public java.util.List<android.view.inputmethod.InputMethodInfo> getInputMethodListAsUser(int);
method public boolean hasActiveInputConnection(@Nullable android.view.View);
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public boolean hasPendingImeVisibilityRequests();
+ method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public boolean isCurrentRootView(@NonNull android.view.View);
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public boolean isInputMethodPickerShown();
method @RequiresPermission(android.Manifest.permission.TEST_INPUT_METHOD) public void setStylusWindowIdleTimeoutForTest(long);
field public static final long CLEAR_SHOW_FORCED_FLAG_WHEN_LEAVING = 214016041L; // 0xcc1a029L
diff --git a/core/java/android/app/admin/DevicePolicyCache.java b/core/java/android/app/admin/DevicePolicyCache.java
index b6e83c8bc8a1..29f657ec6ba7 100644
--- a/core/java/android/app/admin/DevicePolicyCache.java
+++ b/core/java/android/app/admin/DevicePolicyCache.java
@@ -19,8 +19,8 @@ import android.annotation.UserIdInt;
import com.android.server.LocalServices;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Collections;
+import java.util.Map;
/**
* Stores a copy of the set of device policies maintained by {@link DevicePolicyManager} that
@@ -64,10 +64,11 @@ public abstract class DevicePolicyCache {
public abstract boolean canAdminGrantSensorsPermissions();
/**
- * Returns a list of package names for which all launcher shortcuts should be modified to be
- * launched in the managed profile and badged accordingly.
+ * Returns a map of package names to package names, for which all launcher shortcuts which
+ * match a key package name should be modified to launch the corresponding value package
+ * name in the managed profile. The overridden shortcut should be badged accordingly.
*/
- public abstract List<String> getLauncherShortcutOverrides();
+ public abstract Map<String, String> getLauncherShortcutOverrides();
/**
* Empty implementation.
@@ -95,8 +96,8 @@ public abstract class DevicePolicyCache {
return false;
}
@Override
- public List<String> getLauncherShortcutOverrides() {
- return new ArrayList<>();
+ public Map<String, String> getLauncherShortcutOverrides() {
+ return Collections.EMPTY_MAP;
}
}
}
diff --git a/core/java/android/app/admin/DevicePolicyIdentifiers.java b/core/java/android/app/admin/DevicePolicyIdentifiers.java
index 9b0a70d65d6f..aeac59b12a2e 100644
--- a/core/java/android/app/admin/DevicePolicyIdentifiers.java
+++ b/core/java/android/app/admin/DevicePolicyIdentifiers.java
@@ -17,6 +17,7 @@
package android.app.admin;
import android.annotation.NonNull;
+import android.annotation.TestApi;
import android.os.UserManager;
import java.util.Objects;
@@ -118,6 +119,7 @@ public final class DevicePolicyIdentifiers {
*
* @hide
*/
+ @TestApi
public static final String PERMITTED_INPUT_METHODS_POLICY = "permittedInputMethods";
/**
@@ -125,6 +127,7 @@ public final class DevicePolicyIdentifiers {
*
* @hide
*/
+ @TestApi
public static final String PERSONAL_APPS_SUSPENDED_POLICY = "personalAppsSuspended";
/**
@@ -132,6 +135,7 @@ public final class DevicePolicyIdentifiers {
*
* @hide
*/
+ @TestApi
public static final String SCREEN_CAPTURE_DISABLED_POLICY = "screenCaptureDisabled";
/**
diff --git a/core/java/android/view/IRemoteAnimationRunner.aidl b/core/java/android/view/IRemoteAnimationRunner.aidl
index 1981c9d66c8b..1f64fb8ca2ec 100644
--- a/core/java/android/view/IRemoteAnimationRunner.aidl
+++ b/core/java/android/view/IRemoteAnimationRunner.aidl
@@ -46,5 +46,5 @@ oneway interface IRemoteAnimationRunner {
* won't have any effect anymore.
*/
@UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
- void onAnimationCancelled(boolean isKeyguardOccluded);
+ void onAnimationCancelled();
}
diff --git a/core/java/android/view/ImeFocusController.java b/core/java/android/view/ImeFocusController.java
index 43828d58afc4..97148969e17f 100644
--- a/core/java/android/view/ImeFocusController.java
+++ b/core/java/android/view/ImeFocusController.java
@@ -86,9 +86,12 @@ public final class ImeFocusController {
void onPreWindowFocus(boolean hasWindowFocus, WindowManager.LayoutParams windowAttribute) {
mHasImeFocus = WindowManager.LayoutParams.mayUseInputMethod(windowAttribute.flags);
if (!hasWindowFocus || !mHasImeFocus || isInLocalFocusMode(windowAttribute)) {
- return;
+ if (!hasWindowFocus) {
+ getImmDelegate().onWindowLostFocus(mViewRootImpl);
+ }
+ } else {
+ getImmDelegate().onPreWindowGainedFocus(mViewRootImpl);
}
- getImmDelegate().onPreWindowGainedFocus(mViewRootImpl);
}
@UiThread
@@ -163,6 +166,7 @@ public final class ImeFocusController {
void onPreWindowGainedFocus(ViewRootImpl viewRootImpl);
void onPostWindowGainedFocus(View viewForWindowFocus,
@NonNull WindowManager.LayoutParams windowAttribute);
+ void onWindowLostFocus(@NonNull ViewRootImpl viewRootImpl);
void onViewFocusChanged(@NonNull View view, boolean hasFocus);
void onScheduledCheckFocus(@NonNull ViewRootImpl viewRootImpl);
void onViewDetachedFromWindow(View view, ViewRootImpl viewRootImpl);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index c0ac04ccd4d8..8f20e2d044ac 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -961,12 +961,20 @@ public final class ViewRootImpl implements ViewParent,
}
sAnrReported = true;
+ // If we're making an in-process call to ActivityManagerService
+ // and the previous binder call on this thread was oneway, the
+ // calling PID will be 0. Clearing the calling identity fixes
+ // this and ensures ActivityManager gets the correct calling
+ // pid.
+ final long identityToken = Binder.clearCallingIdentity();
try {
ActivityManager.getService().appNotResponding(reason);
} catch (RemoteException e) {
// We asked the system to crash us, but the system
// already crashed. Unfortunately things may be
// out of control.
+ } finally {
+ Binder.restoreCallingIdentity(identityToken);
}
}
};
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 82cf07355a56..41ef44e1ac1f 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -482,13 +482,21 @@ public final class InputMethodManager {
private View mNextServedView;
/**
- * This is the root view of the overall window that currently has input
- * method focus.
+ * The latest {@link ViewRootImpl} that has, or most recently had, input method focus.
+ *
+ * <p>This value will be cleared when it becomes inactive and no longer has window focus.
*/
+ @Nullable
@GuardedBy("mH")
ViewRootImpl mCurRootView;
/**
+ * Whether the {@link #mCurRootView} currently has window focus.
+ */
+ @GuardedBy("mH")
+ boolean mCurRootViewWindowFocused;
+
+ /**
* This is set when we are in the process of connecting, to determine
* when we have actually finished.
*/
@@ -745,6 +753,7 @@ public final class InputMethodManager {
public void onPreWindowGainedFocus(ViewRootImpl viewRootImpl) {
synchronized (mH) {
setCurrentRootViewLocked(viewRootImpl);
+ mCurRootViewWindowFocused = true;
}
}
@@ -822,6 +831,17 @@ public final class InputMethodManager {
}
@Override
+ public void onWindowLostFocus(@NonNull ViewRootImpl viewRootImpl) {
+ synchronized (mH) {
+ if (mCurRootView == viewRootImpl) {
+ mCurRootViewWindowFocused = false;
+
+ clearCurRootViewIfNeeded();
+ }
+ }
+ }
+
+ @Override
public void onViewFocusChanged(@Nullable View view, boolean hasFocus) {
onViewFocusChangedInternal(view, hasFocus);
}
@@ -1114,6 +1134,10 @@ public final class InputMethodManager {
// Note that finishComposingText() is allowed to run
// even when we are not active.
mFallbackInputConnection.finishComposingTextFromImm();
+
+ if (clearCurRootViewIfNeeded()) {
+ return;
+ }
}
// Check focus again in case that "onWindowFocus" is called before
// handling this message.
@@ -1756,8 +1780,7 @@ public final class InputMethodManager {
}
/**
- * Return true if the given view is the currently active view for the
- * input method.
+ * Return {@code true} if the given view is the currently active view for the input method.
*/
public boolean isActive(View view) {
// Re-dispatch if there is a context mismatch.
@@ -1773,7 +1796,7 @@ public final class InputMethodManager {
}
/**
- * Return true if any view is currently active in the input method.
+ * Return {@code true} if any view is currently active for the input method.
*/
public boolean isActive() {
checkFocus();
@@ -1783,6 +1806,20 @@ public final class InputMethodManager {
}
/**
+ * Returns {@code true} if the given view's {@link ViewRootImpl} is the currently active one
+ * for the {@code InputMethodManager}.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(Manifest.permission.TEST_INPUT_METHOD)
+ public boolean isCurrentRootView(@NonNull View attachedView) {
+ synchronized (mH) {
+ return mCurRootView == attachedView.getViewRootImpl();
+ }
+ }
+
+ /**
* Return {@code true} if the currently served view is accepting full text edits.
* If {@code false}, it has no input connection, so it can only handle raw key events.
*/
@@ -1908,6 +1945,24 @@ public final class InputMethodManager {
mImeDispatcher.clear();
}
+ /**
+ * Clears the {@link #mCurRootView} if it's no longer window focused and the connection is
+ * no longer active.
+ *
+ * @return {@code} true iff it was cleared.
+ */
+ @GuardedBy("mH")
+ private boolean clearCurRootViewIfNeeded() {
+ if (!mActive && !mCurRootViewWindowFocused) {
+ finishInputLocked();
+ mDelegate.setCurrentRootViewLocked(null);
+
+ return true;
+ }
+
+ return false;
+ }
+
public void displayCompletions(View view, CompletionInfo[] completions) {
// Re-dispatch if there is a context mismatch.
final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
diff --git a/core/java/android/view/inputmethod/TextBoundsInfo.java b/core/java/android/view/inputmethod/TextBoundsInfo.java
index d42d94e91933..d9f59d634295 100644
--- a/core/java/android/view/inputmethod/TextBoundsInfo.java
+++ b/core/java/android/view/inputmethod/TextBoundsInfo.java
@@ -1025,6 +1025,7 @@ public final class TextBoundsInfo implements Parcelable {
mEnd = -1;
mCharacterBounds = null;
mCharacterFlags = null;
+ mCharacterBidiLevels = null;
mLineSegmentFinder = null;
mWordSegmentFinder = null;
mGraphemeSegmentFinder = null;
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 7931d1a06d39..2dbff581fe84 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -724,7 +724,10 @@ public class Editor {
}
getPositionListener().addSubscriber(mCursorAnchorInfoNotifier, true);
- makeBlink();
+ // Call resumeBlink here instead of makeBlink to ensure that if mBlink is not null the
+ // Blink object is uncancelled. This ensures when a view is removed and added back the
+ // cursor will resume blinking.
+ resumeBlink();
}
void onDetachedFromWindow() {
@@ -1094,8 +1097,10 @@ public class Editor {
private void resumeBlink() {
if (mBlink != null) {
mBlink.uncancel();
- makeBlink();
}
+ // Moving makeBlink outside of the null check block ensures that mBlink object gets
+ // instantiated when the view is added to the window if mBlink is still null.
+ makeBlink();
}
void adjustInputType(boolean password, boolean passwordInputType,
@@ -2921,6 +2926,9 @@ public class Editor {
if (shouldBlink()) {
mShowCursor = SystemClock.uptimeMillis();
if (mBlink == null) mBlink = new Blink();
+ // Call uncancel as mBlink could have previously been cancelled and cursor will not
+ // resume blinking unless uncancelled.
+ mBlink.uncancel();
mTextView.removeCallbacks(mBlink);
mTextView.postDelayed(mBlink, BLINK);
} else {
diff --git a/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java b/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
index 3a8f427d54bc..4f9fc39300ae 100644
--- a/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
+++ b/core/java/com/android/internal/accessibility/util/AccessibilityUtils.java
@@ -32,6 +32,9 @@ import android.content.pm.ResolveInfo;
import android.os.Build;
import android.os.UserHandle;
import android.provider.Settings;
+import android.telecom.TelecomManager;
+import android.telephony.Annotation;
+import android.telephony.TelephonyManager;
import android.text.ParcelableSpan;
import android.text.Spanned;
import android.text.TextUtils;
@@ -204,6 +207,32 @@ public final class AccessibilityUtils {
}
/**
+ * Intercepts the {@link AccessibilityService#GLOBAL_ACTION_KEYCODE_HEADSETHOOK} action
+ * by directly interacting with TelecomManager if a call is incoming or in progress.
+ *
+ * <p>
+ * Provided here in shared utils to be used by both the legacy and modern (SysUI)
+ * system action implementations.
+ * </p>
+ *
+ * @return True if the action was propagated to TelecomManager, otherwise false.
+ */
+ public static boolean interceptHeadsetHookForActiveCall(Context context) {
+ final TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
+ @Annotation.CallState final int callState =
+ telecomManager != null ? telecomManager.getCallState()
+ : TelephonyManager.CALL_STATE_IDLE;
+ if (callState == TelephonyManager.CALL_STATE_RINGING) {
+ telecomManager.acceptRingingCall();
+ return true;
+ } else if (callState == TelephonyManager.CALL_STATE_OFFHOOK) {
+ telecomManager.endCall();
+ return true;
+ }
+ return false;
+ }
+
+ /**
* Indicates whether the current user has completed setup via the setup wizard.
* {@link android.provider.Settings.Secure#USER_SETUP_COMPLETE}
*
diff --git a/core/java/com/android/internal/widget/NotificationActionListLayout.java b/core/java/com/android/internal/widget/NotificationActionListLayout.java
index 302d2e797e74..a7a69c9e43fb 100644
--- a/core/java/com/android/internal/widget/NotificationActionListLayout.java
+++ b/core/java/com/android/internal/widget/NotificationActionListLayout.java
@@ -50,6 +50,8 @@ public class NotificationActionListLayout extends LinearLayout {
private boolean mEmphasizedMode;
private int mDefaultPaddingBottom;
private int mDefaultPaddingTop;
+ private int mEmphasizedPaddingTop;
+ private int mEmphasizedPaddingBottom;
private int mEmphasizedHeight;
private int mRegularHeight;
@DimenRes private int mCollapsibleIndentDimen = R.dimen.notification_actions_padding_start;
@@ -322,13 +324,16 @@ public class NotificationActionListLayout extends LinearLayout {
}
private void updateHeights() {
- int paddingTop = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_content_margin);
+ int inset = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.button_inset_vertical_material);
+ mEmphasizedPaddingTop = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_content_margin) - inset;
// same padding on bottom and at end
- int paddingBottom = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_content_margin_end);
- mEmphasizedHeight = paddingBottom + paddingTop + getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_action_emphasized_height);
+ mEmphasizedPaddingBottom = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_content_margin_end) - inset;
+ mEmphasizedHeight = mEmphasizedPaddingTop + mEmphasizedPaddingBottom
+ + getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.notification_action_emphasized_height);
mRegularHeight = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_action_list_height);
}
@@ -356,18 +361,10 @@ public class NotificationActionListLayout extends LinearLayout {
mEmphasizedMode = emphasizedMode;
int height;
if (emphasizedMode) {
- int paddingTop = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_content_margin);
- // same padding on bottom and at end
- int paddingBottom = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.notification_content_margin_end);
- int buttonPaddingInternal = getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.button_inset_vertical_material);
setPaddingRelative(getPaddingStart(),
- paddingTop - buttonPaddingInternal,
+ mEmphasizedPaddingTop,
getPaddingEnd(),
- paddingBottom - buttonPaddingInternal);
-
+ mEmphasizedPaddingBottom);
setMinimumHeight(mEmphasizedHeight);
height = ViewGroup.LayoutParams.WRAP_CONTENT;
} else {
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 31220b438ac4..fefa79f65201 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -8067,16 +8067,6 @@
</intent-filter>
</receiver>
- <!-- Broadcast Receiver listen to sufficient verifier requests from Package Manager
- when install new SDK, to verifier SDK code during installation time
- and terminate install if SDK not compatible with privacy sandbox restrictions. -->
- <receiver android:name="com.android.server.sdksandbox.SdkSandboxVerifierReceiver"
- android:exported="false">
- <intent-filter>
- <action android:name="android.intent.action.PACKAGE_NEEDS_VERIFICATION"/>
- </intent-filter>
- </receiver>
-
<service android:name="android.hardware.location.GeofenceHardwareService"
android:permission="android.permission.LOCATION_HARDWARE"
android:exported="false" />
@@ -8204,6 +8194,10 @@
android:permission="android.permission.BIND_JOB_SERVICE">
</service>
+ <service android:name="com.android.server.healthconnect.backuprestore.BackupRestore$BackupRestoreJobService"
+ android:permission="android.permission.BIND_JOB_SERVICE">
+ </service>
+
<service android:name="com.android.server.pm.PackageManagerShellCommandDataLoader"
android:exported="false">
<intent-filter>
@@ -8228,6 +8222,8 @@
<service android:name="com.android.server.companion.datatransfer.contextsync.CallMetadataSyncInCallService"
android:permission="android.permission.BIND_INCALL_SERVICE"
android:exported="true">
+ <meta-data android:name="android.telecom.INCLUDE_SELF_MANAGED_CALLS"
+ android:value="true" />
<intent-filter>
<action android:name="android.telecom.InCallService"/>
</intent-filter>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index c5f7ea6501ff..12dad7eb1faa 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -558,6 +558,9 @@
docked if the dock is configured to enable the accelerometer. -->
<bool name="config_supportAutoRotation">true</bool>
+ <!-- If true, allows rotation resolver service to help resolve screen rotation. -->
+ <bool name="config_allowRotationResolver">true</bool>
+
<!-- If true, the screen can be rotated via the accelerometer in all 4
rotations as the default behavior. -->
<bool name="config_allowAllRotations">false</bool>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index b1b1edf85a09..bc0af12e9569 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -257,8 +257,8 @@
<!-- The margin of the notification action list at the top -->
<dimen name="notification_action_list_margin_top">0dp</dimen>
- <!-- The visual height of the emphasized notification action -->
- <dimen name="notification_action_emphasized_height">36dp</dimen>
+ <!-- The overall height of the emphasized notification action -->
+ <dimen name="notification_action_emphasized_height">48dp</dimen>
<!-- The padding of the actions in non-conversation layout. For conversations, the analogous
value is calculated in ConversationLayout#updateActionListPadding() -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ae107fd648d3..bb10f7ae7c93 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1715,6 +1715,7 @@
<java-symbol type="integer" name="config_motionPredictionOffsetNanos" />
<java-symbol type="bool" name="config_showNavigationBar" />
<java-symbol type="bool" name="config_supportAutoRotation" />
+ <java-symbol type="bool" name="config_allowRotationResolver" />
<java-symbol type="bool" name="config_dockedStackDividerFreeSnapMode" />
<java-symbol type="dimen" name="docked_stack_divider_thickness" />
<java-symbol type="dimen" name="docked_stack_divider_insets" />
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/RadioServiceUserControllerTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/RadioServiceUserControllerTest.java
index 3e9e9922431b..516253b0ebff 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/RadioServiceUserControllerTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/RadioServiceUserControllerTest.java
@@ -58,7 +58,7 @@ public final class RadioServiceUserControllerTest extends ExtendedRadioMockitoTe
}
@Test
- public void isCurrentUser_forCurrentUser_returnsFalse() {
+ public void isCurrentOrSystemUser_forCurrentUser_returnsFalse() {
when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_1);
assertWithMessage("Current user")
@@ -66,7 +66,7 @@ public final class RadioServiceUserControllerTest extends ExtendedRadioMockitoTe
}
@Test
- public void isCurrentUser_forNonCurrentUser_returnsFalse() {
+ public void isCurrentOrSystemUser_forNonCurrentUser_returnsFalse() {
when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_2);
assertWithMessage("Non-current user")
@@ -74,7 +74,8 @@ public final class RadioServiceUserControllerTest extends ExtendedRadioMockitoTe
}
@Test
- public void isCurrentUser_forSystemUser_returnsTrue() {
+ public void isCurrentOrSystemUser_forSystemUser_returnsTrue() {
+ when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_1);
when(mUserHandleMock.getIdentifier()).thenReturn(UserHandle.USER_SYSTEM);
assertWithMessage("System user")
@@ -82,10 +83,26 @@ public final class RadioServiceUserControllerTest extends ExtendedRadioMockitoTe
}
@Test
- public void isCurrentUser_withActivityManagerFails_returnsFalse() {
- doThrow(new RuntimeException()).when(() -> ActivityManager.getCurrentUser());
+ public void isCurrentOrSystemUser_withActivityManagerFailure_returnsFalse() {
+ when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_1);
+ doThrow(new RuntimeException()).when(ActivityManager::getCurrentUser);
assertWithMessage("User when activity manager fails")
.that(RadioServiceUserController.isCurrentOrSystemUser()).isFalse();
}
+
+ @Test
+ public void getCurrentUser() {
+ assertWithMessage("Current user")
+ .that(RadioServiceUserController.getCurrentUser()).isEqualTo(USER_ID_1);
+ }
+
+ @Test
+ public void getCurrentUser_withActivityManagerFailure_returnsUserNull() {
+ when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_1);
+ doThrow(new RuntimeException()).when(ActivityManager::getCurrentUser);
+
+ assertWithMessage("Current user when activity manager fails")
+ .that(RadioServiceUserController.getCurrentUser()).isEqualTo(UserHandle.USER_NULL);
+ }
}
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
index 78b5a4ad71de..f85748c93c57 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
@@ -47,9 +47,11 @@ import android.hardware.radio.ProgramList;
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
import android.hardware.radio.RadioTuner;
+import android.os.Binder;
import android.os.ParcelableException;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -73,6 +75,8 @@ import java.util.Set;
*/
public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
+ private static final int USER_ID_1 = 11;
+ private static final int USER_ID_2 = 12;
private static final VerificationWithTimeout CALLBACK_TIMEOUT =
timeout(/* millis= */ 200);
private static final int SIGNAL_QUALITY = 90;
@@ -109,7 +113,10 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
SIGNAL_QUALITY);
// Mocks
- @Mock private IBroadcastRadio mBroadcastRadioMock;
+ @Mock
+ private UserHandle mUserHandleMock;
+ @Mock
+ private IBroadcastRadio mBroadcastRadioMock;
private android.hardware.radio.ITunerCallback[] mAidlTunerCallbackMocks;
// RadioModule under test
@@ -124,14 +131,18 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
@Override
protected void initializeSession(StaticMockitoSessionBuilder builder) {
- builder.spyStatic(RadioServiceUserController.class).spyStatic(CompatChanges.class);
+ builder.spyStatic(RadioServiceUserController.class).spyStatic(CompatChanges.class)
+ .spyStatic(Binder.class);
}
@Before
public void setup() throws Exception {
+ when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_1);
doReturn(true).when(() -> CompatChanges.isChangeEnabled(
eq(ConversionUtils.RADIO_U_VERSION_REQUIRED), anyInt()));
doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
+ doReturn(USER_ID_1).when(() -> RadioServiceUserController.getCurrentUser());
+ doReturn(mUserHandleMock).when(() -> Binder.getCallingUserHandle());
mRadioModule = new RadioModule(mBroadcastRadioMock,
AidlTestUtils.makeDefaultModuleProperties());
@@ -421,6 +432,21 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
}
@Test
+ public void tune_forSystemUser() throws Exception {
+ when(mUserHandleMock.getIdentifier()).thenReturn(UserHandle.USER_SYSTEM);
+ doReturn(mUserHandleMock).when(() -> Binder.getCallingUserHandle());
+ doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
+ ProgramSelector initialSel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
+ RadioManager.ProgramInfo tuneInfo =
+ AidlTestUtils.makeProgramInfo(initialSel, SIGNAL_QUALITY);
+ openAidlClients(/* numClients= */ 1);
+
+ mTunerSessions[0].tune(initialSel);
+
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onCurrentProgramInfoChanged(tuneInfo);
+ }
+
+ @Test
public void tune_withUnknownErrorFromHal_fails() throws Exception {
openAidlClients(/* numClients= */ 1);
ProgramSelector sel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
@@ -1136,6 +1162,19 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase {
}
@Test
+ public void onCurrentProgramInfoChanged_withNoncurrentUser_doesNotInvokeCallback()
+ throws Exception {
+ openAidlClients(1);
+ doReturn(USER_ID_2).when(() -> RadioServiceUserController.getCurrentUser());
+
+ mHalTunerCallback.onCurrentProgramInfoChanged(AidlTestUtils.makeHalProgramInfo(
+ AidlTestUtils.makeHalFmSelector(/* freq= */ 97300), SIGNAL_QUALITY));
+
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
+ .onCurrentProgramInfoChanged(any());
+ }
+
+ @Test
public void onAntennaStateChange_forTunerCallback() throws Exception {
int numSessions = 3;
openAidlClients(numSessions);
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java
index 3815008bd4fb..fac9eaafe94c 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TunerSessionHidlTest.java
@@ -46,8 +46,10 @@ import android.hardware.radio.ProgramList;
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
import android.hardware.radio.RadioTuner;
+import android.os.Binder;
import android.os.ParcelableException;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -74,6 +76,8 @@ import java.util.Map;
@RunWith(MockitoJUnitRunner.class)
public final class TunerSessionHidlTest extends ExtendedRadioMockitoTestCase {
+ private static final int USER_ID_1 = 11;
+ private static final int USER_ID_2 = 12;
private static final VerificationWithTimeout CALLBACK_TIMEOUT =
timeout(/* millis= */ 200);
private static final int SIGNAL_QUALITY = 1;
@@ -94,18 +98,25 @@ public final class TunerSessionHidlTest extends ExtendedRadioMockitoTestCase {
private ProgramInfo mHalCurrentInfo;
private TunerSession[] mTunerSessions;
- @Mock private IBroadcastRadio mBroadcastRadioMock;
- @Mock ITunerSession mHalTunerSessionMock;
+ @Mock
+ private UserHandle mUserHandleMock;
+ @Mock
+ private IBroadcastRadio mBroadcastRadioMock;
+ @Mock
+ ITunerSession mHalTunerSessionMock;
private android.hardware.radio.ITunerCallback[] mAidlTunerCallbackMocks;
@Override
protected void initializeSession(StaticMockitoSessionBuilder builder) {
- builder.spyStatic(RadioServiceUserController.class);
+ builder.spyStatic(RadioServiceUserController.class).spyStatic(Binder.class);
}
@Before
public void setup() throws Exception {
+ when(mUserHandleMock.getIdentifier()).thenReturn(USER_ID_1);
+ doReturn(mUserHandleMock).when(() -> Binder.getCallingUserHandle());
doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
+ doReturn(USER_ID_1).when(() -> RadioServiceUserController.getCurrentUser());
mRadioModule = new RadioModule(mBroadcastRadioMock,
TestUtils.makeDefaultModuleProperties());
@@ -387,6 +398,20 @@ public final class TunerSessionHidlTest extends ExtendedRadioMockitoTestCase {
}
@Test
+ public void tune_forSystemUser() throws Exception {
+ when(mUserHandleMock.getIdentifier()).thenReturn(UserHandle.USER_SYSTEM);
+ doReturn(mUserHandleMock).when(() -> Binder.getCallingUserHandle());
+ doReturn(true).when(() -> RadioServiceUserController.isCurrentOrSystemUser());
+ ProgramSelector initialSel = TestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
+ RadioManager.ProgramInfo tuneInfo = TestUtils.makeProgramInfo(initialSel, SIGNAL_QUALITY);
+ openAidlClients(/* numClients= */ 1);
+
+ mTunerSessions[0].tune(initialSel);
+
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onCurrentProgramInfoChanged(tuneInfo);
+ }
+
+ @Test
public void step_withDirectionUp() throws Exception {
long initFreq = AM_FM_FREQUENCY_LIST[1];
ProgramSelector initialSel = TestUtils.makeFmSelector(initFreq);
@@ -858,6 +883,19 @@ public final class TunerSessionHidlTest extends ExtendedRadioMockitoTestCase {
}
@Test
+ public void onCurrentProgramInfoChanged_withNoncurrentUser_doesNotInvokeCallback()
+ throws Exception {
+ openAidlClients(1);
+ doReturn(USER_ID_2).when(() -> RadioServiceUserController.getCurrentUser());
+
+ mHalTunerCallback.onCurrentProgramInfoChanged(TestUtils.makeHalProgramInfo(
+ TestUtils.makeHalFmSelector(/* freq= */ 97300), SIGNAL_QUALITY));
+
+ verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
+ .onCurrentProgramInfoChanged(any());
+ }
+
+ @Test
public void onConfigFlagUpdated_forTunerCallback() throws Exception {
int numSessions = 3;
openAidlClients(numSessions);
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index fb0f3d419002..af81957d1e03 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -62,7 +62,6 @@ import android.util.MergedConfiguration;
import android.view.Display;
import android.view.View;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
@@ -616,7 +615,6 @@ public class ActivityThreadTest {
}
@Test
- @FlakyTest(bugId = 176134235)
public void testHandleConfigurationChanged_DoesntOverrideActivityConfig() {
final TestActivity activity = mActivityTestRule.launchActivity(new Intent());
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java
index b917ac80256c..d9b73a8290f5 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java
@@ -83,10 +83,7 @@ class TaskFragmentAnimationRunner extends IRemoteAnimationRunner.Stub {
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
- if (TaskFragmentAnimationController.DEBUG) {
- Log.v(TAG, "onAnimationCancelled: isKeyguardOccluded=" + isKeyguardOccluded);
- }
+ public void onAnimationCancelled() {
mHandler.post(this::cancelAnimation);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java
index 22c90153bb39..edefe9e3ab06 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CrossActivityAnimation.java
@@ -404,7 +404,7 @@ class CrossActivityAnimation {
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
finishAnimation();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
index f0c5d8b29b2f..2d6ec7547187 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/CustomizeActivityAnimation.java
@@ -323,7 +323,7 @@ class CustomizeActivityAnimation {
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
finishAnimation();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 2afe8ee83391..b9ff5f0e820a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -282,6 +282,11 @@ public class BubbleStackView extends FrameLayout
/** Whether the expanded view has been hidden, because we are dragging out a bubble. */
private boolean mExpandedViewTemporarilyHidden = false;
+ /**
+ * Whether the last bubble is being removed when expanded, which impacts the collapse animation.
+ */
+ private boolean mRemovingLastBubbleWhileExpanded = false;
+
/** Animator for animating the expanded view's alpha (including the TaskView inside it). */
private final ValueAnimator mExpandedViewAlphaAnimator = ValueAnimator.ofFloat(0f, 1f);
@@ -765,7 +770,7 @@ public class BubbleStackView extends FrameLayout
// Update scrim
if (!mScrimAnimating) {
- showScrim(true);
+ showScrim(true, null /* runnable */);
}
}
}
@@ -880,6 +885,7 @@ public class BubbleStackView extends FrameLayout
final Runnable onBubbleAnimatedOut = () -> {
if (getBubbleCount() == 0) {
+ mExpandedViewTemporarilyHidden = false;
mBubbleController.onAllBubblesAnimatedOut();
}
};
@@ -1773,6 +1779,20 @@ public class BubbleStackView extends FrameLayout
if (DEBUG_BUBBLE_STACK_VIEW) {
Log.d(TAG, "removeBubble: " + bubble);
}
+ if (isExpanded() && getBubbleCount() == 1) {
+ mRemovingLastBubbleWhileExpanded = true;
+ // We're expanded while the last bubble is being removed. Let the scrim animate away
+ // and then remove our views (removing the icon view triggers the removal of the
+ // bubble window so do that at the end of the animation so we see the scrim animate).
+ showScrim(false, () -> {
+ mRemovingLastBubbleWhileExpanded = false;
+ bubble.cleanupExpandedView();
+ mBubbleContainer.removeView(bubble.getIconView());
+ bubble.cleanupViews(); // cleans up the icon view
+ updateExpandedView(); // resets state for no expanded bubble
+ });
+ return;
+ }
// Remove it from the views
for (int i = 0; i < getBubbleCount(); i++) {
View v = mBubbleContainer.getChildAt(i);
@@ -2143,7 +2163,7 @@ public class BubbleStackView extends FrameLayout
mExpandedViewAlphaAnimator.start();
}
- private void showScrim(boolean show) {
+ private void showScrim(boolean show, Runnable after) {
AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
@@ -2153,6 +2173,9 @@ public class BubbleStackView extends FrameLayout
@Override
public void onAnimationEnd(Animator animation) {
mScrimAnimating = false;
+ if (after != null) {
+ after.run();
+ }
}
};
if (show) {
@@ -2179,7 +2202,7 @@ public class BubbleStackView extends FrameLayout
}
beforeExpandedViewAnimation();
- showScrim(true);
+ showScrim(true, null /* runnable */);
updateZOrder();
updateBadges(false /* setBadgeForCollapsedStack */);
mBubbleContainer.setActiveController(mExpandedAnimationController);
@@ -2303,7 +2326,10 @@ public class BubbleStackView extends FrameLayout
mIsExpanded = false;
mIsExpansionAnimating = true;
- showScrim(false);
+ if (!mRemovingLastBubbleWhileExpanded) {
+ // When we remove the last bubble it animates the scrim.
+ showScrim(false, null /* runnable */);
+ }
mBubbleContainer.cancelAllAnimations();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 2f25511a1f4d..643245943916 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -460,7 +460,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
}
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
final WindowContainerTransaction evictWct = new WindowContainerTransaction();
mStageCoordinator.prepareEvictInvisibleChildTasks(evictWct);
mSyncQueue.queue(evictWct);
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 49e8227c98f1..4c903f500651 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
@@ -483,7 +483,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
if (isEnteringSplit) {
mMainExecutor.execute(() -> exitSplitScreen(
mSideStage.getChildCount() == 0 ? mMainStage : mSideStage,
@@ -869,7 +869,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
onRemoteAnimationFinished(apps);
t.apply();
try {
- adapter.getRunner().onAnimationCancelled(mKeyguardShowing);
+ adapter.getRunner().onAnimationCancelled();
} catch (RemoteException e) {
Slog.e(TAG, "Error starting remote animation", e);
}
@@ -1013,11 +1013,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
onRemoteAnimationFinishedOrCancelled(evictWct);
setDividerVisibility(true, null);
try {
- adapter.getRunner().onAnimationCancelled(isKeyguardOccluded);
+ adapter.getRunner().onAnimationCancelled();
} catch (RemoteException e) {
Slog.e(TAG, "Error starting remote animation", e);
}
@@ -1038,7 +1038,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
onRemoteAnimationFinished(apps);
t.apply();
try {
- adapter.getRunner().onAnimationCancelled(mKeyguardShowing);
+ adapter.getRunner().onAnimationCancelled();
} catch (RemoteException e) {
Slog.e(TAG, "Error starting remote animation", e);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/LegacyTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/LegacyTransitions.java
index 61e92f355dc2..61e11e877b90 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/LegacyTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/LegacyTransitions.java
@@ -107,7 +107,7 @@ public class LegacyTransitions {
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) throws RemoteException {
+ public void onAnimationCancelled() throws RemoteException {
mCancelled = true;
mApps = mWallpapers = mNonApps = null;
checkApply();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
index 5b7231c5a5fb..ef2a511177b2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/RemoteTransitionHandler.java
@@ -94,9 +94,11 @@ public class RemoteTransitionHandler implements Transitions.TransitionHandler {
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
- if (!Transitions.SHELL_TRANSITIONS_ROTATION && TransitionUtil.hasDisplayChange(info)) {
+ if (!Transitions.SHELL_TRANSITIONS_ROTATION && TransitionUtil.hasDisplayChange(info)
+ && !TransitionUtil.alwaysReportToKeyguard(info)) {
// Note that if the remote doesn't have permission ACCESS_SURFACE_FLINGER, some
// operations of the start transaction may be ignored.
+ mRequestedRemotes.remove(transition);
return false;
}
RemoteTransition pendingRemote = mRequestedRemotes.get(transition);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 5c8791effe18..a4057b1328f4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -650,7 +650,7 @@ public class Transitions implements RemoteCallable<Transitions> {
active.mToken, info, active.mStartT, active.mFinishT);
}
- if (info.getRootCount() == 0 && !alwaysReportToKeyguard(info)) {
+ if (info.getRootCount() == 0 && !TransitionUtil.alwaysReportToKeyguard(info)) {
// No root-leashes implies that the transition is empty/no-op, so just do
// housekeeping and return.
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "No transition roots in %s so"
@@ -699,23 +699,6 @@ public class Transitions implements RemoteCallable<Transitions> {
return true;
}
- /**
- * Some transitions we always need to report to keyguard even if they are empty.
- * TODO (b/274954192): Remove this once keyguard dispatching moves to Shell.
- */
- private static boolean alwaysReportToKeyguard(TransitionInfo info) {
- // occlusion status of activities can change while screen is off so there will be no
- // visibility change but we still need keyguardservice to be notified.
- if (info.getType() == TRANSIT_KEYGUARD_UNOCCLUDE) return true;
-
- // It's possible for some activities to stop with bad timing (esp. since we can't yet
- // queue activity transitions initiated by apps) that results in an empty transition for
- // keyguard going-away. In general, we should should always report Keyguard-going-away.
- if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) return true;
-
- return false;
- }
-
private boolean areTracksIdle() {
for (int i = 0; i < mTracks.size(); ++i) {
if (!mTracks.get(i).isIdle()) return false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
index ce102917352d..c5cd2d91eb39 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/TransitionUtil.java
@@ -24,7 +24,9 @@ import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
+import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_KEYGUARD_GOING_AWAY;
+import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE;
import static android.view.WindowManager.TRANSIT_OPEN;
import static android.view.WindowManager.TRANSIT_TO_BACK;
import static android.view.WindowManager.TRANSIT_TO_FRONT;
@@ -77,6 +79,23 @@ public class TransitionUtil {
return false;
}
+ /**
+ * Some transitions we always need to report to keyguard even if they are empty.
+ * TODO (b/274954192): Remove this once keyguard dispatching moves to Shell.
+ */
+ public static boolean alwaysReportToKeyguard(TransitionInfo info) {
+ // occlusion status of activities can change while screen is off so there will be no
+ // visibility change but we still need keyguardservice to be notified.
+ if (info.getType() == TRANSIT_KEYGUARD_UNOCCLUDE) return true;
+
+ // It's possible for some activities to stop with bad timing (esp. since we can't yet
+ // queue activity transitions initiated by apps) that results in an empty transition for
+ // keyguard going-away. In general, we should should always report Keyguard-going-away.
+ if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) return true;
+
+ return false;
+ }
+
/** Returns `true` if `change` is a wallpaper. */
public static boolean isWallpaper(TransitionInfo.Change change) {
return (change.getTaskInfo() == null)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index f9fdd831a42c..836efe0347c3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -23,6 +23,7 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
+import android.content.res.TypedArray;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.Region;
@@ -95,7 +96,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
private int mWindowingPillHeight;
private int mMoreActionsPillHeight;
private int mShadowRadius;
- private int mCornerRadius;
+ private int mMenuCornerRadius;
DesktopModeWindowDecoration(
Context context,
@@ -182,6 +183,11 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
mRelayoutParams.mShadowRadiusId = shadowRadiusID;
mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw;
+ final TypedArray ta = mContext.obtainStyledAttributes(
+ new int[]{android.R.attr.dialogCornerRadius});
+ mRelayoutParams.mCornerRadius = ta.getDimensionPixelSize(0, 0);
+ ta.recycle();
+
relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);
// After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index e772fc25f8cf..ac5ff2075901 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -16,6 +16,8 @@
package com.android.wm.shell.windowdecor;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.res.Configuration;
@@ -256,13 +258,17 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
mTmpColor[0] = (float) Color.red(backgroundColorInt) / 255.f;
mTmpColor[1] = (float) Color.green(backgroundColorInt) / 255.f;
mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f;
- Point taskPosition = mTaskInfo.positionInParent;
+ final Point taskPosition = mTaskInfo.positionInParent;
startT.setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight)
.setShadowRadius(mTaskSurface, shadowRadius)
.setColor(mTaskSurface, mTmpColor)
.show(mTaskSurface);
finishT.setPosition(mTaskSurface, taskPosition.x, taskPosition.y)
.setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight);
+ if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
+ startT.setCornerRadius(mTaskSurface, params.mCornerRadius);
+ finishT.setCornerRadius(mTaskSurface, params.mCornerRadius);
+ }
if (mCaptionWindowManager == null) {
// Put caption under a container surface because ViewRootImpl sets the destination frame
@@ -414,6 +420,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
int mCaptionWidthId;
int mShadowRadiusId;
+ int mCornerRadius;
+
int mCaptionX;
int mCaptionY;
@@ -425,6 +433,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
mCaptionWidthId = Resources.ID_NULL;
mShadowRadiusId = Resources.ID_NULL;
+ mCornerRadius = 0;
+
mCaptionX = 0;
mCaptionY = 0;
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
index c5ee7b722617..86edc25b64d3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
@@ -18,7 +18,7 @@ package com.android.wm.shell.flicker
import android.app.Instrumentation
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerBuilderProvider
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
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 45024f387c25..798cc95c020f 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
@@ -20,9 +20,9 @@ package com.android.wm.shell.flicker
import android.tools.common.Rotation
import android.tools.common.datatypes.Region
-import android.tools.common.datatypes.component.IComponentMatcher
import android.tools.common.flicker.subject.layers.LayerTraceEntrySubject
import android.tools.common.flicker.subject.layers.LayersTraceSubject
+import android.tools.common.traces.component.IComponentMatcher
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.helpers.WindowUtils
@@ -218,11 +218,11 @@ fun FlickerTest.splitAppLayerBoundsChanges(
assertLayers {
if (landscapePosLeft) {
splitAppLayerBoundsSnapToDivider(
- component,
- landscapePosLeft,
- portraitPosTop,
- scenario.endRotation
- )
+ component,
+ landscapePosLeft,
+ portraitPosTop,
+ scenario.endRotation
+ )
} else {
splitAppLayerBoundsSnapToDivider(
component,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
index 983640a70c4b..3bc1e2acd015 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
@@ -18,7 +18,7 @@
package com.android.wm.shell.flicker
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
const val SYSTEM_UI_PACKAGE_NAME = "com.android.systemui"
const val LAUNCHER_UI_PACKAGE_NAME = "com.google.android.apps.nexuslauncher"
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt
index d01a0ee67f25..11c5951faa1f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/BaseAppCompat.kt
@@ -20,11 +20,11 @@ import android.content.Context
import android.system.helpers.CommandsHelper
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
-import com.android.wm.shell.flicker.BaseTest
-import com.android.server.wm.flicker.helpers.setRotation
-import com.android.server.wm.flicker.helpers.LetterboxAppHelper
import android.tools.device.flicker.legacy.FlickerTestFactory
import android.tools.device.flicker.legacy.IFlickerTestData
+import com.android.server.wm.flicker.helpers.LetterboxAppHelper
+import com.android.server.wm.flicker.helpers.setRotation
+import com.android.wm.shell.flicker.BaseTest
import com.android.wm.shell.flicker.appWindowIsVisibleAtEnd
import com.android.wm.shell.flicker.appWindowIsVisibleAtStart
import org.junit.Assume
@@ -104,8 +104,8 @@ abstract class BaseAppCompat(flicker: FlickerTest) : BaseTest(flicker) {
/**
* Creates the test configurations.
*
- * See [FlickerTestFactory.rotationTests] for configuring screen orientation and
- * navigation modes.
+ * See [FlickerTestFactory.rotationTests] for configuring screen orientation and navigation
+ * modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt
index c57100e44c17..f212a4e0417e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/OpenAppInSizeCompatModeTest.kt
@@ -17,11 +17,11 @@
package com.android.wm.shell.flicker.appcompat
import android.platform.test.annotations.Postsubmit
-import androidx.test.filters.RequiresDevice
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import androidx.test.filters.RequiresDevice
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@@ -35,13 +35,13 @@ import org.junit.runners.Parameterized
* ```
* Rotate non resizable portrait only app to opposite orientation to trigger size compat mode
* ```
+ *
* Notes:
* ```
* Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [BaseTest]
* ```
*/
-
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -86,4 +86,4 @@ class OpenAppInSizeCompatModeTest(flicker: FlickerTest) : BaseAppCompat(flicker)
.isInvisible(ComponentNameMatcher.ROTATION)
}
}
-} \ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt
index f111a8d62d83..8e75439889b2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/appcompat/RestartAppInSizeCompatModeTest.kt
@@ -17,11 +17,11 @@
package com.android.wm.shell.flicker.appcompat
import android.platform.test.annotations.Postsubmit
-import androidx.test.filters.RequiresDevice
+import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
-import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.helpers.WindowUtils
+import androidx.test.filters.RequiresDevice
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@@ -36,13 +36,13 @@ import org.junit.runners.Parameterized
* Rotate app to opposite orientation to trigger size compat mode
* Press restart button and wait for letterboxed app to resize
* ```
+ *
* Notes:
* ```
* Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [BaseTest]
* ```
*/
-
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -56,9 +56,7 @@ class RestartAppInSizeCompatModeTest(flicker: FlickerTest) : BaseAppCompat(flick
teardown { letterboxApp.exit(wmHelper) }
}
- @Postsubmit
- @Test
- fun appVisibleAtStartAndEnd() = assertLetterboxAppVisibleAtStartAndEnd()
+ @Postsubmit @Test fun appVisibleAtStartAndEnd() = assertLetterboxAppVisibleAtStartAndEnd()
@Postsubmit
@Test
@@ -83,4 +81,4 @@ class RestartAppInSizeCompatModeTest(flicker: FlickerTest) : BaseAppCompat(flick
val displayBounds = WindowUtils.getDisplayBounds(flicker.scenario.endRotation)
flicker.assertLayersEnd { visibleRegion(letterboxApp).coversAtMost(displayBounds) }
}
-} \ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt
index 18a3aa79f6e2..889e1771593d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/OpenActivityFromBubbleOnLocksreenTest.kt
@@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.bubble
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Postsubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
@@ -149,9 +149,7 @@ class OpenActivityFromBubbleOnLocksreenTest(flicker: FlickerTest) : BaseBubbleSc
@Ignore("Not applicable to this CUJ. Taskbar is not shown on lock screen")
override fun taskBarWindowIsAlwaysVisible() {}
- /**
- * Checks that the [ComponentNameMatcher.TASK_BAR] is visible at the end of the transition
- */
+ /** Checks that the [ComponentNameMatcher.TASK_BAR] is visible at the end of the transition */
@Postsubmit
@Test
fun taskBarLayerIsVisibleAtEnd() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
index 59918fb7b6a9..e6544c9f39bc 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipBySwipingDownTest.kt
@@ -17,7 +17,7 @@
package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
index 36c6f7c438c4..2417c45bf9a0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ClosePipTransition.kt
@@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.LAUNCHER
+import android.tools.common.traces.component.ComponentNameMatcher.Companion.LAUNCHER
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.flicker.legacy.FlickerTestFactory
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
index db18edba9cc4..4b4613704a16 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientation.kt
@@ -21,7 +21,7 @@ import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
index 51f01364ec9c..bfd57786e615 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTransition.kt
@@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.flicker.legacy.FlickerTestFactory
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
index 2001f484ed96..5ac9829b6c8f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
@@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.flicker.legacy.FlickerTestFactory
import com.android.server.wm.flicker.helpers.SimpleAppHelper
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
index 6deba1b68f38..bbb1c6c2ac63 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
@@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
index a626713aaa11..6b061bbb1565 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipOnImeVisibilityChangeTest.kt
@@ -18,7 +18,7 @@ package com.android.wm.shell.flicker.pip
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
index b30f30830156..eb1245b9ab86 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
@@ -20,7 +20,7 @@ import android.app.Instrumentation
import android.content.Intent
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
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 0c9c16153ea3..d53eac073e6b 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
@@ -19,8 +19,8 @@ package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
-import android.tools.common.datatypes.component.EdgeExtensionComponentMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.common.traces.component.EdgeExtensionComponentMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
index 625987a2e7ef..1063dfd8d737 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
@@ -19,9 +19,9 @@ package com.android.wm.shell.flicker.splitscreen
import android.app.Instrumentation
import android.graphics.Point
import android.os.SystemClock
-import android.tools.common.datatypes.component.ComponentNameMatcher
-import android.tools.common.datatypes.component.IComponentMatcher
-import android.tools.common.datatypes.component.IComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.common.traces.component.IComponentMatcher
+import android.tools.common.traces.component.IComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.WindowManagerStateHelper
import android.tools.device.traces.parsers.toFlickerComponent
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index fc4bfd9754a0..5a2326b9c393 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -16,6 +16,8 @@
package com.android.wm.shell.windowdecor;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+
import static com.android.wm.shell.MockSurfaceControlHelper.createMockSurfaceControlBuilder;
import static com.android.wm.shell.MockSurfaceControlHelper.createMockSurfaceControlTransaction;
@@ -86,6 +88,7 @@ import java.util.function.Supplier;
public class WindowDecorationTests extends ShellTestCase {
private static final Rect TASK_BOUNDS = new Rect(100, 300, 400, 400);
private static final Point TASK_POSITION_IN_PARENT = new Point(40, 60);
+ private static final int CORNER_RADIUS = 20;
private final WindowDecoration.RelayoutResult<TestView> mRelayoutResult =
new WindowDecoration.RelayoutResult<>();
@@ -130,6 +133,7 @@ public class WindowDecorationTests extends ShellTestCase {
mCaptionMenuShadowRadiusId = R.dimen.test_caption_menu_shadow_radius;
mCaptionMenuCornerRadiusId = R.dimen.test_caption_menu_corner_radius;
mRelayoutParams.mShadowRadiusId = R.dimen.test_window_decor_shadow_radius;
+ mRelayoutParams.mCornerRadius = CORNER_RADIUS;
doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
.create(any(), any(), any());
@@ -209,6 +213,7 @@ public class WindowDecorationTests extends ShellTestCase {
.setBounds(TASK_BOUNDS)
.setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y)
.setVisible(true)
+ .setWindowingMode(WINDOWING_MODE_FREEFORM)
.build();
taskInfo.isFocused = true;
// Density is 2. Shadow radius is 10px. Caption height is 64px.
@@ -249,6 +254,8 @@ public class WindowDecorationTests extends ShellTestCase {
.setPosition(taskSurface, TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y);
verify(mMockSurfaceControlFinishT)
.setWindowCrop(taskSurface, 300, 100);
+ verify(mMockSurfaceControlStartT).setCornerRadius(taskSurface, CORNER_RADIUS);
+ verify(mMockSurfaceControlFinishT).setCornerRadius(taskSurface, CORNER_RADIUS);
verify(mMockSurfaceControlStartT)
.show(taskSurface);
verify(mMockSurfaceControlStartT)
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 193544edbf99..88b9643c12c1 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -934,13 +934,25 @@ public final class MediaCodecInfo {
}
}
levelCaps = createFromProfileLevel(mMime, profile, maxLevel);
- // remove profile from this format otherwise levelCaps.isFormatSupported will
- // get into this same conditon and loop forever.
- Map<String, Object> mapWithoutProfile = new HashMap<>(map);
- mapWithoutProfile.remove(MediaFormat.KEY_PROFILE);
- MediaFormat formatWithoutProfile = new MediaFormat(mapWithoutProfile);
- if (levelCaps != null && !levelCaps.isFormatSupported(formatWithoutProfile)) {
- return false;
+ // We must remove the profile from this format otherwise levelCaps.isFormatSupported
+ // will get into this same condition and loop forever. Furthermore, since levelCaps
+ // does not contain features and bitrate specific keys, keep only keys relevant for
+ // a level check.
+ Map<String, Object> levelCriticalFormatMap = new HashMap<>(map);
+ final Set<String> criticalKeys =
+ isVideo() ? VideoCapabilities.VIDEO_LEVEL_CRITICAL_FORMAT_KEYS :
+ isAudio() ? AudioCapabilities.AUDIO_LEVEL_CRITICAL_FORMAT_KEYS :
+ null;
+
+ // critical keys will always contain KEY_MIME, but should also contain others to be
+ // meaningful
+ if (criticalKeys != null && criticalKeys.size() > 1 && levelCaps != null) {
+ levelCriticalFormatMap.keySet().retainAll(criticalKeys);
+
+ MediaFormat levelCriticalFormat = new MediaFormat(levelCriticalFormatMap);
+ if (!levelCaps.isFormatSupported(levelCriticalFormat)) {
+ return false;
+ }
}
}
if (mAudioCaps != null && !mAudioCaps.supportsFormat(format)) {
@@ -1633,6 +1645,16 @@ public final class MediaCodecInfo {
}
}
+ /* package private */
+ // must not contain KEY_PROFILE
+ static final Set<String> AUDIO_LEVEL_CRITICAL_FORMAT_KEYS = Set.of(
+ // We don't set level-specific limits for audio codecs today. Key candidates would
+ // be sample rate, bit rate or channel count.
+ // MediaFormat.KEY_SAMPLE_RATE,
+ // MediaFormat.KEY_CHANNEL_COUNT,
+ // MediaFormat.KEY_BIT_RATE,
+ MediaFormat.KEY_MIME);
+
/** @hide */
public boolean supportsFormat(MediaFormat format) {
Map<String, Object> map = format.getMap();
@@ -2357,6 +2379,15 @@ public final class MediaCodecInfo {
return ok;
}
+ /* package private */
+ // must not contain KEY_PROFILE
+ static final Set<String> VIDEO_LEVEL_CRITICAL_FORMAT_KEYS = Set.of(
+ MediaFormat.KEY_WIDTH,
+ MediaFormat.KEY_HEIGHT,
+ MediaFormat.KEY_FRAME_RATE,
+ MediaFormat.KEY_BIT_RATE,
+ MediaFormat.KEY_MIME);
+
/**
* @hide
* @throws java.lang.ClassCastException */
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index b6d70afa85b7..783528711877 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -54,7 +54,6 @@ import android.util.Slog;
import com.android.internal.app.ISoundTriggerService;
import com.android.internal.app.ISoundTriggerSession;
-import com.android.internal.util.Preconditions;
import java.util.HashMap;
import java.util.List;
@@ -67,6 +66,8 @@ import java.util.concurrent.Executor;
* models. Usage of this class is restricted to system or signature applications only. This allows
* OEMs to write apps that can manage non-voice based sound trigger models.
*
+ * If no ST module is available, {@link getModuleProperties()} will return {@code null}, and all
+ * other methods will throw {@link IllegalStateException}.
* @hide
*/
@SystemApi
@@ -82,7 +83,7 @@ public final class SoundTriggerManager {
// Stores a mapping from the sound model UUID to the SoundTriggerInstance created by
// the createSoundTriggerDetector() call.
- private final HashMap<UUID, SoundTriggerDetector> mReceiverInstanceMap;
+ private final HashMap<UUID, SoundTriggerDetector> mReceiverInstanceMap = new HashMap<>();
/**
* @hide
@@ -121,7 +122,6 @@ public final class SoundTriggerManager {
}
mContext = context;
mSoundTriggerService = soundTriggerService;
- mReceiverInstanceMap = new HashMap<UUID, SoundTriggerDetector>();
}
/**
@@ -160,7 +160,7 @@ public final class SoundTriggerManager {
.findFirst()
.orElse(null);
if (moduleProps == null) {
- throw new IllegalStateException("Fake ST HAL should always be available");
+ throw new AssertionError("Fake ST HAL should always be available");
}
return moduleProps;
}
@@ -183,7 +183,6 @@ public final class SoundTriggerManager {
}
mContext = Objects.requireNonNull(context);
mSoundTriggerService = Objects.requireNonNull(soundTriggerService);
- mReceiverInstanceMap = new HashMap<UUID, SoundTriggerDetector>();
}
/**
@@ -241,7 +240,8 @@ public final class SoundTriggerManager {
}
try {
GenericSoundModel model =
- mSoundTriggerSession.getSoundModel(new ParcelUuid(soundModelId));
+ mSoundTriggerSession.getSoundModel(
+ new ParcelUuid(Objects.requireNonNull(soundModelId)));
if (model == null) {
return null;
}
@@ -265,7 +265,8 @@ public final class SoundTriggerManager {
}
try {
- mSoundTriggerSession.deleteSoundModel(new ParcelUuid(soundModelId));
+ mSoundTriggerSession.deleteSoundModel(
+ new ParcelUuid(Objects.requireNonNull(soundModelId)));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -291,8 +292,8 @@ public final class SoundTriggerManager {
@RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
public SoundTriggerDetector createSoundTriggerDetector(UUID soundModelId,
@NonNull SoundTriggerDetector.Callback callback, @Nullable Handler handler) {
- if (soundModelId == null || mSoundTriggerSession == null) {
- return null;
+ if (mSoundTriggerSession == null) {
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
SoundTriggerDetector oldInstance = mReceiverInstanceMap.get(soundModelId);
@@ -301,7 +302,8 @@ public final class SoundTriggerManager {
}
try {
SoundTriggerDetector newInstance = new SoundTriggerDetector(mSoundTriggerSession,
- mSoundTriggerSession.getSoundModel(new ParcelUuid(soundModelId)),
+ mSoundTriggerSession.getSoundModel(
+ new ParcelUuid(Objects.requireNonNull(soundModelId))),
callback, handler);
mReceiverInstanceMap.put(soundModelId, newInstance);
return newInstance;
@@ -469,8 +471,8 @@ public final class SoundTriggerManager {
@UnsupportedAppUsage
@TestApi
public int loadSoundModel(@NonNull SoundModel soundModel) {
- if (soundModel == null || mSoundTriggerSession == null) {
- return STATUS_ERROR;
+ if (mSoundTriggerSession == null) {
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
try {
@@ -513,11 +515,11 @@ public final class SoundTriggerManager {
@UnsupportedAppUsage
public int startRecognition(@NonNull UUID soundModelId, @Nullable Bundle params,
@NonNull ComponentName detectionService, @NonNull RecognitionConfig config) {
- Preconditions.checkNotNull(soundModelId);
- Preconditions.checkNotNull(detectionService);
- Preconditions.checkNotNull(config);
+ Objects.requireNonNull(soundModelId);
+ Objects.requireNonNull(detectionService);
+ Objects.requireNonNull(config);
if (mSoundTriggerSession == null) {
- return STATUS_ERROR;
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
try {
return mSoundTriggerSession.startRecognitionForService(new ParcelUuid(soundModelId),
@@ -534,11 +536,12 @@ public final class SoundTriggerManager {
@RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int stopRecognition(UUID soundModelId) {
- if (soundModelId == null || mSoundTriggerSession == null) {
- return STATUS_ERROR;
+ if (mSoundTriggerSession == null) {
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
try {
- return mSoundTriggerSession.stopRecognitionForService(new ParcelUuid(soundModelId));
+ return mSoundTriggerSession.stopRecognitionForService(
+ new ParcelUuid(Objects.requireNonNull(soundModelId)));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -551,12 +554,12 @@ public final class SoundTriggerManager {
@RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public int unloadSoundModel(UUID soundModelId) {
- if (soundModelId == null || mSoundTriggerSession == null) {
- return STATUS_ERROR;
+ if (mSoundTriggerSession == null) {
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
try {
return mSoundTriggerSession.unloadSoundModel(
- new ParcelUuid(soundModelId));
+ new ParcelUuid(Objects.requireNonNull(soundModelId)));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -604,7 +607,10 @@ public final class SoundTriggerManager {
@RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
@UnsupportedAppUsage
public int getModelState(UUID soundModelId) {
- if (soundModelId == null || mSoundTriggerSession == null) {
+ if (mSoundTriggerSession == null) {
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
+ }
+ if (soundModelId == null) {
return STATUS_ERROR;
}
try {
@@ -652,11 +658,12 @@ public final class SoundTriggerManager {
public int setParameter(@Nullable UUID soundModelId,
@ModelParams int modelParam, int value) {
if (mSoundTriggerSession == null) {
- return SoundTrigger.STATUS_INVALID_OPERATION;
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
try {
- return mSoundTriggerSession.setParameter(new ParcelUuid(soundModelId), modelParam,
+ return mSoundTriggerSession.setParameter(
+ new ParcelUuid(Objects.requireNonNull(soundModelId)), modelParam,
value);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -679,11 +686,11 @@ public final class SoundTriggerManager {
public int getParameter(@NonNull UUID soundModelId,
@ModelParams int modelParam) {
if (mSoundTriggerSession == null) {
- throw new IllegalArgumentException("Sound model is not loaded: "
- + soundModelId.toString());
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
try {
- return mSoundTriggerSession.getParameter(new ParcelUuid(soundModelId), modelParam);
+ return mSoundTriggerSession.getParameter(
+ new ParcelUuid(Objects.requireNonNull(soundModelId)), modelParam);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -703,10 +710,11 @@ public final class SoundTriggerManager {
public ModelParamRange queryParameter(@Nullable UUID soundModelId,
@ModelParams int modelParam) {
if (mSoundTriggerSession == null) {
- return null;
+ throw new IllegalStateException("No underlying SoundTriggerModule available");
}
try {
- return mSoundTriggerSession.queryParameter(new ParcelUuid(soundModelId), modelParam);
+ return mSoundTriggerSession.queryParameter(
+ new ParcelUuid(Objects.requireNonNull(soundModelId)), modelParam);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 95522001d342..44aff6408f5b 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -385,6 +385,10 @@ android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz, jobject piidParcel)
process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." );
+ if (env->ExceptionCheck()) {
+ return UNKNOWN_ERROR;
+ }
+
// update the piid
Parcel *request = parcelForJavaObject(env, piidParcel);
auto reply = std::make_unique<Parcel>();
@@ -407,6 +411,10 @@ android_media_MediaPlayer_prepareAsync(JNIEnv *env, jobject thiz, jobject piidPa
process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." );
+ if (env->ExceptionCheck()) {
+ return UNKNOWN_ERROR;
+ }
+
// update the piid
Parcel *request = parcelForJavaObject(env, piidParcel);
auto reply = std::make_unique<Parcel>();
diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml
index 905e0ca92733..a3b27529d857 100644
--- a/packages/CredentialManager/res/values/strings.xml
+++ b/packages/CredentialManager/res/values/strings.xml
@@ -114,13 +114,13 @@
<!-- Strings for the get flow. -->
<!-- This appears as the title of the modal bottom sheet asking for user confirmation to use the single previously saved passkey to sign in to the app. [CHAR LIMIT=200] -->
<string name="get_dialog_title_use_passkey_for">Use your saved passkey for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
- <!-- This appears as the title of the dialog asking for user confirmation to use the single previously saved credential to sign in to the app. [CHAR LIMIT=200] -->
- <string name="get_dialog_title_use_sign_in_for">Use your saved sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
- <!-- This appears as the title of the dialog asking for user to make a choice from various previously saved credentials to sign in to the app. [CHAR LIMIT=200] -->
- <string name="get_dialog_title_choose_sign_in_for">Choose a saved sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
- <!-- This appears as the title of the dialog asking for user to make a choice from various previously saved credentials to sign in to the app. [CHAR LIMIT=200] -->
+ <!-- This appears as the title of the dialog asking for user confirmation to use the single user credential (previously saved or to be created) to sign in to the app. [CHAR LIMIT=200] -->
+ <string name="get_dialog_title_use_sign_in_for">Use your sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
+ <!-- This appears as the title of the dialog asking for user to make a choice from various available user credentials (previously saved or to be created) to sign in to the app. [CHAR LIMIT=200] -->
+ <string name="get_dialog_title_choose_sign_in_for">Choose a sign-in for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
+ <!-- This appears as the title of the dialog asking for user to make a choice from options of available user information (e.g. driver's license, vaccination status) to pass to the app. [CHAR LIMIT=200] -->
<string name="get_dialog_title_choose_option_for">Choose an option for <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
- <!-- This appears as the title of the dialog asking user to use a previously saved credentials to sign in to the app. [CHAR LIMIT=200] -->
+ <!-- This appears as the title of the dialog asking user to send a piece of user information (e.g. driver's license, vaccination status) to the app. [CHAR LIMIT=200] -->
<string name="get_dialog_title_use_info_on">Use this info on <xliff:g id="app_name" example="YouTube">%1$s</xliff:g>?</string>
<!-- This is a label for a button that links the user to different sign-in methods . [CHAR LIMIT=80] -->
<string name="get_dialog_use_saved_passkey_for">Sign in another way</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 45c0d7823e99..adaf4a1d3ab5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -14,7 +14,9 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
@@ -26,6 +28,8 @@ import android.net.NetworkKey;
import android.net.NetworkRequest;
import android.net.NetworkScoreManager;
import android.net.ScoredNetwork;
+import android.net.TransportInfo;
+import android.net.vcn.VcnTransportInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkScoreCache;
@@ -34,8 +38,9 @@ import android.os.HandlerThread;
import android.os.Looper;
import android.provider.Settings;
+import androidx.annotation.Nullable;
+
import com.android.settingslib.R;
-import com.android.settingslib.Utils;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
@@ -46,6 +51,7 @@ import java.util.Set;
/**
* Track status of Wi-Fi for the Sys UI.
*/
+@SuppressLint("MissingPermission")
public class WifiStatusTracker {
private static final int HISTORY_SIZE = 32;
private static final SimpleDateFormat SSDF = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
@@ -66,8 +72,9 @@ public class WifiStatusTracker {
private final NetworkRequest mNetworkRequest = new NetworkRequest.Builder()
.clearCapabilities()
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
- .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build();
+ .addTransportType(TRANSPORT_WIFI)
+ .addTransportType(TRANSPORT_CELLULAR)
+ .build();
private final NetworkCallback mNetworkCallback =
new NetworkCallback(NetworkCallback.FLAG_INCLUDE_LOCATION_INFO) {
// Note: onCapabilitiesChanged is guaranteed to be called "immediately" after onAvailable
@@ -75,18 +82,10 @@ public class WifiStatusTracker {
@Override
public void onCapabilitiesChanged(
Network network, NetworkCapabilities networkCapabilities) {
- boolean isVcnOverWifi = false;
- boolean isWifi = false;
- WifiInfo wifiInfo = null;
- if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
- wifiInfo = Utils.tryGetWifiInfoForVcn(networkCapabilities);
- isVcnOverWifi = (wifiInfo != null);
- } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
- wifiInfo = (WifiInfo) networkCapabilities.getTransportInfo();
- isWifi = true;
- }
+ WifiInfo wifiInfo = getMainOrUnderlyingWifiInfo(networkCapabilities);
+ boolean isWifi = connectionIsWifi(networkCapabilities, wifiInfo);
// As long as it is a WiFi network, we will log it in the dumpsys for debugging.
- if (isVcnOverWifi || isWifi) {
+ if (isWifi) {
String log = new StringBuilder()
.append(SSDF.format(System.currentTimeMillis())).append(",")
.append("onCapabilitiesChanged: ")
@@ -303,17 +302,8 @@ public class WifiStatusTracker {
return;
}
NetworkCapabilities networkCapabilities;
- isDefaultNetwork = false;
- if (mDefaultNetworkCapabilities != null) {
- boolean isWifi = mDefaultNetworkCapabilities.hasTransport(
- NetworkCapabilities.TRANSPORT_WIFI);
- boolean isVcnOverWifi = mDefaultNetworkCapabilities.hasTransport(
- NetworkCapabilities.TRANSPORT_CELLULAR)
- && (Utils.tryGetWifiInfoForVcn(mDefaultNetworkCapabilities) != null);
- if (isWifi || isVcnOverWifi) {
- isDefaultNetwork = true;
- }
- }
+ isDefaultNetwork = mDefaultNetworkCapabilities != null
+ && connectionIsWifi(mDefaultNetworkCapabilities);
if (isDefaultNetwork) {
// Wifi is connected and the default network.
networkCapabilities = mDefaultNetworkCapabilities;
@@ -352,6 +342,70 @@ public class WifiStatusTracker {
? null : AccessPoint.getSpeedLabel(mContext, scoredNetwork, rssi);
}
+ @Nullable
+ private WifiInfo getMainOrUnderlyingWifiInfo(NetworkCapabilities networkCapabilities) {
+ WifiInfo mainWifiInfo = getMainWifiInfo(networkCapabilities);
+ if (mainWifiInfo != null) {
+ return mainWifiInfo;
+ }
+
+ // Only CELLULAR networks may have underlying wifi information that's relevant to SysUI,
+ // so skip the underlying network check if it's not CELLULAR.
+ if (!networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
+ return mainWifiInfo;
+ }
+
+ List<Network> underlyingNetworks = networkCapabilities.getUnderlyingNetworks();
+ if (underlyingNetworks == null) {
+ return null;
+ }
+
+ // Some connections, like VPN connections, may have underlying networks that are
+ // eventually traced to a wifi or carrier merged connection. So, check those underlying
+ // networks for possible wifi information as well. See b/225902574.
+ for (Network underlyingNetwork : underlyingNetworks) {
+ NetworkCapabilities underlyingNetworkCapabilities =
+ mConnectivityManager.getNetworkCapabilities(underlyingNetwork);
+ WifiInfo underlyingWifiInfo = getMainWifiInfo(underlyingNetworkCapabilities);
+ if (underlyingWifiInfo != null) {
+ return underlyingWifiInfo;
+ }
+ }
+
+ return null;
+ }
+
+ @Nullable
+ private WifiInfo getMainWifiInfo(NetworkCapabilities networkCapabilities) {
+ boolean canHaveWifiInfo = networkCapabilities.hasTransport(TRANSPORT_WIFI)
+ || networkCapabilities.hasTransport(TRANSPORT_CELLULAR);
+ if (!canHaveWifiInfo) {
+ return null;
+ }
+
+ TransportInfo transportInfo = networkCapabilities.getTransportInfo();
+ if (transportInfo instanceof VcnTransportInfo) {
+ // This VcnTransportInfo logic is copied from
+ // [com.android.settingslib.Utils.tryGetWifiInfoForVcn]. It's copied instead of
+ // re-used because it makes the logic here clearer.
+ return ((VcnTransportInfo) transportInfo).getWifiInfo();
+ } else if (transportInfo instanceof WifiInfo) {
+ return (WifiInfo) transportInfo;
+ } else {
+ return null;
+ }
+ }
+
+ private boolean connectionIsWifi(NetworkCapabilities networkCapabilities) {
+ return connectionIsWifi(
+ networkCapabilities,
+ getMainOrUnderlyingWifiInfo(networkCapabilities));
+ }
+
+ private boolean connectionIsWifi(NetworkCapabilities networkCapabilities, WifiInfo wifiInfo) {
+ return wifiInfo != null || networkCapabilities.hasTransport(TRANSPORT_WIFI);
+ }
+
/** Refresh the status label on Locale changed. */
public void refreshLocale() {
updateStatusLabel();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiStatusTrackerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiStatusTrackerTest.java
index dc7e313dfcfa..6e975cf9d8f3 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiStatusTrackerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiStatusTrackerTest.java
@@ -40,6 +40,8 @@ import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
+import java.util.Arrays;
+
@RunWith(RobolectricTestRunner.class)
public class WifiStatusTrackerTest {
@Mock Context mContext;
@@ -48,13 +50,32 @@ public class WifiStatusTrackerTest {
@Mock ConnectivityManager mConnectivityManager;
@Mock Runnable mCallback;
+ private WifiStatusTracker mWifiStatusTracker;
+
private final ArgumentCaptor<ConnectivityManager.NetworkCallback>
mNetworkCallbackCaptor =
ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
+ private final ArgumentCaptor<ConnectivityManager.NetworkCallback>
+ mDefaultNetworkCallbackCaptor =
+ ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+
+ mWifiStatusTracker = new WifiStatusTracker(
+ mContext,
+ mWifiManager,
+ mNetworkScoreManager,
+ mConnectivityManager,
+ mCallback);
+ mWifiStatusTracker.setListening(true);
+
+ verify(mConnectivityManager)
+ .registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());
+ verify(mConnectivityManager)
+ .registerDefaultNetworkCallback(mDefaultNetworkCallbackCaptor.capture(), any());
}
/**
@@ -62,13 +83,6 @@ public class WifiStatusTrackerTest {
*/
@Test
public void testWifiInfoClearedOnPrimaryNetworkLost() {
- WifiStatusTracker wifiStatusTracker = new WifiStatusTracker(mContext, mWifiManager,
- mNetworkScoreManager, mConnectivityManager, mCallback);
- wifiStatusTracker.setListening(true);
-
- verify(mConnectivityManager)
- .registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());
-
// Trigger a validation callback for the primary Wifi network.
WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
when(primaryWifiInfo.makeCopy(anyLong())).thenReturn(primaryWifiInfo);
@@ -86,8 +100,8 @@ public class WifiStatusTrackerTest {
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
// Verify primary wifi info is the one being used.
- assertThat(wifiStatusTracker.connected).isTrue();
- assertThat(wifiStatusTracker.rssi).isEqualTo(primaryRssi);
+ assertThat(mWifiStatusTracker.connected).isTrue();
+ assertThat(mWifiStatusTracker.rssi).isEqualTo(primaryRssi);
// Trigger a validation callback for the non-primary Wifi network.
WifiInfo nonPrimaryWifiInfo = Mockito.mock(WifiInfo.class);
@@ -106,20 +120,189 @@ public class WifiStatusTrackerTest {
mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(nonPrimaryNetwork, nonPrimaryCap);
// Verify primary wifi info is still the one being used.
- assertThat(wifiStatusTracker.connected).isTrue();
- assertThat(wifiStatusTracker.rssi).isEqualTo(primaryRssi);
+ assertThat(mWifiStatusTracker.connected).isTrue();
+ assertThat(mWifiStatusTracker.rssi).isEqualTo(primaryRssi);
// Lose the non-primary network.
mNetworkCallbackCaptor.getValue().onLost(nonPrimaryNetwork);
// Verify primary wifi info is still the one being used.
- assertThat(wifiStatusTracker.connected).isTrue();
- assertThat(wifiStatusTracker.rssi).isEqualTo(primaryRssi);
+ assertThat(mWifiStatusTracker.connected).isTrue();
+ assertThat(mWifiStatusTracker.rssi).isEqualTo(primaryRssi);
// Lose the primary network.
mNetworkCallbackCaptor.getValue().onLost(primaryNetwork);
// Verify we aren't connected anymore.
- assertThat(wifiStatusTracker.connected).isFalse();
+ assertThat(mWifiStatusTracker.connected).isFalse();
+ }
+
+ @Test
+ public void isCarrierMerged_typicalWifi_false() {
+ WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
+ when(primaryWifiInfo.isPrimary()).thenReturn(true);
+
+ NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
+ when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)).thenReturn(true);
+ when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
+
+ assertThat(mWifiStatusTracker.isCarrierMerged).isFalse();
+ }
+
+ @Test
+ public void isCarrierMerged_typicalCellular_false() {
+ NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
+ when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
+
+ assertThat(mWifiStatusTracker.isCarrierMerged).isFalse();
+ }
+
+ @Test
+ public void isCarrierMerged_cellularCarrierMergedWifi_true() {
+ WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
+ when(primaryWifiInfo.isPrimary()).thenReturn(true);
+ when(primaryWifiInfo.isCarrierMerged()).thenReturn(true);
+
+ NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
+ when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
+ when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
+
+ assertThat(mWifiStatusTracker.isCarrierMerged).isTrue();
+ }
+
+ /** Test for b/225902574. */
+ @Test
+ public void isCarrierMerged_cellularWithUnderlyingCarrierMergedWifi_true() {
+ WifiInfo underlyingCarrierMergedInfo = Mockito.mock(WifiInfo.class);
+ when(underlyingCarrierMergedInfo.isPrimary()).thenReturn(true);
+ when(underlyingCarrierMergedInfo.isCarrierMerged()).thenReturn(true);
+
+ NetworkCapabilities underlyingNetworkCapabilities = Mockito.mock(NetworkCapabilities.class);
+ when(underlyingNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
+ .thenReturn(true);
+ when(underlyingNetworkCapabilities.getTransportInfo())
+ .thenReturn(underlyingCarrierMergedInfo);
+
+ Network underlyingNetwork = Mockito.mock(Network.class);
+ when(mConnectivityManager.getNetworkCapabilities(underlyingNetwork))
+ .thenReturn(underlyingNetworkCapabilities);
+
+ NetworkCapabilities mainCapabilities = Mockito.mock(NetworkCapabilities.class);
+ when(mainCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
+ .thenReturn(true);
+ when(mainCapabilities.getTransportInfo()).thenReturn(null);
+ when(mainCapabilities.getUnderlyingNetworks())
+ .thenReturn(Arrays.asList(underlyingNetwork));
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, mainCapabilities);
+
+ assertThat(mWifiStatusTracker.isCarrierMerged).isTrue();
+ }
+
+ @Test
+ public void isDefaultNetwork_typicalWifi_true() {
+ WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
+ when(primaryWifiInfo.isPrimary()).thenReturn(true);
+
+ NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
+ when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)).thenReturn(true);
+ when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
+
+ assertThat(mWifiStatusTracker.isDefaultNetwork).isTrue();
+ }
+
+ @Test
+ public void isDefaultNetwork_typicalCellular_false() {
+ NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
+ when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
+
+ assertThat(mWifiStatusTracker.isDefaultNetwork).isFalse();
+ }
+
+ @Test
+ public void isDefaultNetwork_cellularCarrierMergedWifi_true() {
+ WifiInfo primaryWifiInfo = Mockito.mock(WifiInfo.class);
+ when(primaryWifiInfo.isPrimary()).thenReturn(true);
+ when(primaryWifiInfo.isCarrierMerged()).thenReturn(true);
+
+ NetworkCapabilities primaryCap = Mockito.mock(NetworkCapabilities.class);
+ when(primaryCap.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).thenReturn(true);
+ when(primaryCap.getTransportInfo()).thenReturn(primaryWifiInfo);
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(primaryNetwork, primaryCap);
+
+ assertThat(mWifiStatusTracker.isDefaultNetwork).isTrue();
+ }
+
+ /** Test for b/225902574. */
+ @Test
+ public void isDefaultNetwork_cellularWithUnderlyingCarrierMergedWifi_true() {
+ WifiInfo underlyingCarrierMergedInfo = Mockito.mock(WifiInfo.class);
+ when(underlyingCarrierMergedInfo.isPrimary()).thenReturn(true);
+ when(underlyingCarrierMergedInfo.isCarrierMerged()).thenReturn(true);
+
+ NetworkCapabilities underlyingNetworkCapabilities = Mockito.mock(NetworkCapabilities.class);
+ when(underlyingNetworkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
+ .thenReturn(true);
+ when(underlyingNetworkCapabilities.getTransportInfo())
+ .thenReturn(underlyingCarrierMergedInfo);
+
+ Network underlyingNetwork = Mockito.mock(Network.class);
+ when(mConnectivityManager.getNetworkCapabilities(underlyingNetwork))
+ .thenReturn(underlyingNetworkCapabilities);
+
+ NetworkCapabilities mainCapabilities = Mockito.mock(NetworkCapabilities.class);
+ when(mainCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
+ .thenReturn(true);
+ when(mainCapabilities.getTransportInfo()).thenReturn(null);
+ when(mainCapabilities.getUnderlyingNetworks())
+ .thenReturn(Arrays.asList(underlyingNetwork));
+
+ Network primaryNetwork = Mockito.mock(Network.class);
+ int primaryNetworkId = 1;
+ when(primaryNetwork.getNetId()).thenReturn(primaryNetworkId);
+
+ mDefaultNetworkCallbackCaptor.getValue()
+ .onCapabilitiesChanged(primaryNetwork, mainCapabilities);
+
+ assertThat(mWifiStatusTracker.isDefaultNetwork).isTrue();
}
}
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index b95a149eb0cc..a5908a888449 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -252,9 +252,11 @@ filegroup {
// domain
"tests/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractorTest.kt",
"tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt",
+ "tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardLongPressInteractorTest.kt",
"tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractorTest.kt",
"tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt",
"tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt",
+ "tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerCallbackInteractorTest.kt",
"tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt",
// ui
"tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt",
@@ -263,6 +265,7 @@ filegroup {
"tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDreamingTransitionViewModelTest.kt",
"tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToOccludedTransitionViewModelTest.kt",
"tests/src/com/android/systemui/keyguard/ui/viewmodel/OccludedToLockscreenTransitionViewModelTest.kt",
+ "tests/src/com/android/systemui/keyguard/ui/viewmodel/PrimaryBouncerToGoneTransitionViewModelTest.kt",
// Keyguard helper
"tests/src/com/android/systemui/keyguard/data/quickaffordance/FakeKeyguardQuickAffordanceConfig.kt",
"tests/src/com/android/systemui/dump/LogBufferHelper.kt",
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 4652ef195a0c..32d6b70f7f47 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -966,22 +966,6 @@
android:permission="android.permission.BIND_JOB_SERVICE"/>
<!-- region Note Task -->
- <activity
- android:name=".notetask.shortcut.CreateNoteTaskShortcutActivity"
- android:enabled="false"
- android:exported="true"
- android:excludeFromRecents="true"
- android:resizeableActivity="false"
- android:theme="@android:style/Theme.NoDisplay"
- android:label="@string/note_task_button_label"
- android:icon="@drawable/ic_note_task_shortcut_widget">
-
- <intent-filter>
- <action android:name="android.intent.action.CREATE_SHORTCUT" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </activity>
-
<service android:name=".notetask.NoteTaskControllerUpdateService" />
<activity
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
index 296c2ae5cf99..94b37403b232 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt
@@ -436,8 +436,8 @@ class ActivityLaunchAnimator(
}
@BinderThread
- override fun onAnimationCancelled(isKeyguardOccluded: Boolean) {
- context.mainExecutor.execute { delegate.onAnimationCancelled(isKeyguardOccluded) }
+ override fun onAnimationCancelled() {
+ context.mainExecutor.execute { delegate.onAnimationCancelled() }
}
}
@@ -744,7 +744,7 @@ class ActivityLaunchAnimator(
}
@UiThread
- override fun onAnimationCancelled(isKeyguardOccluded: Boolean) {
+ override fun onAnimationCancelled() {
if (timedOut) {
return
}
@@ -754,7 +754,7 @@ class ActivityLaunchAnimator(
removeTimeout()
animation?.cancel()
- controller.onLaunchAnimationCancelled(newKeyguardOccludedState = isKeyguardOccluded)
+ controller.onLaunchAnimationCancelled()
}
private fun IRemoteAnimationFinishedCallback.invoke() {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationDelegate.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationDelegate.kt
index 337408bb9c5d..d465962d6edf 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationDelegate.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteAnimationDelegate.kt
@@ -26,5 +26,5 @@ interface RemoteAnimationDelegate<in T : IRemoteAnimationFinishedCallback> {
)
/** Called on the UI thread when a signal is received to cancel the animation. */
- @UiThread fun onAnimationCancelled(isKeyguardOccluded: Boolean)
+ @UiThread fun onAnimationCancelled()
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
index 9d1dd1b67801..3a19990f0627 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt
@@ -22,12 +22,11 @@ import android.annotation.IntRange
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
-import android.graphics.Rect
import android.text.Layout
import android.text.TextUtils
import android.text.format.DateFormat
import android.util.AttributeSet
-import android.util.MathUtils
+import android.util.MathUtils.constrainedMap
import android.widget.TextView
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.animation.GlyphCallback
@@ -40,8 +39,6 @@ import java.io.PrintWriter
import java.util.Calendar
import java.util.Locale
import java.util.TimeZone
-import kotlin.math.max
-import kotlin.math.min
/**
* Displays the time with the hour positioned above the minutes. (ie: 09 above 30 is 9:30)
@@ -478,122 +475,56 @@ class AnimatableClockView @JvmOverloads constructor(
pw.println(" time=$time")
}
- fun moveForSplitShade(fromRect: Rect, toRect: Rect, fraction: Float) {
- // Do we need to cancel an in-flight animation?
- // Need to also check against 0.0f here; we can sometimes get two calls with fraction == 0,
- // which trips up the check otherwise.
- if (lastSeenAnimationProgress != 1.0f &&
- lastSeenAnimationProgress != 0.0f &&
- fraction == 0.0f) {
- // New animation, but need to stop the old one. Figure out where each glyph currently
- // is in relation to the box position. After that, use the leading digit's current
- // position as the stop target.
- currentAnimationNeededStop = true
-
- // We assume that the current glyph offsets would be relative to the "from" position.
- val moveAmount = toRect.left - fromRect.left
-
- // Remap the current glyph offsets to be relative to the new "end" position, and figure
- // out the start/end positions for the stop animation.
- for (i in 0 until NUM_DIGITS) {
- glyphOffsets[i] = -moveAmount + glyphOffsets[i]
- animationCancelStartPosition[i] = glyphOffsets[i]
- }
+ private val moveToCenterDelays
+ get() = if (isLayoutRtl) MOVE_LEFT_DELAYS else MOVE_RIGHT_DELAYS
- // Use the leading digit's offset as the stop position.
- if (toRect.left > fromRect.left) {
- // It _was_ moving left
- animationCancelStopPosition = glyphOffsets[0]
- } else {
- // It was moving right
- animationCancelStopPosition = glyphOffsets[1]
- }
- }
-
- // Is there a cancellation in progress?
- if (currentAnimationNeededStop && fraction < ANIMATION_CANCELLATION_TIME) {
- val animationStopProgress = MathUtils.constrainedMap(
- 0.0f, 1.0f, 0.0f, ANIMATION_CANCELLATION_TIME, fraction
- )
+ private val moveToSideDelays
+ get() = if (isLayoutRtl) MOVE_RIGHT_DELAYS else MOVE_LEFT_DELAYS
- // One of the digits has already stopped.
- val animationStopStep = 1.0f / (NUM_DIGITS - 1)
-
- for (i in 0 until NUM_DIGITS) {
- val stopAmount = if (toRect.left > fromRect.left) {
- // It was moving left (before flipping)
- MOVE_LEFT_DELAYS[i] * animationStopStep
- } else {
- // It was moving right (before flipping)
- MOVE_RIGHT_DELAYS[i] * animationStopStep
- }
-
- // Leading digit stops immediately.
- if (stopAmount == 0.0f) {
- glyphOffsets[i] = animationCancelStopPosition
- } else {
- val actualStopAmount = MathUtils.constrainedMap(
- 0.0f, 1.0f, 0.0f, stopAmount, animationStopProgress
+ /**
+ * Offsets the glyphs of the clock for the step clock animation.
+ *
+ * The animation makes the glyphs of the clock move at different speeds, when the clock is
+ * moving horizontally.
+ *
+ * @param clockStartLeft the [getLeft] position of the clock, before it started moving.
+ * @param clockMoveDirection the direction in which it is moving. A positive number means right,
+ * and negative means left.
+ * @param moveFraction fraction of the clock movement. 0 means it is at the beginning, and 1
+ * means it finished moving.
+ */
+ fun offsetGlyphsForStepClockAnimation(
+ clockStartLeft: Int,
+ clockMoveDirection: Int,
+ moveFraction: Float
+ ) {
+ val isMovingToCenter = if (isLayoutRtl) clockMoveDirection < 0 else clockMoveDirection > 0
+ val currentMoveAmount = left - clockStartLeft
+ val digitOffsetDirection = if (isLayoutRtl) -1 else 1
+ for (i in 0 until NUM_DIGITS) {
+ // The delay for the digit, in terms of fraction (i.e. the digit should not move
+ // during 0.0 - 0.1).
+ val digitInitialDelay =
+ if (isMovingToCenter) {
+ moveToCenterDelays[i] * MOVE_DIGIT_STEP
+ } else {
+ moveToSideDelays[i] * MOVE_DIGIT_STEP
+ }
+ val digitFraction =
+ MOVE_INTERPOLATOR.getInterpolation(
+ constrainedMap(
+ 0.0f,
+ 1.0f,
+ digitInitialDelay,
+ digitInitialDelay + AVAILABLE_ANIMATION_TIME,
+ moveFraction
+ )
)
- val easedProgress = MOVE_INTERPOLATOR.getInterpolation(actualStopAmount)
- val glyphMoveAmount =
- animationCancelStopPosition - animationCancelStartPosition[i]
- glyphOffsets[i] =
- animationCancelStartPosition[i] + glyphMoveAmount * easedProgress
- }
- }
- } else {
- // Normal part of the animation.
- // Do we need to remap the animation progress to take account of the cancellation?
- val actualFraction = if (currentAnimationNeededStop) {
- MathUtils.constrainedMap(
- 0.0f, 1.0f, ANIMATION_CANCELLATION_TIME, 1.0f, fraction
- )
- } else {
- fraction
- }
-
- val digitFractions = (0 until NUM_DIGITS).map {
- // The delay for each digit, in terms of fraction (i.e. the digit should not move
- // during 0.0 - 0.1).
- val initialDelay = if (toRect.left > fromRect.left) {
- MOVE_RIGHT_DELAYS[it] * MOVE_DIGIT_STEP
- } else {
- MOVE_LEFT_DELAYS[it] * MOVE_DIGIT_STEP
- }
-
- val f = MathUtils.constrainedMap(
- 0.0f, 1.0f,
- initialDelay, initialDelay + AVAILABLE_ANIMATION_TIME,
- actualFraction
- )
- MOVE_INTERPOLATOR.getInterpolation(max(min(f, 1.0f), 0.0f))
- }
-
- // Was there an animation halt?
- val moveAmount = if (currentAnimationNeededStop) {
- // Only need to animate over the remaining space if the animation was aborted.
- -animationCancelStopPosition
- } else {
- toRect.left.toFloat() - fromRect.left.toFloat()
- }
-
- for (i in 0 until NUM_DIGITS) {
- glyphOffsets[i] = -moveAmount + (moveAmount * digitFractions[i])
- }
+ val moveAmountForDigit = currentMoveAmount * digitFraction
+ val moveAmountDeltaForDigit = moveAmountForDigit - currentMoveAmount
+ glyphOffsets[i] = digitOffsetDirection * moveAmountDeltaForDigit
}
-
invalidate()
-
- if (fraction == 1.0f) {
- // Reset
- currentAnimationNeededStop = false
- }
-
- lastSeenAnimationProgress = fraction
-
- // Ensure that the actual clock container is always in the "end" position.
- this.setLeftTopRightBottom(toRect.left, toRect.top, toRect.right, toRect.bottom)
}
// DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often.
@@ -647,9 +578,6 @@ class AnimatableClockView @JvmOverloads constructor(
private const val NUM_DIGITS = 4
private const val DIGITS_PER_LINE = 2
- // How much of "fraction" to spend on canceling the animation, if needed
- private const val ANIMATION_CANCELLATION_TIME = 0f
-
// Delays. Each digit's animation should have a slight delay, so we get a nice
// "stepping" effect. When moving right, the second digit of the hour should move first.
// When moving left, the first digit of the hour should move first. The lists encode
@@ -668,6 +596,6 @@ class AnimatableClockView @JvmOverloads constructor(
// Total available transition time for each digit, taking into account the step. If step is
// 0.1, then digit 0 would animate over 0.0 - 0.7, making availableTime 0.7.
- private val AVAILABLE_ANIMATION_TIME = 1.0f - MOVE_DIGIT_STEP * (NUM_DIGITS - 1)
+ private const val AVAILABLE_ANIMATION_TIME = 1.0f - MOVE_DIGIT_STEP * (NUM_DIGITS - 1)
}
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
index f57432c073c1..b0c02407873c 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt
@@ -151,6 +151,7 @@ open class ClockRegistry(
{ str1 = id },
{ "Clock Id conflict on load: $str1 is double registered" }
)
+ manager.unloadPlugin()
continue
}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
index 3fda83d7b6f4..2cc36008e4f8 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt
@@ -189,8 +189,9 @@ class DefaultClockController(
view.setLayoutParams(lp)
}
- fun moveForSplitShade(fromRect: Rect, toRect: Rect, fraction: Float) {
- view.moveForSplitShade(fromRect, toRect, fraction)
+ /** See documentation at [AnimatableClockView.offsetGlyphsForStepClockAnimation]. */
+ fun offsetGlyphsForStepClockAnimation(fromLeft: Int, direction: Int, fraction: Float) {
+ view.offsetGlyphsForStepClockAnimation(fromLeft, direction, fraction)
}
}
@@ -277,8 +278,8 @@ class DefaultClockController(
dozeFraction: Float,
foldFraction: Float,
) : DefaultClockAnimations(view, dozeFraction, foldFraction) {
- override fun onPositionUpdated(fromRect: Rect, toRect: Rect, fraction: Float) {
- largeClock.moveForSplitShade(fromRect, toRect, fraction)
+ override fun onPositionUpdated(fromLeft: Int, direction: Int, fraction: Float) {
+ largeClock.offsetGlyphsForStepClockAnimation(fromLeft, direction, fraction)
}
}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
index 8ef2d8033000..ca3e710a4acb 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -141,8 +141,16 @@ interface ClockAnimations {
/** Runs the battery animation (if any). */
fun charge() {}
- /** Move the clock, for example, if the notification tray appears in split-shade mode. */
- fun onPositionUpdated(fromRect: Rect, toRect: Rect, fraction: Float) {}
+ /**
+ * Runs when the clock's position changed during the move animation.
+ *
+ * @param fromLeft the [View.getLeft] position of the clock, before it started moving.
+ * @param direction the direction in which it is moving. A positive number means right, and
+ * negative means left.
+ * @param fraction fraction of the clock movement. 0 means it is at the beginning, and 1 means
+ * it finished moving.
+ */
+ fun onPositionUpdated(fromLeft: Int, direction: Int, fraction: Float) {}
/**
* Runs when swiping clock picker, swipingFraction: 1.0 -> clock is scaled up in the preview,
diff --git a/packages/SystemUI/res/layout/screen_record_dialog.xml b/packages/SystemUI/res/layout/screen_record_dialog.xml
index ab38dd2aebba..ae052502a110 100644
--- a/packages/SystemUI/res/layout/screen_record_dialog.xml
+++ b/packages/SystemUI/res/layout/screen_record_dialog.xml
@@ -49,13 +49,13 @@
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:fontFamily="@*android:string/config_headlineFontFamily"
- android:text="@string/screenrecord_start_label"
+ android:text="@string/screenrecord_permission_dialog_title"
android:layout_marginTop="22dp"
android:layout_marginBottom="15dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/screenrecord_description"
+ android:text="@string/screenrecord_permission_dialog_warning_entire_screen"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:textColorSecondary"
android:gravity="center"
@@ -168,7 +168,7 @@
android:layout_height="wrap_content"
android:layout_weight="0"
android:layout_gravity="end"
- android:text="@string/screenrecord_start"
+ android:text="@string/screenrecord_continue"
style="@style/Widget.Dialog.Button" />
</LinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/screen_share_dialog.xml b/packages/SystemUI/res/layout/screen_share_dialog.xml
index bd719894e25f..7dbe0598f3c8 100644
--- a/packages/SystemUI/res/layout/screen_share_dialog.xml
+++ b/packages/SystemUI/res/layout/screen_share_dialog.xml
@@ -63,7 +63,7 @@
android:id="@+id/text_warning"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/screenrecord_description"
+ android:text="@string/screenrecord_permission_dialog_warning_entire_screen"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:textColorSecondary"
android:gravity="start"
@@ -91,7 +91,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0"
- android:text="@string/screenrecord_start"
+ android:text="@string/screenrecord_continue"
style="@style/Widget.Dialog.Button" />
</LinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 4e68efeea870..853930e174a7 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -251,25 +251,22 @@
<string name="app_clips_save_add_to_note">Add to note</string>
<!-- Notification title displayed for screen recording [CHAR LIMIT=50]-->
- <string name="screenrecord_name">Screen Recorder</string>
+ <string name="screenrecord_title">Screen Recorder</string>
<!-- Processing screen recoding video in the background [CHAR LIMIT=30]-->
<string name="screenrecord_background_processing_label">Processing screen recording</string>
<!-- Description of the screen recording notification channel [CHAR LIMIT=NONE]-->
<string name="screenrecord_channel_description">Ongoing notification for a screen record session</string>
+
+ <!-- For updated Screen Recording permission dialog (i.e. with PSS)-->
<!-- Title for the screen prompting the user to begin recording their screen [CHAR LIMIT=NONE]-->
- <string name="screenrecord_start_label">Start Recording?</string>
- <!-- Message reminding the user that sensitive information may be captured during a screen recording [CHAR_LIMIT=NONE]-->
- <string name="screenrecord_description">While recording, Android System can capture any sensitive information that\u2019s visible on your screen or played on your device. This includes passwords, payment info, photos, messages, and audio.</string>
- <!-- Dropdown option to record the entire screen [CHAR_LIMIT=30]-->
- <string name="screenrecord_option_entire_screen">Record entire screen</string>
- <!-- Dropdown option to record a single app [CHAR_LIMIT=30]-->
- <string name="screenrecord_option_single_app">Record a single app</string>
+ <string name="screenrecord_permission_dialog_title">Start Recording?</string>
<!-- Message reminding the user that sensitive information may be captured during a full screen recording for the updated dialog that includes partial screen sharing option [CHAR_LIMIT=350]-->
- <string name="screenrecord_warning_entire_screen">While you\'re recording, Android has access to anything visible on your screen or played on your device. So be careful with passwords, payment details, messages, or other sensitive information.</string>
+ <string name="screenrecord_permission_dialog_warning_entire_screen">While you’re recording, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
<!-- Message reminding the user that sensitive information may be captured during a single app screen recording for the updated dialog that includes partial screen sharing option [CHAR_LIMIT=350]-->
- <string name="screenrecord_warning_single_app">While you\'re recording an app, Android has access to anything shown or played on that app. So be careful with passwords, payment details, messages, or other sensitive information.</string>
+ <string name="screenrecord_permission_dialog_warning_single_app">While you’re recording an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
<!-- Button to start a screen recording in the updated screen record dialog that allows to select an app to record [CHAR LIMIT=50]-->
- <string name="screenrecord_start_recording">Start recording</string>
+ <string name="screenrecord_permission_dialog_continue">Start recording</string>
+
<!-- Label for a switch to enable recording audio [CHAR LIMIT=NONE]-->
<string name="screenrecord_audio_label">Record audio</string>
<!-- Label for the option to record audio from the device [CHAR LIMIT=NONE]-->
@@ -281,7 +278,7 @@
<!-- Label for an option to record audio from both device and microphone [CHAR LIMIT=NONE]-->
<string name="screenrecord_device_audio_and_mic_label">Device audio and microphone</string>
<!-- Button to start a screen recording [CHAR LIMIT=50]-->
- <string name="screenrecord_start">Start</string>
+ <string name="screenrecord_continue">Start</string>
<!-- Notification text displayed when we are recording the screen [CHAR LIMIT=100]-->
<string name="screenrecord_ongoing_screen_only">Recording screen</string>
<!-- Notification text displayed when we are recording both the screen and audio [CHAR LIMIT=100]-->
@@ -1064,47 +1061,52 @@
<!-- Label for button in confirmation dialog when exiting guest session [CHAR LIMIT=35] -->
<string name="user_remove_user_remove">Remove</string>
- <!-- Media projection permission dialog warning text. [CHAR LIMIT=NONE] -->
- <string name="media_projection_dialog_text"><xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play.</string>
-
- <!-- Media projection permission dialog warning text for system services. [CHAR LIMIT=NONE] -->
- <string name="media_projection_dialog_service_text">The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play.</string>
-
- <!-- Media projection permission dialog warning title for system services. [CHAR LIMIT=NONE] -->
- <string name="media_projection_dialog_service_title">Start recording or casting?</string>
-
+ <!-- Media projection without Partial Screenshare -->
<!-- Media projection permission dialog warning title. [CHAR LIMIT=NONE] -->
<string name="media_projection_dialog_title">Start recording or casting with <xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g>?</string>
+ <!-- Media projection permission dialog warning text. [CHAR LIMIT=NONE] -->
+ <string name="media_projection_dialog_warning"><xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g> will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play.</string>
+ <!-- Media projection permission dialog warning title for system services. [CHAR LIMIT=NONE] -->
+ <string name="media_projection_sys_service_dialog_title">Start recording or casting?</string>
+ <!-- Media projection permission dialog warning text for system services. [CHAR LIMIT=NONE] -->
+ <string name="media_projection_sys_service_dialog_warning">The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play.</string>
- <!-- Media projection permission dialog title. [CHAR LIMIT=NONE] -->
- <string name="media_projection_permission_dialog_title">Allow <xliff:g id="app_seeking_permission" example="Meet">%s</xliff:g> to share or record?</string>
-
- <!-- Media projection permission dropdown option for capturing the whole screen. [CHAR LIMIT=30] -->
- <string name="media_projection_permission_dialog_option_entire_screen">Entire screen</string>
-
- <!-- Media projection permission dropdown option for capturing single app. [CHAR LIMIT=30] -->
- <string name="media_projection_permission_dialog_option_single_app">A single app</string>
-
- <!-- Media projection permission warning for capturing the whole screen. [CHAR LIMIT=350] -->
- <string name="media_projection_permission_dialog_warning_entire_screen">When you\'re sharing, recording, or casting, <xliff:g id="app_seeking_permission" example="Meet">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with passwords, payment details, messages, or other sensitive information.</string>
-
- <!-- Media projection permission warning for capturing an app. [CHAR LIMIT=350] -->
- <string name="media_projection_permission_dialog_warning_single_app">When you\'re sharing, recording, or casting an app, <xliff:g id="app_seeking_permission" example="Meet">%s</xliff:g> has access to anything shown or played on that app. So be careful with passwords, payment details, messages, or other sensitive information.</string>
-
- <!-- Media projection permission button to continue with app selection or recording [CHAR LIMIT=60] -->
- <string name="media_projection_permission_dialog_continue">Continue</string>
-
+ <!-- Permission dropdown option for sharing or recording the whole screen. [CHAR LIMIT=30] -->
+ <string name="screen_share_permission_dialog_option_entire_screen">Entire screen</string>
+ <!-- Permission dropdown option for sharing or recording single app. [CHAR LIMIT=30] -->
+ <string name="screen_share_permission_dialog_option_single_app">A single app</string>
<!-- Title of the dialog that allows to select an app to share or record [CHAR LIMIT=NONE] -->
- <string name="media_projection_permission_app_selector_title">Share or record an app</string>
-
- <!-- Media projection permission dialog title when there is no app name (e.g. it could be a system service when casting). [CHAR LIMIT=100] -->
- <string name="media_projection_permission_dialog_system_service_title">Allow this app to share or record?</string>
-
- <!-- Media projection permission warning for capturing the whole screen when a system service requests it (e.g. when casting). [CHAR LIMIT=350] -->
- <string name="media_projection_permission_dialog_system_service_warning_entire_screen">When you\'re sharing, recording, or casting, this app has access to anything visible on your screen or played on your device. So be careful with passwords, payment details, messages, or other sensitive information.</string>
-
- <!-- Media projection permission warning for capturing a single app when a system service requests it (e.g. when casting). [CHAR LIMIT=350] -->
- <string name="media_projection_permission_dialog_system_service_warning_single_app">When you\'re sharing, recording, or casting an app, this app has access to anything shown or played on that app. So be careful with passwords, payment details, messages, or other sensitive information.</string>
+ <string name="screen_share_permission_app_selector_title">Share or record an app</string>
+
+ <!-- Media projection that launched from 1P/3P apps -->
+ <!-- 1P/3P app media projection permission dialog title. [CHAR LIMIT=NONE] -->
+ <string name="media_projection_entry_app_permission_dialog_title">Start recording or casting with <xliff:g id="app_seeking_permission" example="Meet">%s</xliff:g>?</string>
+ <!-- 1P/3P app media projection permission warning for capturing the whole screen. [CHAR LIMIT=350] -->
+ <string name="media_projection_entry_app_permission_dialog_warning_entire_screen">When you’re sharing, recording, or casting, <xliff:g id="app_seeking_permission" example="Meet">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
+ <!-- 1P/3P app media projection permission warning for capturing an app. [CHAR LIMIT=350] -->
+ <string name="media_projection_entry_app_permission_dialog_warning_single_app">When you’re sharing, recording, or casting an app, <xliff:g id="app_seeking_permission" example="Meet">%s</xliff:g> has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
+ <!-- 1P/3P apps media projection permission button to continue with app selection or recording [CHAR LIMIT=60] -->
+ <string name="media_projection_entry_app_permission_dialog_continue">Start</string>
+
+ <!-- Casting that launched by SysUI (i.e. when there is no app name) -->
+ <!-- System casting media projection permission dialog title. [CHAR LIMIT=100] -->
+ <string name="media_projection_entry_cast_permission_dialog_title">Start casting?</string>
+ <!-- System casting media projection permission warning for capturing the whole screen when SysUI casting requests it. [CHAR LIMIT=350] -->
+ <string name="media_projection_entry_cast_permission_dialog_warning_entire_screen">When you’re casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
+ <!-- System casting media projection permission warning for capturing a single app when SysUI casting requests it. [CHAR LIMIT=350] -->
+ <string name="media_projection_entry_cast_permission_dialog_warning_single_app">When you’re casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
+ <!-- System casting media projection permission button to continue for SysUI casting. [CHAR LIMIT=60] -->
+ <string name="media_projection_entry_cast_permission_dialog_continue">Start casting</string>
+
+ <!-- Other sharing (not recording nor casting) that launched by SysUI (currently not in use) -->
+ <!-- System sharing media projection permission dialog title. [CHAR LIMIT=100] -->
+ <string name="media_projection_entry_generic_permission_dialog_title">Start sharing?</string>
+ <!-- System sharing media projection permission warning for capturing the whole screen. [CHAR LIMIT=350] -->
+ <string name="media_projection_entry_generic_permission_dialog_warning_entire_screen">When you’re sharing, recording, or casting, Android has access to anything visible on your screen or played on your device. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
+ <!-- System sharing media projection permission warning for capturing a single app. [CHAR LIMIT=350] -->
+ <string name="media_projection_entry_generic_permission_dialog_warning_single_app">When you’re sharing, recording, or casting an app, Android has access to anything shown or played on that app. So be careful with things like passwords, payment details, messages, photos, and audio and video.</string>
+ <!-- System sharing media projection permission button to continue. [CHAR LIMIT=60] -->
+ <string name="media_projection_entry_generic_permission_dialog_continue">Start</string>
<!-- Title for the dialog that is shown when screen capturing is disabled by enterprise policy. [CHAR LIMIT=100] -->
<string name="screen_capturing_disabled_by_policy_dialog_title">Blocked by your IT admin</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java
index 3d05542116e0..4f73fc426c3b 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/plugins/PluginActionManager.java
@@ -109,7 +109,7 @@ public class PluginActionManager<T extends Plugin> {
/** Load all plugins matching this instance's action. */
public void loadAll() {
if (DEBUG) Log.d(TAG, "startListening");
- mBgExecutor.execute(this::queryAll);
+ mBgExecutor.execute(() -> queryAll());
}
/** Unload all plugins managed by this instance. */
@@ -255,17 +255,18 @@ public class PluginActionManager<T extends Plugin> {
intent.setPackage(pkgName);
}
List<ResolveInfo> result = mPm.queryIntentServices(intent, 0);
- if (DEBUG) Log.d(TAG, "Found " + result.size() + " plugins");
+ if (DEBUG) {
+ Log.d(TAG, "Found " + result.size() + " plugins");
+ for (ResolveInfo info : result) {
+ ComponentName name = new ComponentName(info.serviceInfo.packageName,
+ info.serviceInfo.name);
+ Log.d(TAG, " " + name);
+ }
+ }
+
if (result.size() > 1 && !mAllowMultiple) {
// TODO: Show warning.
Log.w(TAG, "Multiple plugins found for " + mAction);
- if (DEBUG) {
- for (ResolveInfo info : result) {
- ComponentName name = new ComponentName(info.serviceInfo.packageName,
- info.serviceInfo.name);
- Log.w(TAG, " " + name);
- }
- }
return;
}
for (ResolveInfo info : result) {
@@ -307,7 +308,7 @@ public class PluginActionManager<T extends Plugin> {
// TODO: Only create the plugin before version check if we need it for
// legacy version check.
if (DEBUG) {
- Log.d(TAG, "createPlugin");
+ Log.d(TAG, "createPlugin: " + component);
}
try {
return mPluginInstanceFactory.create(
@@ -317,7 +318,7 @@ public class PluginActionManager<T extends Plugin> {
reportInvalidVersion(component, component.getClassName(), e);
}
} catch (Throwable e) {
- Log.w(TAG, "Couldn't load plugin: " + packageName, e);
+ Log.w(TAG, "Couldn't load plugin: " + component, e);
return null;
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java
index 1b0dacc327c1..8dcd2aaac9ef 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationRunnerCompat.java
@@ -206,7 +206,7 @@ public abstract class RemoteAnimationRunnerCompat extends IRemoteAnimationRunner
t.close();
info.releaseAllSurfaces();
if (finishRunnable == null) return;
- onAnimationCancelled(false /* isKeyguardOccluded */);
+ onAnimationCancelled();
finishRunnable.run();
}
};
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index edfcb8d0d1a6..0826f8a8b985 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -363,8 +363,6 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
} else {
View clockView = clockContainerView.getChildAt(0);
- transition.excludeTarget(clockView, /* exclude= */ true);
-
TransitionSet set = new TransitionSet();
set.addTransition(transition);
@@ -389,8 +387,9 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
@VisibleForTesting
static class SplitShadeTransitionAdapter extends Transition {
- private static final String PROP_BOUNDS = "splitShadeTransitionAdapter:bounds";
- private static final String[] TRANSITION_PROPERTIES = { PROP_BOUNDS };
+ private static final String PROP_BOUNDS_LEFT = "splitShadeTransitionAdapter:boundsLeft";
+ private static final String PROP_X_IN_WINDOW = "splitShadeTransitionAdapter:xInWindow";
+ private static final String[] TRANSITION_PROPERTIES = { PROP_BOUNDS_LEFT, PROP_X_IN_WINDOW};
private final KeyguardClockSwitchController mController;
@@ -400,12 +399,10 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
}
private void captureValues(TransitionValues transitionValues) {
- Rect boundsRect = new Rect();
- boundsRect.left = transitionValues.view.getLeft();
- boundsRect.top = transitionValues.view.getTop();
- boundsRect.right = transitionValues.view.getRight();
- boundsRect.bottom = transitionValues.view.getBottom();
- transitionValues.values.put(PROP_BOUNDS, boundsRect);
+ transitionValues.values.put(PROP_BOUNDS_LEFT, transitionValues.view.getLeft());
+ int[] locationInWindowTmp = new int[2];
+ transitionValues.view.getLocationInWindow(locationInWindowTmp);
+ transitionValues.values.put(PROP_X_IN_WINDOW, locationInWindowTmp[0]);
}
@Override
@@ -427,8 +424,12 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
}
ValueAnimator anim = ValueAnimator.ofFloat(0, 1);
- Rect from = (Rect) startValues.values.get(PROP_BOUNDS);
- Rect to = (Rect) endValues.values.get(PROP_BOUNDS);
+ int fromLeft = (int) startValues.values.get(PROP_BOUNDS_LEFT);
+ int fromWindowX = (int) startValues.values.get(PROP_X_IN_WINDOW);
+ int toWindowX = (int) endValues.values.get(PROP_X_IN_WINDOW);
+ // Using windowX, to determine direction, instead of left, as in RTL the difference of
+ // toLeft - fromLeft is always positive, even when moving left.
+ int direction = toWindowX - fromWindowX > 0 ? 1 : -1;
anim.addUpdateListener(animation -> {
ClockController clock = mController.getClock();
@@ -437,7 +438,7 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
}
clock.getLargeClock().getAnimations()
- .onPositionUpdated(from, to, animation.getAnimatedFraction());
+ .onPositionUpdated(fromLeft, direction, animation.getAnimatedFraction());
});
return anim;
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 2c669bbb8fed..9573913e5e2f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -396,6 +396,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private int mFaceRunningState = BIOMETRIC_STATE_STOPPED;
private boolean mIsDreaming;
private boolean mLogoutEnabled;
+ private boolean mIsFaceEnrolled;
private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private int mPostureState = DEVICE_POSTURE_UNKNOWN;
private FingerprintInteractiveToAuthProvider mFingerprintInteractiveToAuthProvider;
@@ -2572,6 +2573,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
}
+ private void updateFaceEnrolled(int userId) {
+ final Boolean isFaceEnrolled = isFaceSupported()
+ && mBiometricEnabledForUser.get(userId)
+ && mAuthController.isFaceAuthEnrolled(userId);
+ if (mIsFaceEnrolled != isFaceEnrolled) {
+ mLogger.logFaceEnrolledUpdated(mIsFaceEnrolled, isFaceEnrolled);
+ }
+ mIsFaceEnrolled = isFaceEnrolled;
+ }
+
private boolean isFaceSupported() {
return mFaceManager != null && !mFaceSensorProperties.isEmpty();
}
@@ -2611,17 +2622,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
/**
- * @return true if there's at least one face enrolled for the given user
- */
- private boolean isFaceEnrolled(int userId) {
- return mAuthController.isFaceAuthEnrolled(userId);
- }
-
- /**
- * @return true if there's at least one face enrolled for the current user
+ * @return true if there's at least one face enrolled
*/
public boolean isFaceEnrolled() {
- return isFaceEnrolled(getCurrentUser());
+ return mIsFaceEnrolled;
}
private final UserTracker.Callback mUserChangedCallback = new UserTracker.Callback() {
@@ -3280,13 +3284,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@SuppressLint("MissingPermission")
@VisibleForTesting
boolean isUnlockWithFingerprintPossible(int userId) {
- boolean newFpPossible = isFingerprintSupported()
- && !isFingerprintDisabled(userId) && mAuthController.isFingerprintEnrolled(userId);
- Boolean oldFpPossible = mIsUnlockWithFingerprintPossible.getOrDefault(userId, false);
- if (oldFpPossible != newFpPossible) {
- mLogger.logFpPossibleUpdated(userId, oldFpPossible, newFpPossible);
- }
- mIsUnlockWithFingerprintPossible.put(userId, newFpPossible);
+ // TODO (b/242022358), make this rely on onEnrollmentChanged event and update it only once.
+ boolean newFpEnrolled = isFingerprintSupported()
+ && !isFingerprintDisabled(userId) && mFpm.hasEnrolledTemplates(userId);
+ Boolean oldFpEnrolled = mIsUnlockWithFingerprintPossible.getOrDefault(userId, false);
+ if (oldFpEnrolled != newFpEnrolled) {
+ mLogger.logFpEnrolledUpdated(userId, oldFpEnrolled, newFpEnrolled);
+ }
+ mIsUnlockWithFingerprintPossible.put(userId, newFpEnrolled);
return mIsUnlockWithFingerprintPossible.get(userId);
}
@@ -3301,13 +3306,24 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
/**
* @deprecated This is being migrated to use modern architecture.
*/
- @VisibleForTesting
@Deprecated
- public boolean isUnlockWithFacePossible(int userId) {
+ private boolean isUnlockWithFacePossible(int userId) {
if (isFaceAuthInteractorEnabled()) {
return getFaceAuthInteractor().canFaceAuthRun();
}
- return isFaceSupported() && isFaceEnrolled(userId) && !isFaceDisabled(userId);
+ return isFaceAuthEnabledForUser(userId) && !isFaceDisabled(userId);
+ }
+
+ /**
+ * If face hardware is available, user has enrolled and enabled auth via setting.
+ *
+ * @deprecated This is being migrated to use modern architecture.
+ */
+ @Deprecated
+ public boolean isFaceAuthEnabledForUser(int userId) {
+ // TODO (b/242022358), make this rely on onEnrollmentChanged event and update it only once.
+ updateFaceEnrolled(userId);
+ return mIsFaceEnrolled;
}
private void stopListeningForFingerprint() {
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index fe4014575156..16618064f249 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -630,7 +630,7 @@ constructor(@KeyguardUpdateMonitorLog private val logBuffer: LogBuffer) {
)
}
- fun logFpPossibleUpdated(userId: Int, oldValue: Boolean, newValue: Boolean) {
+ fun logFpEnrolledUpdated(userId: Int, oldValue: Boolean, newValue: Boolean) {
logBuffer.log(
TAG,
DEBUG,
@@ -639,7 +639,7 @@ constructor(@KeyguardUpdateMonitorLog private val logBuffer: LogBuffer) {
bool1 = oldValue
bool2 = newValue
},
- { "Fp possible state changed for userId: $int1 old: $bool1, new: $bool2" }
+ { "Fp enrolled state changed for userId: $int1 old: $bool1, new: $bool2" }
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/OWNERS b/packages/SystemUI/src/com/android/systemui/accessibility/OWNERS
new file mode 100644
index 000000000000..1f66c91b3573
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 44215
+
+include /core/java/android/view/accessibility/OWNERS \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index f3c71da63594..4158390ec953 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -45,6 +45,8 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.R;
import com.android.internal.accessibility.dialog.AccessibilityButtonChooserActivity;
+import com.android.internal.accessibility.util.AccessibilityUtils;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ScreenshotHelper;
import com.android.systemui.CoreStartable;
import com.android.systemui.dagger.SysUISingleton;
@@ -520,8 +522,11 @@ public class SystemActions implements CoreStartable {
SCREENSHOT_ACCESSIBILITY_ACTIONS, new Handler(Looper.getMainLooper()), null);
}
- private void handleHeadsetHook() {
- sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HEADSETHOOK);
+ @VisibleForTesting
+ void handleHeadsetHook() {
+ if (!AccessibilityUtils.interceptHeadsetHookForActiveCall(mContext)) {
+ sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HEADSETHOOK);
+ }
}
private void handleAccessibilityButton() {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
index 7bfd84e4b647..155c26d9fe9d 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationSettings.java
@@ -463,13 +463,17 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
if ((configDiff & ActivityInfo.CONFIG_UI_MODE) != 0
|| (configDiff & ActivityInfo.CONFIG_ASSETS_PATHS) != 0
|| (configDiff & ActivityInfo.CONFIG_FONT_SCALE) != 0
+ || (configDiff & ActivityInfo.CONFIG_LOCALE) != 0
|| (configDiff & ActivityInfo.CONFIG_DENSITY) != 0) {
// We listen to following config changes to trigger layout inflation:
// CONFIG_UI_MODE: theme change
// CONFIG_ASSETS_PATHS: wallpaper change
// CONFIG_FONT_SCALE: font size change
+ // CONFIG_LOCALE: language change
// CONFIG_DENSITY: display size change
+ mParams.accessibilityTitle = getAccessibilityWindowTitle(mContext);
+
boolean showSettingPanelAfterThemeChange = mIsVisible;
hideSettingPanel(/* resetPosition= */ false);
inflateView();
@@ -490,11 +494,6 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
+ mDraggableWindowBounds.top;
return;
}
-
- if ((configDiff & ActivityInfo.CONFIG_LOCALE) != 0) {
- updateAccessibilityWindowTitle();
- return;
- }
}
private void onWindowInsetChanged() {
@@ -515,13 +514,6 @@ class WindowMagnificationSettings implements MagnificationGestureDetector.OnGest
}
}
- private void updateAccessibilityWindowTitle() {
- mParams.accessibilityTitle = getAccessibilityWindowTitle(mContext);
- if (mIsVisible) {
- mWindowManager.updateViewLayout(mSettingView, mParams);
- }
- }
-
public void editMagnifierSizeMode(boolean enable) {
setEditMagnifierSizeMode(enable);
updateSelectedButton(MagnificationSize.NONE);
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
index 3d6d3356fb55..18bd46756660 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
@@ -41,7 +41,8 @@ open class ControlsBindingControllerImpl @Inject constructor(
private val context: Context,
@Background private val backgroundExecutor: DelayableExecutor,
private val lazyController: Lazy<ControlsController>,
- userTracker: UserTracker
+ private val packageUpdateMonitorFactory: PackageUpdateMonitor.Factory,
+ userTracker: UserTracker,
) : ControlsBindingController {
companion object {
@@ -93,7 +94,8 @@ open class ControlsBindingControllerImpl @Inject constructor(
backgroundExecutor,
actionCallbackService,
currentUser,
- component
+ component,
+ packageUpdateMonitorFactory
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
index 217f4d89e24c..cb2476ce0ebf 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -16,6 +16,7 @@
package com.android.systemui.controls.controller
+import android.annotation.WorkerThread
import android.content.ComponentName
import android.content.Context
import android.content.Intent
@@ -23,7 +24,6 @@ import android.content.ServiceConnection
import android.os.Binder
import android.os.Bundle
import android.os.IBinder
-import android.os.RemoteException
import android.os.UserHandle
import android.service.controls.ControlsProviderService
import android.service.controls.ControlsProviderService.CALLBACK_BUNDLE
@@ -38,6 +38,7 @@ import android.util.Log
import com.android.internal.annotations.GuardedBy
import com.android.systemui.util.concurrency.DelayableExecutor
import java.util.concurrent.TimeUnit
+import java.util.concurrent.atomic.AtomicBoolean
/**
* Manager for the lifecycle of the connection to a given [ControlsProviderService].
@@ -45,6 +46,9 @@ import java.util.concurrent.TimeUnit
* This class handles binding and unbinding and requests to the service. The class will queue
* requests until the service is connected and dispatch them then.
*
+ * If the provider app is updated, and we are currently bound to it, it will try to rebind after
+ * update is completed.
+ *
* @property context A SystemUI context for binding to the services
* @property executor A delayable executor for posting timeouts
* @property actionCallbackService a callback interface to hand the remote service for sending
@@ -59,22 +63,22 @@ class ControlsProviderLifecycleManager(
private val executor: DelayableExecutor,
private val actionCallbackService: IControlsActionCallback.Stub,
val user: UserHandle,
- val componentName: ComponentName
-) : IBinder.DeathRecipient {
+ val componentName: ComponentName,
+ packageUpdateMonitorFactory: PackageUpdateMonitor.Factory,
+) {
val token: IBinder = Binder()
private var requiresBound = false
@GuardedBy("queuedServiceMethods")
private val queuedServiceMethods: MutableSet<ServiceMethod> = ArraySet()
private var wrapper: ServiceWrapper? = null
- private var bindTryCount = 0
private val TAG = javaClass.simpleName
private var onLoadCanceller: Runnable? = null
+ private var lastForPanel = false
+
companion object {
- private const val BIND_RETRY_DELAY = 1000L // ms
private const val LOAD_TIMEOUT_SECONDS = 20L // seconds
- private const val MAX_BIND_RETRIES = 5
private const val DEBUG = true
private val BIND_FLAGS = Context.BIND_AUTO_CREATE or Context.BIND_FOREGROUND_SERVICE or
Context.BIND_NOT_PERCEPTIBLE
@@ -91,60 +95,56 @@ class ControlsProviderLifecycleManager(
})
}
+ private val packageUpdateMonitor = packageUpdateMonitorFactory.create(
+ user,
+ componentName.packageName,
+ ) {
+ if (requiresBound) {
+ // Let's unbind just in case. onBindingDied should have been called and unbound before.
+ executor.execute {
+ unbindAndCleanup("package updated")
+ bindService(true, lastForPanel)
+ }
+ }
+ }
+
private fun bindService(bind: Boolean, forPanel: Boolean = false) {
executor.execute {
- requiresBound = bind
- if (bind) {
- if (bindTryCount != MAX_BIND_RETRIES && wrapper == null) {
- if (DEBUG) {
- Log.d(TAG, "Binding service $intent")
- }
- bindTryCount++
- try {
- val flags = if (forPanel) BIND_FLAGS_PANEL else BIND_FLAGS
- val bound = context
- .bindServiceAsUser(intent, serviceConnection, flags, user)
- if (!bound) {
- context.unbindService(serviceConnection)
- }
- } catch (e: SecurityException) {
- Log.e(TAG, "Failed to bind to service", e)
- }
- }
- } else {
- if (DEBUG) {
- Log.d(TAG, "Unbinding service $intent")
- }
- bindTryCount = 0
- wrapper?.run {
- context.unbindService(serviceConnection)
- }
- wrapper = null
- }
+ bindServiceBackground(bind, forPanel)
}
}
private val serviceConnection = object : ServiceConnection {
+
+ val connected = AtomicBoolean(false)
+
override fun onServiceConnected(name: ComponentName, service: IBinder) {
if (DEBUG) Log.d(TAG, "onServiceConnected $name")
- bindTryCount = 0
wrapper = ServiceWrapper(IControlsProvider.Stub.asInterface(service))
- try {
- service.linkToDeath(this@ControlsProviderLifecycleManager, 0)
- } catch (_: RemoteException) {}
+ packageUpdateMonitor.startMonitoring()
handlePendingServiceMethods()
}
override fun onServiceDisconnected(name: ComponentName?) {
if (DEBUG) Log.d(TAG, "onServiceDisconnected $name")
wrapper = null
- bindService(false)
+ // No need to call unbind. We may get a new `onServiceConnected`
}
override fun onNullBinding(name: ComponentName?) {
if (DEBUG) Log.d(TAG, "onNullBinding $name")
wrapper = null
- context.unbindService(this)
+ executor.execute {
+ unbindAndCleanup("null binding")
+ }
+ }
+
+ override fun onBindingDied(name: ComponentName?) {
+ super.onBindingDied(name)
+ if (DEBUG) Log.d(TAG, "onBindingDied $name")
+ executor.execute {
+ unbindAndCleanup("binder died")
+ }
}
}
@@ -159,14 +159,55 @@ class ControlsProviderLifecycleManager(
}
}
- override fun binderDied() {
- if (wrapper == null) return
- wrapper = null
- if (requiresBound) {
- if (DEBUG) {
- Log.d(TAG, "binderDied")
+ @WorkerThread
+ private fun bindServiceBackground(bind: Boolean, forPanel: Boolean = true) {
+ requiresBound = bind
+ if (bind) {
+ if (wrapper == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Binding service $intent")
+ }
+ try {
+ lastForPanel = forPanel
+ val flags = if (forPanel) BIND_FLAGS_PANEL else BIND_FLAGS
+ var bound = false
+ if (serviceConnection.connected.compareAndSet(false, true)) {
+ bound = context
+ .bindServiceAsUser(intent, serviceConnection, flags, user)
+ }
+ if (!bound) {
+ Log.d(TAG, "Couldn't bind to $intent")
+ doUnbind()
+ }
+ } catch (e: SecurityException) {
+ Log.e(TAG, "Failed to bind to service", e)
+ // Couldn't even bind. Let's reset the connected value
+ serviceConnection.connected.set(false)
+ }
}
- // Try rebinding some time later
+ } else {
+ unbindAndCleanup("unbind requested")
+ packageUpdateMonitor.stopMonitoring()
+ }
+ }
+
+ @WorkerThread
+ private fun unbindAndCleanup(reason: String) {
+ if (DEBUG) {
+ Log.d(TAG, "Unbinding service $intent. Reason: $reason")
+ }
+ wrapper = null
+ try {
+ doUnbind()
+ } catch (e: IllegalArgumentException) {
+ Log.e(TAG, "Failed to unbind service", e)
+ }
+ }
+
+ @WorkerThread
+ private fun doUnbind() {
+ if (serviceConnection.connected.compareAndSet(true, false)) {
+ context.unbindService(serviceConnection)
}
}
@@ -313,7 +354,7 @@ class ControlsProviderLifecycleManager(
fun run() {
if (!callWrapper()) {
queueServiceMethod(this)
- binderDied()
+ executor.execute { unbindAndCleanup("couldn't call through binder") }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/PackageUpdateMonitor.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/PackageUpdateMonitor.kt
new file mode 100644
index 000000000000..1973b620b34f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/PackageUpdateMonitor.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 The Android Open 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.controls.controller
+
+import android.content.Context
+import android.os.Handler
+import android.os.UserHandle
+import com.android.internal.content.PackageMonitor
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import java.util.concurrent.atomic.AtomicBoolean
+
+/** [PackageMonitor] that tracks when [packageName] has finished updating for user [user]. */
+class PackageUpdateMonitor
+@AssistedInject
+constructor(
+ @Assisted private val user: UserHandle,
+ @Assisted private val packageName: String,
+ @Assisted private val callback: Runnable,
+ @Background private val bgHandler: Handler,
+ @Application private val context: Context,
+) : PackageMonitor() {
+
+ private val monitoring = AtomicBoolean(false)
+
+ @AssistedFactory
+ fun interface Factory {
+ /**
+ * Create a [PackageUpdateMonitor] for a given [user] and [packageName]. It will run
+ * [callback] every time the package finishes updating.
+ */
+ fun create(user: UserHandle, packageName: String, callback: Runnable): PackageUpdateMonitor
+ }
+
+ /** Start monitoring for package updates. No-op if already monitoring. */
+ fun startMonitoring() {
+ if (monitoring.compareAndSet(/* expected */ false, /* new */ true)) {
+ register(context, user, false, bgHandler)
+ }
+ }
+
+ /** Stop monitoring for package updates. No-op if not monitoring. */
+ fun stopMonitoring() {
+ if (monitoring.compareAndSet(/* expected */ true, /* new */ false)) {
+ unregister()
+ }
+ }
+
+ /**
+ * If the package and the user match the ones for this [PackageUpdateMonitor], it will run
+ * [callback].
+ */
+ override fun onPackageUpdateFinished(packageName: String?, uid: Int) {
+ super.onPackageUpdateFinished(packageName, uid)
+ if (packageName == this.packageName && UserHandle.getUserHandleForUid(uid) == user) {
+ callback.run()
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
index 2c717f5af8da..45cb13be361e 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
@@ -16,11 +16,11 @@
package com.android.systemui.controls.controller
-import android.service.controls.actions.ControlAction
import android.service.controls.IControlsActionCallback
import android.service.controls.IControlsProvider
import android.service.controls.IControlsSubscriber
import android.service.controls.IControlsSubscription
+import android.service.controls.actions.ControlAction
import android.service.controls.actions.ControlActionWrapper
import android.util.Log
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamLogger.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamLogger.kt
new file mode 100644
index 000000000000..eb7929095a4b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamLogger.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2023 The Android Open 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
+
+import com.android.systemui.log.dagger.DreamLog
+import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.plugins.log.LogLevel
+import javax.inject.Inject
+
+/** Logs dream-related stuff to a {@link LogBuffer}. */
+class DreamLogger @Inject constructor(@DreamLog private val buffer: LogBuffer) {
+ /** Logs a debug message to the buffer. */
+ fun d(tag: String, message: String) {
+ buffer.log(tag, LogLevel.DEBUG, { str1 = message }, { message })
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
index 5b56c04ae8aa..df46e07e0911 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayAnimationsController.kt
@@ -21,6 +21,7 @@ import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.view.View
import android.view.animation.Interpolator
+import androidx.core.animation.doOnCancel
import androidx.core.animation.doOnEnd
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
@@ -65,7 +66,11 @@ constructor(
private val mDreamInTranslationYDistance: Int,
@Named(DreamOverlayModule.DREAM_IN_TRANSLATION_Y_DURATION)
private val mDreamInTranslationYDurationMs: Long,
+ private val mLogger: DreamLogger,
) {
+ companion object {
+ private const val TAG = "DreamOverlayAnimationsController"
+ }
private var mAnimator: Animator? = null
private lateinit var view: View
@@ -169,8 +174,11 @@ constructor(
doOnEnd {
mAnimator = null
mOverlayStateController.setEntryAnimationsFinished(true)
+ mLogger.d(TAG, "Dream overlay entry animations finished.")
}
+ doOnCancel { mLogger.d(TAG, "Dream overlay entry animations canceled.") }
start()
+ mLogger.d(TAG, "Dream overlay entry animations started.")
}
}
@@ -232,8 +240,11 @@ constructor(
doOnEnd {
mAnimator = null
mOverlayStateController.setExitAnimationsRunning(false)
+ mLogger.d(TAG, "Dream overlay exit animations finished.")
}
+ doOnCancel { mLogger.d(TAG, "Dream overlay exit animations canceled.") }
start()
+ mLogger.d(TAG, "Dream overlay exit animations started.")
}
mOverlayStateController.setExitAnimationsRunning(true)
return mAnimator as AnimatorSet
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 942730344f20..e31834cef5b4 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -68,8 +68,6 @@ object Flags {
val NOTIFICATION_MEMORY_LOGGING_ENABLED =
unreleasedFlag(119, "notification_memory_logging_enabled")
- @JvmField val USE_ROUNDNESS_SOURCETYPES = releasedFlag(116, "use_roundness_sourcetype")
-
@JvmField
val SIMPLIFIED_APPEAR_FRACTION =
releasedFlag(259395680, "simplified_appear_fraction")
@@ -81,7 +79,8 @@ object Flags {
// TODO(b/278873737): Tracking Bug
@JvmField
val LOAD_NOTIFICATIONS_BEFORE_THE_USER_SWITCH_IS_COMPLETE =
- unreleasedFlag(278873737, "load_notifications_before_the_user_switch_is_complete")
+ unreleasedFlag(278873737, "load_notifications_before_the_user_switch_is_complete",
+ teamfood = true)
// TODO(b/277338665): Tracking Bug
@JvmField
@@ -116,7 +115,7 @@ object Flags {
// TODO(b/275694445): Tracking Bug
@JvmField
- val LOCKSCREEN_WITHOUT_SECURE_LOCK_WHEN_DREAMING = releasedFlag(208,
+ val LOCKSCREEN_WITHOUT_SECURE_LOCK_WHEN_DREAMING = unreleasedFlag(208,
"lockscreen_without_secure_lock_when_dreaming")
/**
@@ -679,8 +678,8 @@ object Flags {
// TODO(b/272805037): Tracking Bug
@JvmField
- val ADVANCED_VPN_ENABLED = unreleasedFlag(2800, name = "AdvancedVpn__enable_feature",
- namespace = "vpn", teamfood = true)
+ val ADVANCED_VPN_ENABLED = releasedFlag(2800, name = "AdvancedVpn__enable_feature",
+ namespace = "vpn")
// TODO(b/278761837): Tracking Bug
@JvmField
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 107e685c4482..8b6bd2486117 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -243,7 +243,7 @@ public class KeyguardService extends Service {
Slog.e(TAG, "Called mergeAnimation, but finish callback is missing");
return;
}
- runner.onAnimationCancelled(false /* isKeyguardOccluded */);
+ runner.onAnimationCancelled();
currentFinishCB.onTransitionFinished(null /* wct */, null /* t */);
} catch (RemoteException e) {
// nothing, we'll just let it finish on its own I guess.
@@ -418,7 +418,7 @@ public class KeyguardService extends Service {
}
@Override // Binder interface
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
mKeyguardViewMediator.cancelKeyguardExitAnimation();
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 93ddfba5b6fc..1a126d72f9e9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -959,20 +959,15 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
@Nullable private ValueAnimator mOccludeByDreamAnimator;
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
mContext.getMainExecutor().execute(() -> {
if (mOccludeByDreamAnimator != null) {
mOccludeByDreamAnimator.cancel();
}
});
- // The value of isKeyguardOccluded here may come from mergeAnimation, which
- // isn't reliable. In all cases, after running or cancelling this animation,
- // keyguard should be occluded.
+
+ Log.d(TAG, "OccludeByDreamAnimator#onAnimationCancelled. Set occluded = true");
setOccluded(true /* isOccluded */, false /* animate */);
- if (DEBUG) {
- Log.d(TAG, "Occlude by Dream animation cancelled. Occluded state is now: "
- + mOccluded);
- }
}
@Override
@@ -984,6 +979,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
// Usually we rely on animation completion to synchronize occluded status,
// but there was no animation to play, so just update it now.
setOccluded(true /* isOccluded */, false /* animate */);
+ finishedCallback.onAnimationFinished();
}
}
@@ -991,11 +987,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
if (apps == null || apps.length == 0 || apps[0] == null) {
- if (DEBUG) {
- Log.d(TAG, "No apps provided to the OccludeByDream runner; "
- + "skipping occluding animation.");
- }
- finishedCallback.onAnimationFinished();
+ Log.d(TAG, "No apps provided to the OccludeByDream runner; "
+ + "skipping occluding animation.");
return false;
}
@@ -1005,7 +998,6 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
if (!isDream) {
Log.w(TAG, "The occluding app isn't Dream; "
+ "finishing up. Please check that the config is correct.");
- finishedCallback.onAnimationFinished();
return false;
}
@@ -1071,17 +1063,14 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
private final Matrix mUnoccludeMatrix = new Matrix();
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
mContext.getMainExecutor().execute(() -> {
if (mUnoccludeAnimator != null) {
mUnoccludeAnimator.cancel();
}
});
- setOccluded(isKeyguardOccluded /* isOccluded */, false /* animate */);
- Log.d(TAG, "Unocclude animation cancelled. Occluded state is now: "
- + mOccluded);
-
+ Log.d(TAG, "Unocclude animation cancelled.");
mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_OCCLUSION);
}
@@ -3404,9 +3393,9 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) throws RemoteException {
+ public void onAnimationCancelled() throws RemoteException {
if (mRunner != null) {
- mRunner.onAnimationCancelled(isKeyguardOccluded);
+ mRunner.onAnimationCancelled();
}
}
@@ -3452,13 +3441,9 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) throws RemoteException {
- super.onAnimationCancelled(isKeyguardOccluded);
-
- Log.d(TAG, "Occlude animation cancelled by WM. "
- + "Setting occluded state to: " + isKeyguardOccluded);
- setOccluded(isKeyguardOccluded /* occluded */, false /* animate */);
-
+ public void onAnimationCancelled() throws RemoteException {
+ super.onAnimationCancelled();
+ Log.d(TAG, "Occlude animation cancelled by WM.");
mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_OCCLUSION);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
index 9b94cdbfe8dc..148d4255636c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AlternateBouncerInteractor.kt
@@ -41,17 +41,6 @@ constructor(
var receivedDownTouch = false
val isVisible: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
- private val keyguardStateControllerCallback: KeyguardStateController.Callback =
- object : KeyguardStateController.Callback {
- override fun onUnlockedChanged() {
- maybeHide()
- }
- }
-
- init {
- keyguardStateController.addCallback(keyguardStateControllerCallback)
- }
-
/**
* Sets the correct bouncer states to show the alternate bouncer if it can show.
*
@@ -102,11 +91,18 @@ constructor(
return (systemClock.uptimeMillis() - bouncerRepository.lastAlternateBouncerVisibleTime) >
MIN_VISIBILITY_DURATION_UNTIL_TOUCHES_DISMISS_ALTERNATE_BOUNCER_MS
}
-
- private fun maybeHide() {
+ /**
+ * Should only be called through StatusBarKeyguardViewManager which propagates the source of
+ * truth to other concerned controllers. Will hide the alternate bouncer if it's no longer
+ * allowed to show.
+ *
+ * @return true if the alternate bouncer was newly hidden, else false.
+ */
+ fun maybeHide(): Boolean {
if (isVisibleState() && !canShowAlternateBouncerForFingerprint()) {
- hide()
+ return hide()
}
+ return false
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/DreamLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/DreamLog.kt
new file mode 100644
index 000000000000..cb9913abe99b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/DreamLog.kt
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2023 The Android Open 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.log.dagger
+
+import javax.inject.Qualifier
+
+/** A [com.android.systemui.log.LogBuffer] for dream-related logging. */
+@Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class DreamLog
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
index 077ee027d764..658f6a087854 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -440,4 +440,14 @@ public class LogModule {
public static LogBuffer provideKeyguardLogBuffer(LogBufferFactory factory) {
return factory.create("KeyguardLog", 250);
}
+
+ /**
+ * Provides a {@link LogBuffer} for dream-related logs.
+ */
+ @Provides
+ @SysUISingleton
+ @DreamLog
+ public static LogBuffer provideDreamLogBuffer(LogBufferFactory factory) {
+ return factory.create("DreamLog", 250);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/LogProxy.kt b/packages/SystemUI/src/com/android/systemui/log/table/LogProxy.kt
new file mode 100644
index 000000000000..53886aabfa72
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/log/table/LogProxy.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 The Android Open 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.log.table
+
+import android.util.Log
+import javax.inject.Inject
+
+/** Dagger-friendly interface so we can inject a fake [android.util.Log] in tests */
+interface LogProxy {
+ /** verbose log */
+ fun v(tag: String, message: String)
+
+ /** debug log */
+ fun d(tag: String, message: String)
+
+ /** info log */
+ fun i(tag: String, message: String)
+
+ /** warning log */
+ fun w(tag: String, message: String)
+
+ /** error log */
+ fun e(tag: String, message: String)
+
+ /** wtf log */
+ fun wtf(tag: String, message: String)
+}
+
+class LogProxyDefault @Inject constructor() : LogProxy {
+ override fun v(tag: String, message: String) {
+ Log.v(tag, message)
+ }
+
+ override fun d(tag: String, message: String) {
+ Log.d(tag, message)
+ }
+
+ override fun i(tag: String, message: String) {
+ Log.i(tag, message)
+ }
+
+ override fun w(tag: String, message: String) {
+ Log.w(tag, message)
+ }
+
+ override fun e(tag: String, message: String) {
+ Log.e(tag, message)
+ }
+
+ override fun wtf(tag: String, message: String) {
+ Log.wtf(tag, message)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
index faaa205b15c2..9d883cc10d6c 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
@@ -19,10 +19,17 @@ package com.android.systemui.log.table
import android.os.Trace
import com.android.systemui.Dumpable
import com.android.systemui.common.buffer.RingBuffer
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.plugins.log.LogcatEchoTracker
import com.android.systemui.util.time.SystemClock
import java.io.PrintWriter
import java.text.SimpleDateFormat
import java.util.Locale
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.launch
/**
* A logger that logs changes in table format.
@@ -73,12 +80,18 @@ class TableLogBuffer(
maxSize: Int,
private val name: String,
private val systemClock: SystemClock,
+ private val logcatEchoTracker: LogcatEchoTracker,
+ @Background private val bgDispatcher: CoroutineDispatcher,
+ private val coroutineScope: CoroutineScope,
+ private val localLogcat: LogProxy = LogProxyDefault(),
) : Dumpable {
init {
if (maxSize <= 0) {
throw IllegalArgumentException("maxSize must be > 0")
}
}
+ // For local logcat, send messages across this channel so the background job can process them
+ private val logMessageChannel = Channel<TableChange>(capacity = 10)
private val buffer = RingBuffer(maxSize) { TableChange() }
@@ -105,6 +118,16 @@ class TableLogBuffer(
tableLogBuffer = this,
)
+ /** Start this log buffer logging in the background */
+ internal fun init() {
+ coroutineScope.launch(bgDispatcher) {
+ while (!logMessageChannel.isClosedForReceive) {
+ val log = logMessageChannel.receive()
+ echoToDesiredEndpoints(log)
+ }
+ }
+ }
+
/**
* Log the differences between [prevVal] and [newVal].
*
@@ -189,6 +212,7 @@ class TableLogBuffer(
Trace.beginSection("TableLogBuffer#logChange(string)")
val change = obtain(timestamp, prefix, columnName, isInitial)
change.set(value)
+ tryAddMessage(change)
Trace.endSection()
}
@@ -202,6 +226,7 @@ class TableLogBuffer(
Trace.beginSection("TableLogBuffer#logChange(boolean)")
val change = obtain(timestamp, prefix, columnName, isInitial)
change.set(value)
+ tryAddMessage(change)
Trace.endSection()
}
@@ -215,9 +240,14 @@ class TableLogBuffer(
Trace.beginSection("TableLogBuffer#logChange(int)")
val change = obtain(timestamp, prefix, columnName, isInitial)
change.set(value)
+ tryAddMessage(change)
Trace.endSection()
}
+ private fun tryAddMessage(change: TableChange) {
+ logMessageChannel.trySend(change)
+ }
+
// TODO(b/259454430): Add additional change types here.
@Synchronized
@@ -258,6 +288,17 @@ class TableLogBuffer(
Trace.endSection()
}
+ private fun echoToDesiredEndpoints(change: TableChange) {
+ if (
+ logcatEchoTracker.isBufferLoggable(bufferName = name, LogLevel.DEBUG) ||
+ logcatEchoTracker.isTagLoggable(change.columnName, LogLevel.DEBUG)
+ ) {
+ if (change.hasData()) {
+ localLogcat.d(name, change.logcatRepresentation())
+ }
+ }
+ }
+
@Synchronized
override fun dump(pw: PrintWriter, args: Array<out String>) {
pw.println(HEADER_PREFIX + name)
@@ -284,6 +325,12 @@ class TableLogBuffer(
pw.println()
}
+ /** Transforms an individual [TableChange] into a String for logcat */
+ private fun TableChange.logcatRepresentation(): String {
+ val formattedTimestamp = TABLE_LOG_DATE_FORMAT.format(timestamp)
+ return "$formattedTimestamp$SEPARATOR${getName()}$SEPARATOR${getVal()}"
+ }
+
/**
* A private implementation of [TableRowLogger].
*
diff --git a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
index 06668d33408d..42e742db2842 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
@@ -17,10 +17,15 @@
package com.android.systemui.log.table
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dump.DumpManager
import com.android.systemui.log.LogBufferHelper.Companion.adjustMaxSize
+import com.android.systemui.plugins.log.LogcatEchoTracker
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
@SysUISingleton
class TableLogBufferFactory
@@ -28,6 +33,9 @@ class TableLogBufferFactory
constructor(
private val dumpManager: DumpManager,
private val systemClock: SystemClock,
+ private val logcatEchoTracker: LogcatEchoTracker,
+ @Background private val bgDispatcher: CoroutineDispatcher,
+ @Application private val coroutineScope: CoroutineScope,
) {
private val existingBuffers = mutableMapOf<String, TableLogBuffer>()
@@ -44,8 +52,17 @@ constructor(
name: String,
maxSize: Int,
): TableLogBuffer {
- val tableBuffer = TableLogBuffer(adjustMaxSize(maxSize), name, systemClock)
+ val tableBuffer =
+ TableLogBuffer(
+ adjustMaxSize(maxSize),
+ name,
+ systemClock,
+ logcatEchoTracker,
+ bgDispatcher,
+ coroutineScope,
+ )
dumpManager.registerNormalDumpable(name, tableBuffer)
+ tableBuffer.init()
return tableBuffer
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
index 0860c207ef20..aec7b5f7aa7a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionAppSelectorActivity.kt
@@ -259,7 +259,7 @@ class MediaProjectionAppSelectorActivity(
putExtra(Intent.EXTRA_INTENT, queryIntent)
// Update the title of the chooser
- val title = resources.getString(R.string.media_projection_permission_app_selector_title)
+ val title = resources.getString(R.string.screen_share_permission_app_selector_title)
putExtra(Intent.EXTRA_TITLE, title)
// Select host app's profile tab by default
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index e217e36d1051..28adfbba1103 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -157,8 +157,8 @@ public class MediaProjectionPermissionActivity extends Activity
CharSequence dialogTitle = null;
String appName = null;
if (Utils.isHeadlessRemoteDisplayProvider(packageManager, mPackageName)) {
- dialogText = getString(R.string.media_projection_dialog_service_text);
- dialogTitle = getString(R.string.media_projection_dialog_service_title);
+ dialogText = getString(R.string.media_projection_sys_service_dialog_warning);
+ dialogTitle = getString(R.string.media_projection_sys_service_dialog_title);
} else {
String label = aInfo.loadLabel(packageManager).toString();
@@ -188,7 +188,7 @@ public class MediaProjectionPermissionActivity extends Activity
paint, MAX_APP_NAME_SIZE_PX, TextUtils.TruncateAt.END).toString();
appName = BidiFormatter.getInstance().unicodeWrap(unsanitizedAppName);
- String actionText = getString(R.string.media_projection_dialog_text, appName);
+ String actionText = getString(R.string.media_projection_dialog_warning, appName);
SpannableString message = new SpannableString(actionText);
int appNameIndex = actionText.indexOf(appName);
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index 2a8168b0cb36..05e04a11d7ba 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -88,18 +88,9 @@ public class RingtonePlayer implements CoreStartable {
private final IBinder mToken;
private final Ringtone mRingtone;
- public Client(IBinder token, Uri uri, UserHandle user, AudioAttributes aa) {
- this(token, uri, user, aa, null);
- }
-
- Client(IBinder token, Uri uri, UserHandle user, AudioAttributes aa,
- @Nullable VolumeShaper.Configuration volumeShaperConfig) {
+ Client(IBinder token, Ringtone ringtone) {
mToken = token;
-
- mRingtone = new Ringtone(getContextForUser(user), false);
- mRingtone.setAudioAttributesField(aa);
- mRingtone.setUri(uri, volumeShaperConfig);
- mRingtone.createLocalMediaPlayer();
+ mRingtone = ringtone;
}
@Override
@@ -129,11 +120,28 @@ public class RingtonePlayer implements CoreStartable {
Client client;
synchronized (mClients) {
client = mClients.get(token);
- if (client == null) {
- final UserHandle user = Binder.getCallingUserHandle();
- client = new Client(token, uri, user, aa, volumeShaperConfig);
- token.linkToDeath(client, 0);
- mClients.put(token, client);
+ }
+ // Don't hold the lock while constructing the ringtone, since it can be slow. The caller
+ // shouldn't call play on the same ringtone from 2 threads, so this shouldn't race and
+ // waste the build.
+ if (client == null) {
+ final UserHandle user = Binder.getCallingUserHandle();
+ Ringtone ringtone = new Ringtone(getContextForUser(user), false);
+ ringtone.setAudioAttributesField(aa);
+ ringtone.setUri(uri, volumeShaperConfig);
+ ringtone.createLocalMediaPlayer();
+ synchronized (mClients) {
+ client = mClients.get(token);
+ if (client == null) {
+ client = new Client(token, ringtone);
+ token.linkToDeath(client, 0);
+ mClients.put(token, client);
+ ringtone = null; // "owned" by the client now.
+ }
+ }
+ // Clean up ringtone if it was abandoned (a client already existed).
+ if (ringtone != null) {
+ ringtone.stop();
}
}
client.mRingtone.setLooping(looping);
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
index 120704c0582a..3fc3ad682bc7 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDeviceManager.kt
@@ -154,6 +154,7 @@ constructor(
get() = controller?.sessionToken
private var started = false
private var playbackType = PLAYBACK_TYPE_UNKNOWN
+ private var playbackVolumeControlId: String? = null
private var current: MediaDeviceData? = null
set(value) {
val sameWithoutIcon = value != null && value.equalsWithoutIcon(field)
@@ -181,6 +182,7 @@ constructor(
localMediaManager.startScan()
muteAwaitConnectionManager?.startListening()
playbackType = controller?.playbackInfo?.playbackType ?: PLAYBACK_TYPE_UNKNOWN
+ playbackVolumeControlId = controller?.playbackInfo?.volumeControlId
controller?.registerCallback(this)
updateCurrent()
started = true
@@ -209,6 +211,8 @@ constructor(
println(" current device is ${current?.name}")
val type = controller?.playbackInfo?.playbackType
println(" PlaybackType=$type (1 for local, 2 for remote) cached=$playbackType")
+ val volumeControlId = controller?.playbackInfo?.volumeControlId
+ println(" volumeControlId=$volumeControlId cached= $playbackVolumeControlId")
println(" routingSession=$routingSession")
println(" selectedRoutes=$selectedRoutes")
}
@@ -217,10 +221,15 @@ constructor(
@WorkerThread
override fun onAudioInfoChanged(info: MediaController.PlaybackInfo?) {
val newPlaybackType = info?.playbackType ?: PLAYBACK_TYPE_UNKNOWN
- if (newPlaybackType == playbackType) {
+ val newPlaybackVolumeControlId = info?.volumeControlId
+ if (
+ newPlaybackType == playbackType &&
+ newPlaybackVolumeControlId == playbackVolumeControlId
+ ) {
return
}
playbackType = newPlaybackType
+ playbackVolumeControlId = newPlaybackVolumeControlId
updateCurrent()
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
index 0aa434976ce7..1e9a466ccdce 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt
@@ -67,6 +67,7 @@ import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.time.SystemClock
import com.android.systemui.util.traceSection
import java.io.PrintWriter
+import java.util.Locale
import java.util.TreeMap
import javax.inject.Inject
import javax.inject.Provider
@@ -166,6 +167,8 @@ constructor(
}
}
+ private var carouselLocale: Locale? = null
+
/** Whether the media card currently has the "expanded" layout */
@VisibleForTesting
var currentlyExpanded = true
@@ -218,6 +221,15 @@ constructor(
updatePlayers(recreateMedia = false)
inflateSettingsButton()
}
+
+ override fun onLocaleListChanged() {
+ // Update players only if system primary language changes.
+ if (carouselLocale != context.resources.configuration.locales.get(0)) {
+ carouselLocale = context.resources.configuration.locales.get(0)
+ updatePlayers(recreateMedia = true)
+ inflateSettingsButton()
+ }
+ }
}
private val keyguardUpdateMonitorCallback =
@@ -262,6 +274,7 @@ constructor(
this::logSmartspaceImpression,
logger
)
+ carouselLocale = context.resources.configuration.locales.get(0)
isRtl = context.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL
inflateSettingsButton()
mediaContent = mediaCarousel.requireViewById(R.id.media_carousel)
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 9ebc8e410013..8e014c61c641 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -126,10 +126,11 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
private final LocalBluetoothManager mLocalBluetoothManager;
private final ActivityStarter mActivityStarter;
private final DialogLaunchAnimator mDialogLaunchAnimator;
- private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
private final CommonNotifCollection mNotifCollection;
private final Object mMediaDevicesLock = new Object();
@VisibleForTesting
+ final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
+ @VisibleForTesting
final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>();
final List<MediaDevice> mCachedMediaDevices = new CopyOnWriteArrayList<>();
private final List<MediaItem> mMediaItemList = new CopyOnWriteArrayList<>();
@@ -713,7 +714,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
dividerItems.forEach((key, item) -> {
finalMediaItems.add(key, item);
});
- finalMediaItems.add(new MediaItem());
+ attachConnectNewDeviceItemIfNeeded(finalMediaItems);
mMediaItemList.clear();
mMediaItemList.addAll(finalMediaItems);
}
@@ -749,7 +750,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
finalMediaItems.add(new MediaItem(device));
}
}
- finalMediaItems.add(new MediaItem());
+ attachConnectNewDeviceItemIfNeeded(finalMediaItems);
mMediaItemList.clear();
mMediaItemList.addAll(finalMediaItems);
}
@@ -760,6 +761,13 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
new MediaItem(title, MediaItem.MediaItemType.TYPE_GROUP_DIVIDER));
}
+ private void attachConnectNewDeviceItemIfNeeded(List<MediaItem> mediaItems) {
+ // Attach "Connect a device" item only when current output is not remote and not a group
+ if (!isCurrentConnectedDeviceRemote() && getSelectedMediaDevice().size() == 1) {
+ mediaItems.add(new MediaItem());
+ }
+ }
+
private void attachRangeInfo(List<MediaDevice> devices) {
for (MediaDevice mediaDevice : devices) {
if (mNearbyDeviceInfoMap.containsKey(mediaDevice.getId())) {
@@ -1251,7 +1259,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
return null;
}
- private final MediaController.Callback mCb = new MediaController.Callback() {
+ @VisibleForTesting
+ final MediaController.Callback mCb = new MediaController.Callback() {
@Override
public void onMetadataChanged(MediaMetadata metadata) {
mCallback.onMediaChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index 8aec0c61c75c..d4052f54b3da 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -42,7 +42,6 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
import com.android.systemui.notetask.NoteTaskRoleManagerExt.createNoteShortcutInfoAsUser
import com.android.systemui.notetask.NoteTaskRoleManagerExt.getDefaultRoleHolderAsUser
-import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskManagedProfileProxyActivity
import com.android.systemui.settings.UserTracker
import com.android.systemui.shared.system.ActivityManagerKt.isInForeground
@@ -231,8 +230,6 @@ constructor(
* Widget Picker to all users.
*/
fun setNoteTaskShortcutEnabled(value: Boolean, user: UserHandle) {
- val componentName = ComponentName(context, CreateNoteTaskShortcutActivity::class.java)
-
val enabledState =
if (value) {
PackageManager.COMPONENT_ENABLED_STATE_ENABLED
@@ -249,8 +246,9 @@ constructor(
} else {
context.createContextAsUser(user, /* flags= */ 0)
}
+
userContext.packageManager.setComponentEnabledSetting(
- componentName,
+ SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT,
enabledState,
PackageManager.DONT_KILL_APP,
)
@@ -298,6 +296,19 @@ constructor(
companion object {
val TAG = NoteTaskController::class.simpleName.orEmpty()
+ /**
+ * IMPORTANT! The shortcut package name and class should be synchronized with Settings:
+ * [com.android.settings.notetask.shortcut.CreateNoteTaskShortcutActivity].
+ *
+ * Changing the package name or class is a breaking change.
+ */
+ @VisibleForTesting
+ val SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT =
+ ComponentName(
+ "com.android.settings",
+ "com.android.settings.notetask.shortcut.CreateNoteTaskShortcutActivity",
+ )
+
const val SHORTCUT_ID = "note_task_shortcut_id"
/**
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
index a166393ec29c..2c62ffd4841f 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskModule.kt
@@ -24,7 +24,6 @@ import android.app.role.RoleManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceModule
-import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskManagedProfileProxyActivity
import dagger.Binds
@@ -46,9 +45,6 @@ interface NoteTaskModule {
@[Binds IntoMap ClassKey(LaunchNoteTaskManagedProfileProxyActivity::class)]
fun LaunchNoteTaskManagedProfileProxyActivity.bindNoteTaskLauncherProxyActivity(): Activity
- @[Binds IntoMap ClassKey(CreateNoteTaskShortcutActivity::class)]
- fun CreateNoteTaskShortcutActivity.bindNoteTaskShortcutActivity(): Activity
-
companion object {
@[Provides NoteTaskEnabledKey]
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt b/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
deleted file mode 100644
index 0cfb0a521820..000000000000
--- a/packages/SystemUI/src/com/android/systemui/notetask/shortcut/CreateNoteTaskShortcutActivity.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.
- */
-
-@file:OptIn(InternalNoteTaskApi::class)
-
-package com.android.systemui.notetask.shortcut
-
-import android.app.Activity
-import android.app.role.RoleManager
-import android.content.pm.ShortcutManager
-import android.os.Bundle
-import androidx.activity.ComponentActivity
-import com.android.systemui.notetask.InternalNoteTaskApi
-import com.android.systemui.notetask.NoteTaskRoleManagerExt.createNoteShortcutInfoAsUser
-import javax.inject.Inject
-
-/**
- * Activity responsible for create a shortcut for notes action. If the shortcut is enabled, a new
- * shortcut will appear in the widget picker. If the shortcut is selected, the Activity here will be
- * launched, creating a new shortcut for [CreateNoteTaskShortcutActivity], and will finish.
- *
- * @see <a
- * href="https://developer.android.com/develop/ui/views/launch/shortcuts/creating-shortcuts#custom-pinned">Creating
- * a custom shortcut activity</a>
- */
-class CreateNoteTaskShortcutActivity
-@Inject
-constructor(
- private val roleManager: RoleManager,
- private val shortcutManager: ShortcutManager,
-) : ComponentActivity() {
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
-
- val shortcutInfo = roleManager.createNoteShortcutInfoAsUser(context = this, user)
- val shortcutIntent = shortcutManager.createShortcutResultIntent(shortcutInfo)
- setResult(Activity.RESULT_OK, shortcutIntent)
-
- finish()
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt b/packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt
index 6f645b562008..995c6a476f0d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/HeaderPrivacyIconsController.kt
@@ -26,7 +26,9 @@ import java.util.concurrent.Executor
import javax.inject.Inject
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.shade.ShadeModule.Companion.SHADE_HEADER
import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import javax.inject.Named
interface ChipVisibilityListener {
fun onChipVisibilityRefreshed(visible: Boolean)
@@ -45,10 +47,10 @@ interface ChipVisibilityListener {
class HeaderPrivacyIconsController @Inject constructor(
private val privacyItemController: PrivacyItemController,
private val uiEventLogger: UiEventLogger,
- private val privacyChip: OngoingPrivacyChip,
+ @Named(SHADE_HEADER) private val privacyChip: OngoingPrivacyChip,
private val privacyDialogController: PrivacyDialogController,
private val privacyLogger: PrivacyLogger,
- private val iconContainer: StatusIconContainer,
+ @Named(SHADE_HEADER) private val iconContainer: StatusIconContainer,
private val permissionManager: PermissionManager,
@Background private val backgroundExecutor: Executor,
@Main private val uiExecutor: Executor,
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/MediaProjectionPermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/MediaProjectionPermissionDialog.kt
index 201557c03e48..f4f5f66dfb09 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/MediaProjectionPermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/MediaProjectionPermissionDialog.kt
@@ -28,12 +28,14 @@ class MediaProjectionPermissionDialog(
) : BaseScreenSharePermissionDialog(context, createOptionList(appName), appName) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ // TODO(b/270018943): Handle the case of System sharing (not recording nor casting)
if (appName == null) {
- setDialogTitle(R.string.media_projection_permission_dialog_system_service_title)
+ setDialogTitle(R.string.media_projection_entry_cast_permission_dialog_title)
+ setStartButtonText(R.string.media_projection_entry_cast_permission_dialog_continue)
} else {
- setDialogTitle(R.string.media_projection_permission_dialog_title)
+ setDialogTitle(R.string.media_projection_entry_app_permission_dialog_title)
+ setStartButtonText(R.string.media_projection_entry_app_permission_dialog_continue)
}
- setStartButtonText(R.string.media_projection_permission_dialog_continue)
setStartButtonOnClickListener {
// Note that it is important to run this callback before dismissing, so that the
// callback can disable the dialog exit animation if it wants to.
@@ -50,26 +52,26 @@ class MediaProjectionPermissionDialog(
private fun createOptionList(appName: String?): List<ScreenShareOption> {
val singleAppWarningText =
if (appName == null) {
- R.string.media_projection_permission_dialog_system_service_warning_single_app
+ R.string.media_projection_entry_cast_permission_dialog_warning_single_app
} else {
- R.string.media_projection_permission_dialog_warning_single_app
+ R.string.media_projection_entry_app_permission_dialog_warning_single_app
}
val entireScreenWarningText =
if (appName == null) {
- R.string.media_projection_permission_dialog_system_service_warning_entire_screen
+ R.string.media_projection_entry_cast_permission_dialog_warning_entire_screen
} else {
- R.string.media_projection_permission_dialog_warning_entire_screen
+ R.string.media_projection_entry_app_permission_dialog_warning_entire_screen
}
return listOf(
ScreenShareOption(
mode = ENTIRE_SCREEN,
- spinnerText = R.string.media_projection_permission_dialog_option_entire_screen,
+ spinnerText = R.string.screen_share_permission_dialog_option_entire_screen,
warningText = entireScreenWarningText
),
ScreenShareOption(
mode = SINGLE_APP,
- spinnerText = R.string.media_projection_permission_dialog_option_single_app,
+ spinnerText = R.string.screen_share_permission_dialog_option_single_app,
warningText = singleAppWarningText
)
)
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index 4349bd71f670..69008cca6fe3 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -262,7 +262,7 @@ public class RecordingService extends Service implements ScreenMediaRecorderList
Resources res = getResources();
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
- getString(R.string.screenrecord_name),
+ getString(R.string.screenrecord_title),
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(getString(R.string.screenrecord_channel_description));
channel.enableVibration(true);
@@ -270,7 +270,7 @@ public class RecordingService extends Service implements ScreenMediaRecorderList
Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
- res.getString(R.string.screenrecord_name));
+ res.getString(R.string.screenrecord_title));
String notificationTitle = res.getString(R.string.screenrecord_start_error);
Notification.Builder builder = new Notification.Builder(this, CHANNEL_ID)
@@ -290,7 +290,7 @@ public class RecordingService extends Service implements ScreenMediaRecorderList
Resources res = getResources();
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
- getString(R.string.screenrecord_name),
+ getString(R.string.screenrecord_title),
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(getString(R.string.screenrecord_channel_description));
channel.enableVibration(true);
@@ -298,7 +298,7 @@ public class RecordingService extends Service implements ScreenMediaRecorderList
Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
- res.getString(R.string.screenrecord_name));
+ res.getString(R.string.screenrecord_title));
String notificationTitle = mAudioSource == ScreenRecordingAudioSource.NONE
? res.getString(R.string.screenrecord_ongoing_screen_only)
@@ -335,7 +335,7 @@ public class RecordingService extends Service implements ScreenMediaRecorderList
Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
- res.getString(R.string.screenrecord_name));
+ res.getString(R.string.screenrecord_title));
Notification.Builder builder = new Notification.Builder(getApplicationContext(), CHANNEL_ID)
.setContentTitle(notificationTitle)
@@ -365,7 +365,7 @@ public class RecordingService extends Service implements ScreenMediaRecorderList
Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
- getResources().getString(R.string.screenrecord_name));
+ getResources().getString(R.string.screenrecord_title));
Notification.Builder builder = new Notification.Builder(this, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_screenrecord)
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
index efa45a4c4723..2a21aaa81404 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
@@ -100,7 +100,7 @@ public class ScreenRecordDialog extends SystemUIDialog {
window.addPrivateFlags(WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS);
window.setGravity(Gravity.CENTER);
- setTitle(R.string.screenrecord_name);
+ setTitle(R.string.screenrecord_title);
setContentView(R.layout.screen_record_dialog);
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
index 30509e23d186..bfaf3d0d2ec5 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordPermissionDialog.kt
@@ -62,8 +62,8 @@ class ScreenRecordPermissionDialog(
private lateinit var options: Spinner
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setDialogTitle(R.string.screenrecord_start_label)
- setStartButtonText(R.string.screenrecord_start_recording)
+ setDialogTitle(R.string.screenrecord_permission_dialog_title)
+ setStartButtonText(R.string.screenrecord_permission_dialog_continue)
setStartButtonOnClickListener { v: View? ->
onStartRecordingClicked?.run()
if (selectedScreenShareOption.mode == ENTIRE_SCREEN) {
@@ -186,13 +186,13 @@ class ScreenRecordPermissionDialog(
return listOf(
ScreenShareOption(
ENTIRE_SCREEN,
- R.string.screenrecord_option_entire_screen,
- R.string.screenrecord_warning_entire_screen
+ R.string.screen_share_permission_dialog_option_entire_screen,
+ R.string.screenrecord_permission_dialog_warning_entire_screen
),
ScreenShareOption(
SINGLE_APP,
- R.string.screenrecord_option_single_app,
- R.string.screenrecord_warning_single_app
+ R.string.screen_share_permission_dialog_option_single_app,
+ R.string.screenrecord_permission_dialog_warning_single_app
)
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
index aa8e2c039684..187019a4851d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ActionIntentExecutor.kt
@@ -154,5 +154,5 @@ private val SCREENSHOT_REMOTE_RUNNER: IRemoteAnimationRunner.Stub =
}
}
- override fun onAnimationCancelled(isKeyguardOccluded: Boolean) {}
+ override fun onAnimationCancelled() {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index c9d1da38b196..77a65b22a7f4 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -150,7 +150,7 @@ public class ScreenshotController {
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
index b3d31f2986d1..7e0f50400299 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/CombinedShadeHeadersConstraintManagerImpl.kt
@@ -19,12 +19,12 @@ package com.android.systemui.shade
import android.view.ViewGroup
import androidx.constraintlayout.widget.ConstraintSet
import com.android.systemui.R
-import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent
+import com.android.systemui.dagger.SysUISingleton
/**
* Standard implementation of [CombinedShadeHeadersConstraintManager].
*/
-@CentralSurfacesComponent.CentralSurfacesScope
+@SysUISingleton
object CombinedShadeHeadersConstraintManagerImpl : CombinedShadeHeadersConstraintManager {
override fun privacyChipVisibilityConstraints(visible: Boolean): ConstraintsChanges {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index ef14d1cb7f63..4012736b8beb 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -70,6 +70,7 @@ import com.android.systemui.media.controls.ui.MediaHierarchyManager;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.screenrecord.RecordingController;
+import com.android.systemui.shade.data.repository.ShadeRepository;
import com.android.systemui.shade.transition.ShadeTransitionController;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
@@ -136,6 +137,7 @@ public class QuickSettingsController {
private final KeyguardFaceAuthInteractor mKeyguardFaceAuthInteractor;
private final FeatureFlags mFeatureFlags;
private final InteractionJankMonitor mInteractionJankMonitor;
+ private final ShadeRepository mShadeRepository;
private final FalsingManager mFalsingManager;
private final AccessibilityManager mAccessibilityManager;
private final MetricsLogger mMetricsLogger;
@@ -321,7 +323,8 @@ public class QuickSettingsController {
FeatureFlags featureFlags,
InteractionJankMonitor interactionJankMonitor,
ShadeLogger shadeLog,
- KeyguardFaceAuthInteractor keyguardFaceAuthInteractor
+ KeyguardFaceAuthInteractor keyguardFaceAuthInteractor,
+ ShadeRepository shadeRepository
) {
mPanelViewControllerLazy = panelViewControllerLazy;
mPanelView = panelView;
@@ -363,6 +366,7 @@ public class QuickSettingsController {
mKeyguardFaceAuthInteractor = keyguardFaceAuthInteractor;
mFeatureFlags = featureFlags;
mInteractionJankMonitor = interactionJankMonitor;
+ mShadeRepository = shadeRepository;
mLockscreenShadeTransitionController.addCallback(new LockscreenShadeTransitionCallback());
}
@@ -1001,6 +1005,7 @@ public class QuickSettingsController {
mDepthController.setQsPanelExpansion(qsExpansionFraction);
mStatusBarKeyguardViewManager.setQsExpansion(qsExpansionFraction);
+ mShadeRepository.setQsExpansion(qsExpansionFraction);
// TODO (b/265193930): remove dependency on NPVC
float shadeExpandedFraction = mBarState == KEYGUARD
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
index f0815e93dccd..86ae4ecf6e70 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeHeaderController.kt
@@ -41,6 +41,7 @@ import com.android.systemui.animation.Interpolators
import com.android.systemui.animation.ShadeInterpolation
import com.android.systemui.battery.BatteryMeterView
import com.android.systemui.battery.BatteryMeterViewController
+import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.demomode.DemoMode
import com.android.systemui.demomode.DemoModeController
import com.android.systemui.dump.DumpManager
@@ -52,14 +53,13 @@ import com.android.systemui.shade.ShadeHeaderController.Companion.LARGE_SCREEN_H
import com.android.systemui.shade.ShadeHeaderController.Companion.LARGE_SCREEN_HEADER_TRANSITION_ID
import com.android.systemui.shade.ShadeHeaderController.Companion.QQS_HEADER_CONSTRAINT
import com.android.systemui.shade.ShadeHeaderController.Companion.QS_HEADER_CONSTRAINT
+import com.android.systemui.shade.ShadeModule.Companion.SHADE_HEADER
import com.android.systemui.shade.carrier.ShadeCarrierGroup
import com.android.systemui.shade.carrier.ShadeCarrierGroupController
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.statusbar.phone.StatusBarIconController
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.phone.StatusIconContainer
-import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
-import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SHADE_HEADER
import com.android.systemui.statusbar.policy.Clock
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.NextAlarmController
@@ -79,7 +79,7 @@ import javax.inject.Named
* * [LARGE_SCREEN_HEADER_TRANSITION_ID]: [LARGE_SCREEN_HEADER_CONSTRAINT] for all other
* configurations
*/
-@CentralSurfacesScope
+@SysUISingleton
class ShadeHeaderController
@Inject
constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
index 9cd8c547d1c1..b7551cf3408e 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeModule.kt
@@ -16,21 +16,36 @@
package com.android.systemui.shade
+import android.content.ContentResolver
+import android.os.Handler
import android.view.LayoutInflater
+import android.view.ViewStub
+import androidx.constraintlayout.motion.widget.MotionLayout
import com.android.keyguard.LockIconView
import com.android.systemui.CoreStartable
import com.android.systemui.R
+import com.android.systemui.battery.BatteryMeterView
+import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.biometrics.AuthRippleController
import com.android.systemui.biometrics.AuthRippleView
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.privacy.OngoingPrivacyChip
+import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
+import com.android.systemui.statusbar.phone.StatusIconContainer
import com.android.systemui.statusbar.phone.TapAgainView
+import com.android.systemui.statusbar.policy.BatteryController
+import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.tuner.TunerService
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
+import javax.inject.Named
/** Module for classes related to the notification shade. */
@Module
@@ -42,6 +57,8 @@ abstract class ShadeModule {
abstract fun bindAuthRippleController(controller: AuthRippleController): CoreStartable
companion object {
+ const val SHADE_HEADER = "large_screen_shade_header"
+
@Provides
@SysUISingleton
// TODO(b/277762009): Do something similar to
@@ -109,5 +126,75 @@ abstract class ShadeModule {
): TapAgainView {
return notificationPanelView.findViewById(R.id.shade_falsing_tap_again)
}
+
+ // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
+ @Provides
+ @SysUISingleton
+ @Named(SHADE_HEADER)
+ fun providesShadeHeaderView(
+ notificationShadeWindowView: NotificationShadeWindowView,
+ ): MotionLayout {
+ val stub = notificationShadeWindowView.findViewById<ViewStub>(R.id.qs_header_stub)
+ val layoutId = R.layout.combined_qs_header
+ stub.layoutResource = layoutId
+ return stub.inflate() as MotionLayout
+ }
+
+ @Provides
+ @SysUISingleton
+ fun providesCombinedShadeHeadersConstraintManager(): CombinedShadeHeadersConstraintManager {
+ return CombinedShadeHeadersConstraintManagerImpl
+ }
+
+ // TODO(b/277762009): Only allow this view's controller to inject the view. See above.
+ @Provides
+ @SysUISingleton
+ @Named(SHADE_HEADER)
+ fun providesBatteryMeterView(@Named(SHADE_HEADER) view: MotionLayout): BatteryMeterView {
+ return view.findViewById(R.id.batteryRemainingIcon)
+ }
+
+ @Provides
+ @SysUISingleton
+ @Named(SHADE_HEADER)
+ fun providesBatteryMeterViewController(
+ @Named(SHADE_HEADER) batteryMeterView: BatteryMeterView,
+ userTracker: UserTracker,
+ configurationController: ConfigurationController,
+ tunerService: TunerService,
+ @Main mainHandler: Handler,
+ contentResolver: ContentResolver,
+ featureFlags: FeatureFlags,
+ batteryController: BatteryController,
+ ): BatteryMeterViewController {
+ return BatteryMeterViewController(
+ batteryMeterView,
+ userTracker,
+ configurationController,
+ tunerService,
+ mainHandler,
+ contentResolver,
+ featureFlags,
+ batteryController,
+ )
+ }
+
+ @Provides
+ @SysUISingleton
+ @Named(SHADE_HEADER)
+ fun providesOngoingPrivacyChip(
+ @Named(SHADE_HEADER) header: MotionLayout,
+ ): OngoingPrivacyChip {
+ return header.findViewById(R.id.privacy_chip)
+ }
+
+ @Provides
+ @SysUISingleton
+ @Named(SHADE_HEADER)
+ fun providesStatusIconContainer(
+ @Named(SHADE_HEADER) header: MotionLayout,
+ ): StatusIconContainer {
+ return header.findViewById(R.id.statusIcons)
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
index bf7a2be2e4ca..44c8e48c65d4 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
@@ -25,11 +25,23 @@ import com.android.systemui.shade.domain.model.ShadeModel
import javax.inject.Inject
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
interface ShadeRepository {
/** ShadeModel information regarding shade expansion events */
val shadeModel: Flow<ShadeModel>
+
+ /** Amount qs has expanded. Quick Settings can be expanded without the full shade expansion. */
+ val qsExpansion: StateFlow<Float>
+
+ /** Amount shade has expanded with regard to the UDFPS location */
+ val udfpsTransitionToFullShadeProgress: StateFlow<Float>
+
+ fun setQsExpansion(qsExpansion: Float)
+ fun setUdfpsTransitionToFullShadeProgress(progress: Float)
}
/** Business logic for shade interactions */
@@ -62,6 +74,20 @@ constructor(shadeExpansionStateManager: ShadeExpansionStateManager) : ShadeRepos
}
.distinctUntilChanged()
+ private val _qsExpansion = MutableStateFlow(0f)
+ override val qsExpansion: StateFlow<Float> = _qsExpansion.asStateFlow()
+
+ private var _udfpsTransitionToFullShadeProgress = MutableStateFlow(0f)
+ override val udfpsTransitionToFullShadeProgress: StateFlow<Float> =
+ _udfpsTransitionToFullShadeProgress.asStateFlow()
+ override fun setQsExpansion(qsExpansion: Float) {
+ _qsExpansion.value = qsExpansion
+ }
+
+ override fun setUdfpsTransitionToFullShadeProgress(progress: Float) {
+ _udfpsTransitionToFullShadeProgress.value = progress
+ }
+
companion object {
private const val TAG = "ShadeRepository"
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LegacyNotificationShelfControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/LegacyNotificationShelfControllerImpl.java
index 4ef20633ac21..505f45d021b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LegacyNotificationShelfControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LegacyNotificationShelfControllerImpl.java
@@ -52,7 +52,7 @@ public class LegacyNotificationShelfControllerImpl implements NotificationShelfC
mActivatableNotificationViewController = activatableNotificationViewController;
mKeyguardBypassController = keyguardBypassController;
mStatusBarStateController = statusBarStateController;
- mView.useRoundnessSourceTypes(featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES));
+ mView.useRoundnessSourceTypes(true);
mView.setSensitiveRevealAnimEndabled(featureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM));
mOnAttachStateChangeListener = new View.OnAttachStateChangeListener() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index c5f64b0a2306..7f016f304e05 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -32,6 +32,7 @@ import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.qs.QS
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shade.ShadeViewController
+import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
@@ -74,6 +75,7 @@ class LockscreenShadeTransitionController @Inject constructor(
falsingManager: FalsingManager,
dumpManager: DumpManager,
qsTransitionControllerFactory: LockscreenShadeQsTransitionController.Factory,
+ private val shadeRepository: ShadeRepository,
) : Dumpable {
private var pulseHeight: Float = 0f
@get:VisibleForTesting
@@ -449,6 +451,7 @@ class LockscreenShadeTransitionController @Inject constructor(
}
val udfpsProgress = MathUtils.saturate(dragDownAmount / udfpsTransitionDistance)
+ shadeRepository.setUdfpsTransitionToFullShadeProgress(udfpsProgress)
udfpsKeyguardViewController?.setTransitionToFullShadeProgress(udfpsProgress)
val statusBarProgress = MathUtils.saturate(dragDownAmount / statusBarTransitionDistance)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index 9bf05cb47f04..19c612ed21ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -261,8 +261,7 @@ public class ExpandableNotificationRowController implements NotifViewController
mStatusBarStateController.removeCallback(mStatusBarStateListener);
}
});
- mView.useRoundnessSourceTypes(
- mFeatureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES));
+ mView.useRoundnessSourceTypes(true);
}
private final StatusBarStateController.StateListener mStatusBarStateListener =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt
index 99c6ddb8cfaa..81067157ca5b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shelf/ui/viewbinder/NotificationShelfViewBinder.kt
@@ -81,7 +81,7 @@ object NotificationShelfViewBinder {
ActivatableNotificationViewBinder.bind(viewModel, shelf, falsingManager)
shelf.apply {
setRefactorFlagEnabled(true)
- useRoundnessSourceTypes(featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES))
+ useRoundnessSourceTypes(true)
setSensitiveRevealAnimEndabled(featureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM))
// TODO(278765923): Replace with eventual NotificationIconContainerViewBinder#bind()
notificationIconAreaController.setShelfIcons(shelfIcons)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
index fde8c4d453ce..b6aec83ae600 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
@@ -25,8 +25,6 @@ import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.statusbar.notification.LegacySourceType;
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
import com.android.systemui.statusbar.notification.Roundable;
@@ -73,8 +71,7 @@ public class NotificationRoundnessManager implements Dumpable {
NotificationRoundnessManager(
NotificationSectionsFeatureManager sectionsFeatureManager,
NotificationRoundnessLogger notifLogger,
- DumpManager dumpManager,
- FeatureFlags featureFlags) {
+ DumpManager dumpManager) {
int numberOfSections = sectionsFeatureManager.getNumberOfBuckets();
mFirstInSectionViews = new ExpandableView[numberOfSections];
mLastInSectionViews = new ExpandableView[numberOfSections];
@@ -82,7 +79,7 @@ public class NotificationRoundnessManager implements Dumpable {
mTmpLastInSectionViews = new ExpandableView[numberOfSections];
mNotifLogger = notifLogger;
mDumpManager = dumpManager;
- mUseRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES);
+ mUseRoundnessSourceTypes = true;
mDumpManager.registerDumpable(TAG, this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
index 070b4394291f..57b6dbce5398 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
@@ -19,8 +19,6 @@ import android.annotation.ColorInt
import android.util.Log
import android.view.View
import com.android.internal.annotations.VisibleForTesting
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.media.controls.ui.KeyguardMediaController
import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
import com.android.systemui.statusbar.notification.SourceType
@@ -51,11 +49,10 @@ class NotificationSectionsManager @Inject internal constructor(
@IncomingHeader private val incomingHeaderController: SectionHeaderController,
@PeopleHeader private val peopleHeaderController: SectionHeaderController,
@AlertingHeader private val alertingHeaderController: SectionHeaderController,
- @SilentHeader private val silentHeaderController: SectionHeaderController,
- featureFlags: FeatureFlags
+ @SilentHeader private val silentHeaderController: SectionHeaderController
) : SectionProvider {
- private val useRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES)
+ private val useRoundnessSourceTypes = true
private val configurationListener = object : ConfigurationController.ConfigurationListener {
override fun onLocaleListChanged() {
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 3bc2066d4410..abcb825c3e18 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
@@ -625,7 +625,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mDebugLines = featureFlags.isEnabled(Flags.NSSL_DEBUG_LINES);
mDebugRemoveAnimation = featureFlags.isEnabled(Flags.NSSL_DEBUG_REMOVE_ANIMATION);
mSimplifiedAppearFraction = featureFlags.isEnabled(Flags.SIMPLIFIED_APPEAR_FRACTION);
- mUseRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES);
+ mUseRoundnessSourceTypes = true;
mSensitiveRevealAnimEndabled = featureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM);
setAnimatedInsetsEnabled(featureFlags.isEnabled(Flags.ANIMATED_NOTIFICATION_SHADE_INSETS));
mSectionsManager = Dependency.get(NotificationSectionsManager.class);
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 4751fb68697b..d96a2cd4f760 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
@@ -61,7 +61,6 @@ import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.media.controls.ui.KeyguardMediaController;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
@@ -126,8 +125,6 @@ import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.Compile;
import com.android.systemui.util.settings.SecureSettings;
-import kotlin.Unit;
-
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -723,7 +720,7 @@ public class NotificationStackScrollLayoutController {
mShadeController = shadeController;
mNotifIconAreaController = notifIconAreaController;
mFeatureFlags = featureFlags;
- mUseRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES);
+ mUseRoundnessSourceTypes = true;
mNotificationTargetsHelper = notificationTargetsHelper;
mSecureSettings = secureSettings;
mDismissibilityProvider = dismissibilityProvider;
@@ -822,7 +819,7 @@ public class NotificationStackScrollLayoutController {
mView.generateRemoveAnimation(mKeyguardMediaController.getSinglePaneContainer());
}
mView.requestChildrenUpdate();
- return Unit.INSTANCE;
+ return kotlin.Unit.INSTANCE;
});
// attach callback, and then call it to update mView immediately
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index 91f53b630c73..2d0a6cf8e5a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -35,7 +35,6 @@ import com.android.internal.jank.InteractionJankMonitor;
import com.android.systemui.SwipeHelper;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
@@ -81,7 +80,7 @@ class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeAc
NotificationRoundnessManager notificationRoundnessManager) {
super(callback, resources, viewConfiguration, falsingManager, featureFlags);
mNotificationRoundnessManager = notificationRoundnessManager;
- mUseRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES);
+ mUseRoundnessSourceTypes = true;
mMenuListener = menuListener;
mCallback = callback;
mFalsingCheck = () -> resetExposedMenuView(true /* animate */, true /* force */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
index 8b6d6a4f3170..cd0c1b153816 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelper.kt
@@ -20,7 +20,7 @@ class NotificationTargetsHelper
constructor(
featureFlags: FeatureFlags,
) {
- private val useRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES)
+ private val useRoundnessSourceTypes = true
/**
* This method looks for views that can be rounded (and implement [Roundable]) during a
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index e705afc21c40..0c4821c003dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -27,8 +27,6 @@ import androidx.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.widget.ViewClippingUtil;
import com.android.systemui.R;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.ShadeHeadsUpTracker;
@@ -120,14 +118,13 @@ public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBar
NotificationStackScrollLayoutController stackScrollerController,
ShadeViewController shadeViewController,
NotificationRoundnessManager notificationRoundnessManager,
- FeatureFlags featureFlags,
HeadsUpStatusBarView headsUpStatusBarView,
Clock clockView,
@Named(OPERATOR_NAME_FRAME_VIEW) Optional<View> operatorNameViewOptional) {
super(headsUpStatusBarView);
mNotificationIconAreaController = notificationIconAreaController;
mNotificationRoundnessManager = notificationRoundnessManager;
- mUseRoundnessSourceTypes = featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES);
+ mUseRoundnessSourceTypes = true;
mHeadsUpManager = headsUpManager;
// We may be mid-HUN-expansion when this controller is re-created (for example, if the user
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
index c17366ad242c..74ab47ff27a1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -115,7 +115,9 @@ class KeyguardLiftController @Inject constructor(
val onKeyguard = keyguardUpdateMonitor.isKeyguardVisible &&
!statusBarStateController.isDozing
- val shouldListen = (onKeyguard || bouncerVisible) && keyguardUpdateMonitor.isFaceEnrolled
+ val userId = KeyguardUpdateMonitor.getCurrentUser()
+ val isFaceEnabled = keyguardUpdateMonitor.isFaceAuthEnabledForUser(userId)
+ val shouldListen = (onKeyguard || bouncerVisible) && isFaceEnabled
if (shouldListen != isListening) {
isListening = shouldListen
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 89dddbf1f573..f2fbd7d52ac3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -136,7 +136,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private final DreamOverlayStateController mDreamOverlayStateController;
@Nullable
private final FoldAodAnimationController mFoldAodAnimationController;
- private KeyguardMessageAreaController<AuthKeyguardMessageArea> mKeyguardMessageAreaController;
+ KeyguardMessageAreaController<AuthKeyguardMessageArea> mKeyguardMessageAreaController;
private final PrimaryBouncerCallbackInteractor mPrimaryBouncerCallbackInteractor;
private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
private final AlternateBouncerInteractor mAlternateBouncerInteractor;
@@ -430,6 +430,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mDockManager.addListener(mDockEventListener);
mIsDocked = mDockManager.isDocked();
}
+ mKeyguardStateController.addCallback(mKeyguardStateControllerCallback);
}
/** Register a callback, to be invoked by the Predictive Back system. */
@@ -1564,6 +1565,14 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
|| mode == KeyguardSecurityModel.SecurityMode.SimPuk;
}
+ private KeyguardStateController.Callback mKeyguardStateControllerCallback =
+ new KeyguardStateController.Callback() {
+ @Override
+ public void onUnlockedChanged() {
+ updateAlternateBouncerShowing(mAlternateBouncerInteractor.maybeHide());
+ }
+ };
+
/**
* Delegate used to send show and hide events to an alternate authentication method instead of
* the regular pin/pattern/password bouncer.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
index 2c57a268f6b8..67243b6aed00 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
@@ -16,26 +16,15 @@
package com.android.systemui.statusbar.phone.dagger;
-import android.content.ContentResolver;
-import android.os.Handler;
import android.view.LayoutInflater;
-import android.view.ViewStub;
-
-import androidx.constraintlayout.motion.widget.MotionLayout;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.R;
-import com.android.systemui.battery.BatteryMeterView;
-import com.android.systemui.battery.BatteryMeterViewController;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.privacy.OngoingPrivacyChip;
-import com.android.systemui.settings.UserTracker;
-import com.android.systemui.shade.CombinedShadeHeadersConstraintManager;
-import com.android.systemui.shade.CombinedShadeHeadersConstraintManagerImpl;
import com.android.systemui.shade.NotificationPanelView;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.shade.NotificationShadeWindowView;
@@ -59,17 +48,13 @@ import com.android.systemui.statusbar.phone.StatusBarBoundsProvider;
import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
-import com.android.systemui.statusbar.phone.StatusIconContainer;
import com.android.systemui.statusbar.phone.SystemBarAttributesListener;
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger;
import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.window.StatusBarWindowStateController;
-import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.CarrierConfigTracker;
import com.android.systemui.util.settings.SecureSettings;
@@ -90,7 +75,6 @@ import javax.inject.Provider;
})
public abstract class StatusBarViewModule {
- public static final String SHADE_HEADER = "large_screen_shade_header";
public static final String STATUS_BAR_FRAGMENT = "status_bar_fragment";
/** */
@@ -136,76 +120,6 @@ public abstract class StatusBarViewModule {
abstract ShadeViewController bindsShadeViewController(
NotificationPanelViewController notificationPanelViewController);
- @Provides
- @Named(SHADE_HEADER)
- @CentralSurfacesComponent.CentralSurfacesScope
- public static MotionLayout getLargeScreenShadeHeaderBarView(
- NotificationShadeWindowView notificationShadeWindowView,
- FeatureFlags featureFlags) {
- ViewStub stub = notificationShadeWindowView.findViewById(R.id.qs_header_stub);
- int layoutId = R.layout.combined_qs_header;
- stub.setLayoutResource(layoutId);
- MotionLayout v = (MotionLayout) stub.inflate();
- return v;
- }
-
- /** */
- @Provides
- @CentralSurfacesComponent.CentralSurfacesScope
- public static CombinedShadeHeadersConstraintManager
- provideCombinedShadeHeadersConstraintManager() {
- return CombinedShadeHeadersConstraintManagerImpl.INSTANCE;
- }
-
- /** */
- @Provides
- @CentralSurfacesComponent.CentralSurfacesScope
- public static OngoingPrivacyChip getSplitShadeOngoingPrivacyChip(
- @Named(SHADE_HEADER) MotionLayout header) {
- return header.findViewById(R.id.privacy_chip);
- }
-
- /** */
- @Provides
- @CentralSurfacesComponent.CentralSurfacesScope
- static StatusIconContainer providesStatusIconContainer(
- @Named(SHADE_HEADER) MotionLayout header) {
- return header.findViewById(R.id.statusIcons);
- }
-
- /** */
- @Provides
- @CentralSurfacesComponent.CentralSurfacesScope
- @Named(SHADE_HEADER)
- static BatteryMeterView getBatteryMeterView(@Named(SHADE_HEADER) MotionLayout view) {
- return view.findViewById(R.id.batteryRemainingIcon);
- }
-
- @Provides
- @CentralSurfacesComponent.CentralSurfacesScope
- @Named(SHADE_HEADER)
- static BatteryMeterViewController getBatteryMeterViewController(
- @Named(SHADE_HEADER) BatteryMeterView batteryMeterView,
- UserTracker userTracker,
- ConfigurationController configurationController,
- TunerService tunerService,
- @Main Handler mainHandler,
- ContentResolver contentResolver,
- FeatureFlags featureFlags,
- BatteryController batteryController
- ) {
- return new BatteryMeterViewController(
- batteryMeterView,
- userTracker,
- configurationController,
- tunerService,
- mainHandler,
- contentResolver,
- featureFlags,
- batteryController);
-
- }
-
/** */
@Provides
@CentralSurfacesComponent.CentralSurfacesScope
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
index 3d811cfc901d..673819b20e4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
@@ -240,7 +240,7 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum
|| (Build.IS_DEBUGGABLE && DEBUG_AUTH_WITH_ADB && mDebugUnlocked);
boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user);
boolean trusted = mKeyguardUpdateMonitor.getUserHasTrust(user);
- boolean faceAuthEnabled = mKeyguardUpdateMonitor.isFaceEnrolled();
+ boolean faceAuthEnabled = mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(user);
boolean changed = secure != mSecure || canDismissLockScreen != mCanDismissLockScreen
|| trustManaged != mTrustManaged || mTrusted != trusted
|| mFaceAuthEnabled != faceAuthEnabled;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 71246c994bfa..2962c14b813a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -383,7 +383,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
}
private void setupFingerprintAuth(boolean isClass3) throws RemoteException {
- when(mAuthController.isFingerprintEnrolled(anyInt())).thenReturn(true);
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
mFingerprintSensorProperties = List.of(
@@ -2693,42 +2692,33 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
}
@Test
public void testFingerprintSensorProperties() throws RemoteException {
- // GIVEN no fingerprint sensor properties
- when(mAuthController.isFingerprintEnrolled(anyInt())).thenReturn(true);
mFingerprintAuthenticatorsRegisteredCallback.onAllAuthenticatorsRegistered(
new ArrayList<>());
- // THEN fingerprint is not possible
assertThat(mKeyguardUpdateMonitor.isUnlockWithFingerprintPossible(
KeyguardUpdateMonitor.getCurrentUser())).isFalse();
- // WHEN there are fingerprint sensor properties
mFingerprintAuthenticatorsRegisteredCallback
.onAllAuthenticatorsRegistered(mFingerprintSensorProperties);
- // THEN unlock with fp is possible & fingerprint starts listening
+ verifyFingerprintAuthenticateCall();
assertThat(mKeyguardUpdateMonitor.isUnlockWithFingerprintPossible(
KeyguardUpdateMonitor.getCurrentUser())).isTrue();
- verifyFingerprintAuthenticateCall();
}
@Test
public void testFaceSensorProperties() throws RemoteException {
- // GIVEN no face sensor properties
- when(mAuthController.isFaceAuthEnrolled(anyInt())).thenReturn(true);
mFaceAuthenticatorsRegisteredCallback.onAllAuthenticatorsRegistered(new ArrayList<>());
- // THEN face is not possible
- assertThat(mKeyguardUpdateMonitor.isUnlockWithFacePossible(
+ assertThat(mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(
KeyguardUpdateMonitor.getCurrentUser())).isFalse();
- // WHEN there are face sensor properties
mFaceAuthenticatorsRegisteredCallback.onAllAuthenticatorsRegistered(mFaceSensorProperties);
+ biometricsEnabledForCurrentUser();
- // THEN face is possible but face does NOT start listening immediately
- assertThat(mKeyguardUpdateMonitor.isUnlockWithFacePossible(
- KeyguardUpdateMonitor.getCurrentUser())).isTrue();
verifyFaceAuthenticateNeverCalled();
verifyFaceDetectNeverCalled();
+ assertThat(mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(
+ KeyguardUpdateMonitor.getCurrentUser())).isTrue();
}
@Test
@@ -2801,6 +2791,9 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
}
private void mockCanBypassLockscreen(boolean canBypass) {
+ // force update the isFaceEnrolled cache:
+ mKeyguardUpdateMonitor.isFaceAuthEnabledForUser(getCurrentUser());
+
mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
when(mKeyguardBypassController.canBypass()).thenReturn(canBypass);
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt
index dea2082a2c22..6fe889270d65 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/SplitShadeTransitionAdapterTest.kt
@@ -18,6 +18,7 @@ package com.android.keyguard
import android.animation.Animator
import android.testing.AndroidTestingRunner
import android.transition.TransitionValues
+import android.view.View
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardStatusViewController.SplitShadeTransitionAdapter
import com.android.systemui.SysuiTestCase
@@ -44,14 +45,16 @@ class SplitShadeTransitionAdapterTest : SysuiTestCase() {
@Test
fun createAnimator_nullStartValues_returnsNull() {
- val animator = adapter.createAnimator(startValues = null, endValues = TransitionValues())
+ val endValues = createEndValues()
+
+ val animator = adapter.createAnimator(startValues = null, endValues = endValues)
assertThat(animator).isNull()
}
@Test
fun createAnimator_nullEndValues_returnsNull() {
- val animator = adapter.createAnimator(startValues = TransitionValues(), endValues = null)
+ val animator = adapter.createAnimator(startValues = createStartValues(), endValues = null)
assertThat(animator).isNull()
}
@@ -59,10 +62,22 @@ class SplitShadeTransitionAdapterTest : SysuiTestCase() {
@Test
fun createAnimator_nonNullStartAndEndValues_returnsAnimator() {
val animator =
- adapter.createAnimator(startValues = TransitionValues(), endValues = TransitionValues())
+ adapter.createAnimator(startValues = createStartValues(), endValues = createEndValues())
assertThat(animator).isNotNull()
}
+
+ private fun createStartValues() =
+ TransitionValues().also { values ->
+ values.view = View(context)
+ adapter.captureStartValues(values)
+ }
+
+ private fun createEndValues() =
+ TransitionValues().also { values ->
+ values.view = View(context)
+ adapter.captureEndValues(values)
+ }
}
private fun SplitShadeTransitionAdapter.createAnimator(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/OWNERS b/packages/SystemUI/tests/src/com/android/systemui/accessibility/OWNERS
new file mode 100644
index 000000000000..a2001e66e55b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/view/accessibility/OWNERS \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/SystemActionsTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/SystemActionsTest.java
new file mode 100644
index 000000000000..025c88c36203
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/SystemActionsTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2023 The Android Open 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.accessibility;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.input.InputManager;
+import android.os.RemoteException;
+import android.telecom.TelecomManager;
+import android.telephony.TelephonyManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.KeyEvent;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.settings.FakeDisplayTracker;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.shade.ShadeController;
+import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.phone.CentralSurfaces;
+
+import dagger.Lazy;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+@TestableLooper.RunWithLooper
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class SystemActionsTest extends SysuiTestCase {
+ @Mock
+ private UserTracker mUserTracker;
+ @Mock
+ private NotificationShadeWindowController mNotificationShadeController;
+ @Mock
+ private ShadeController mShadeController;
+ @Mock
+ private Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy;
+ @Mock
+ private Optional<Recents> mRecentsOptional;
+ @Mock
+ private TelecomManager mTelecomManager;
+ @Mock
+ private InputManager mInputManager;
+ private final FakeDisplayTracker mDisplayTracker = new FakeDisplayTracker(mContext);
+
+ private SystemActions mSystemActions;
+
+ @Before
+ public void setUp() throws RemoteException {
+ MockitoAnnotations.initMocks(this);
+ mContext.addMockSystemService(TelecomManager.class, mTelecomManager);
+ mContext.addMockSystemService(InputManager.class, mInputManager);
+ mSystemActions = new SystemActions(mContext, mUserTracker, mNotificationShadeController,
+ mShadeController, mCentralSurfacesOptionalLazy, mRecentsOptional, mDisplayTracker);
+ }
+
+ @Test
+ public void handleHeadsetHook_callStateIdle_injectsKeyEvents() {
+ when(mTelecomManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_IDLE);
+ // Use a custom doAnswer captor that copies the KeyEvent before storing it, because the
+ // method under test modifies the event object after injecting it which prevents
+ // reliably asserting on the event properties.
+ final List<KeyEvent> keyEvents = new ArrayList<>();
+ doAnswer(invocation -> {
+ keyEvents.add(new KeyEvent(invocation.getArgument(0)));
+ return null;
+ }).when(mInputManager).injectInputEvent(any(), anyInt());
+
+ mSystemActions.handleHeadsetHook();
+
+ assertThat(keyEvents.size()).isEqualTo(2);
+ assertThat(keyEvents.get(0).getKeyCode()).isEqualTo(KeyEvent.KEYCODE_HEADSETHOOK);
+ assertThat(keyEvents.get(0).getAction()).isEqualTo(KeyEvent.ACTION_DOWN);
+ assertThat(keyEvents.get(1).getKeyCode()).isEqualTo(KeyEvent.KEYCODE_HEADSETHOOK);
+ assertThat(keyEvents.get(1).getAction()).isEqualTo(KeyEvent.ACTION_UP);
+ }
+
+ @Test
+ public void handleHeadsetHook_callStateRinging_answersCall() {
+ when(mTelecomManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_RINGING);
+
+ mSystemActions.handleHeadsetHook();
+
+ verify(mTelecomManager).acceptRingingCall();
+ }
+
+ @Test
+ public void handleHeadsetHook_callStateOffhook_endsCall() {
+ when(mTelecomManager.getCallState()).thenReturn(TelephonyManager.CALL_STATE_OFFHOOK);
+
+ mSystemActions.handleHeadsetHook();
+
+ verify(mTelecomManager).endCall();
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
index 578e1d4d02ce..cc004363a049 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt
@@ -159,22 +159,11 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() {
@Test
fun doesNotStartIfAnimationIsCancelled() {
val runner = activityLaunchAnimator.createRunner(controller)
- runner.onAnimationCancelled(false /* isKeyguardOccluded */)
+ runner.onAnimationCancelled()
runner.onAnimationStart(0, emptyArray(), emptyArray(), emptyArray(), iCallback)
waitForIdleSync()
- verify(controller).onLaunchAnimationCancelled(false /* newKeyguardOccludedState */)
- verify(controller, never()).onLaunchAnimationStart(anyBoolean())
- }
-
- @Test
- fun passesOccludedStateToLaunchAnimationCancelled_ifTrue() {
- val runner = activityLaunchAnimator.createRunner(controller)
- runner.onAnimationCancelled(true /* isKeyguardOccluded */)
- runner.onAnimationStart(0, emptyArray(), emptyArray(), emptyArray(), iCallback)
-
- waitForIdleSync()
- verify(controller).onLaunchAnimationCancelled(true /* newKeyguardOccludedState */)
+ verify(controller).onLaunchAnimationCancelled()
verify(controller, never()).onLaunchAnimationStart(anyBoolean())
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
index ebbe096b0da3..26cbd7703075 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
@@ -41,11 +41,11 @@ import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@SmallTest
@@ -378,7 +378,13 @@ class TestableControlsBindingControllerImpl(
executor: DelayableExecutor,
lazyController: Lazy<ControlsController>,
userTracker: UserTracker
-) : ControlsBindingControllerImpl(context, executor, lazyController, userTracker) {
+) : ControlsBindingControllerImpl(
+ context,
+ executor,
+ lazyController,
+ mock(PackageUpdateMonitor.Factory::class.java),
+ userTracker
+) {
companion object {
val providers = mutableListOf<ControlsProviderLifecycleManager>()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
index da548f7ccef2..b5d34768dc9f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
@@ -30,6 +30,10 @@ import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
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.eq
+import com.android.systemui.util.mockito.mock
import com.android.systemui.util.time.FakeSystemClock
import org.junit.After
import org.junit.Assert.assertEquals
@@ -39,17 +43,17 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers
-import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyString
-import org.mockito.ArgumentMatchers.eq
import org.mockito.Captor
import org.mockito.Mock
-import org.mockito.Mockito.`when`
import org.mockito.Mockito.anyInt
-import org.mockito.Mockito.mock
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.inOrder
import org.mockito.Mockito.never
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
@SmallTest
@@ -62,16 +66,21 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
private lateinit var subscriberService: IControlsSubscriber.Stub
@Mock
private lateinit var service: IControlsProvider.Stub
-
+ @Mock
+ private lateinit var packageUpdateMonitor: PackageUpdateMonitor
@Captor
private lateinit var wrapperCaptor: ArgumentCaptor<ControlActionWrapper>
+ private lateinit var packageUpdateMonitorFactory: FakePackageUpdateMonitorFactory
+
private val componentName = ComponentName("test.pkg", "test.cls")
private lateinit var manager: ControlsProviderLifecycleManager
private lateinit var executor: FakeExecutor
+ private lateinit var fakeSystemClock: FakeSystemClock
companion object {
fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
+ private val USER = UserHandle.of(0)
}
@Before
@@ -79,16 +88,20 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
MockitoAnnotations.initMocks(this)
context.addMockService(componentName, service)
- executor = FakeExecutor(FakeSystemClock())
+ fakeSystemClock = FakeSystemClock()
+ executor = FakeExecutor(fakeSystemClock)
`when`(service.asBinder()).thenCallRealMethod()
- `when`(service.queryLocalInterface(ArgumentMatchers.anyString())).thenReturn(service)
+ `when`(service.queryLocalInterface(anyString())).thenReturn(service)
+
+ packageUpdateMonitorFactory = FakePackageUpdateMonitorFactory(packageUpdateMonitor)
manager = ControlsProviderLifecycleManager(
context,
executor,
actionCallbackService,
- UserHandle.of(0),
- componentName
+ USER,
+ componentName,
+ packageUpdateMonitorFactory,
)
}
@@ -122,7 +135,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
@Test
fun testNullBinding() {
- val mockContext = mock(Context::class.java)
+ val mockContext = mock<Context>()
lateinit var serviceConnection: ServiceConnection
`when`(mockContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer {
val component = (it.arguments[0] as Intent).component
@@ -139,8 +152,9 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
mockContext,
executor,
actionCallbackService,
- UserHandle.of(0),
- componentName
+ USER,
+ componentName,
+ packageUpdateMonitorFactory,
)
nullManager.bindService()
@@ -229,14 +243,15 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
@Test
fun testFalseBindCallsUnbind() {
- val falseContext = mock(Context::class.java)
+ val falseContext = mock<Context>()
`when`(falseContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(false)
val manager = ControlsProviderLifecycleManager(
falseContext,
executor,
actionCallbackService,
- UserHandle.of(0),
- componentName
+ USER,
+ componentName,
+ packageUpdateMonitorFactory,
)
manager.bindService()
executor.runAllReady()
@@ -247,4 +262,150 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() {
verify(falseContext).bindServiceAsUser(any(), captor.capture(), anyInt(), any())
verify(falseContext).unbindService(captor.value)
}
+
+ @Test
+ fun testPackageUpdateMonitor_createdWithCorrectValues() {
+ assertEquals(USER, packageUpdateMonitorFactory.lastUser)
+ assertEquals(componentName.packageName, packageUpdateMonitorFactory.lastPackage)
+ }
+
+ @Test
+ fun testBound_packageMonitorStartsMonitoring() {
+ manager.bindService()
+ executor.runAllReady()
+
+ // Service will connect and monitoring should start
+ verify(packageUpdateMonitor).startMonitoring()
+ }
+
+ @Test
+ fun testOnPackageUpdateWhileBound_unbound_thenBindAgain() {
+ val mockContext = mock<Context> {
+ `when`(bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true)
+ }
+
+ val manager = ControlsProviderLifecycleManager(
+ mockContext,
+ executor,
+ actionCallbackService,
+ USER,
+ componentName,
+ packageUpdateMonitorFactory,
+ )
+
+ manager.bindService()
+ executor.runAllReady()
+ clearInvocations(mockContext)
+
+ packageUpdateMonitorFactory.lastCallback?.run()
+ executor.runAllReady()
+
+ val inOrder = inOrder(mockContext)
+ inOrder.verify(mockContext).unbindService(any())
+ inOrder.verify(mockContext).bindServiceAsUser(any(), any(), anyInt(), any())
+ }
+
+ @Test
+ fun testOnPackageUpdateWhenNotBound_nothingHappens() {
+ val mockContext = mock<Context> {
+ `when`(bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true)
+ }
+
+ ControlsProviderLifecycleManager(
+ mockContext,
+ executor,
+ actionCallbackService,
+ USER,
+ componentName,
+ packageUpdateMonitorFactory,
+ )
+
+ packageUpdateMonitorFactory.lastCallback?.run()
+ verifyNoMoreInteractions(mockContext)
+ }
+
+ @Test
+ fun testUnbindService_stopsTracking() {
+ manager.bindService()
+ manager.unbindService()
+ executor.runAllReady()
+
+ verify(packageUpdateMonitor).stopMonitoring()
+ }
+
+ @Test
+ fun testRebindForPanelWithSameFlags() {
+ val mockContext = mock<Context> {
+ `when`(bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true)
+ }
+
+ val manager = ControlsProviderLifecycleManager(
+ mockContext,
+ executor,
+ actionCallbackService,
+ USER,
+ componentName,
+ packageUpdateMonitorFactory,
+ )
+
+ manager.bindServiceForPanel()
+ executor.runAllReady()
+
+ val flagsCaptor = argumentCaptor<Int>()
+ verify(mockContext).bindServiceAsUser(any(), any(), capture(flagsCaptor), any())
+ clearInvocations(mockContext)
+
+ packageUpdateMonitorFactory.lastCallback?.run()
+ executor.runAllReady()
+
+ verify(mockContext).bindServiceAsUser(any(), any(), eq(flagsCaptor.value), any())
+ }
+
+ @Test
+ fun testBindAfterSecurityExceptionWorks() {
+ val mockContext = mock<Context> {
+ `when`(bindServiceAsUser(any(), any(), anyInt(), any()))
+ .thenThrow(SecurityException("exception"))
+ }
+
+ val manager = ControlsProviderLifecycleManager(
+ mockContext,
+ executor,
+ actionCallbackService,
+ USER,
+ componentName,
+ packageUpdateMonitorFactory,
+ )
+
+ manager.bindServiceForPanel()
+ executor.runAllReady()
+
+ `when`(mockContext.bindServiceAsUser(any(), any(), anyInt(), any())).thenReturn(true)
+
+ manager.bindServiceForPanel()
+ executor.runAllReady()
+
+ verify(mockContext, times(2)).bindServiceAsUser(any(), any(), anyInt(), any())
+ }
+
+ private class FakePackageUpdateMonitorFactory(
+ private val monitor: PackageUpdateMonitor
+ ) : PackageUpdateMonitor.Factory {
+
+ var lastUser: UserHandle? = null
+ var lastPackage: String? = null
+ var lastCallback: Runnable? = null
+
+ override fun create(
+ user: UserHandle,
+ packageName: String,
+ callback: Runnable
+ ): PackageUpdateMonitor {
+ lastUser = user
+ lastPackage = packageName
+ lastCallback = callback
+ return monitor
+ }
+ }
}
+
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/PackageUpdateMonitorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/PackageUpdateMonitorTest.kt
new file mode 100644
index 000000000000..69547105d419
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/PackageUpdateMonitorTest.kt
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2023 The Android Open 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.controls.controller
+
+import android.content.Context
+import android.os.Handler
+import android.os.UserHandle
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class PackageUpdateMonitorTest : SysuiTestCase() {
+
+ @Mock private lateinit var context: Context
+ @Mock private lateinit var bgHandler: Handler
+
+ private lateinit var underTest: PackageUpdateMonitor
+
+ @Before
+ fun setup() {
+ MockitoAnnotations.initMocks(this)
+ }
+
+ @Test
+ fun startMonitoring_registerOnlyOnce() {
+ underTest = PackageUpdateMonitor(USER, PACKAGE, {}, bgHandler, context)
+
+ underTest.startMonitoring()
+ // There are two receivers registered
+ verify(context, times(2))
+ .registerReceiverAsUser(any(), eq(USER), any(), eq(null), eq(bgHandler))
+
+ underTest.startMonitoring()
+ verifyNoMoreInteractions(context)
+ }
+
+ @Test
+ fun stopMonitoring_unregistersOnlyOnce() {
+ underTest = PackageUpdateMonitor(USER, PACKAGE, {}, bgHandler, context)
+
+ underTest.startMonitoring()
+ clearInvocations(context)
+
+ underTest.stopMonitoring()
+ verify(context).unregisterReceiver(any())
+
+ underTest.stopMonitoring()
+ verifyNoMoreInteractions(context)
+ }
+
+ @Test
+ fun onPackageUpdated_correctPackageAndUser_callbackRuns() {
+ val callback = mock<Runnable>()
+
+ underTest = PackageUpdateMonitor(USER, PACKAGE, callback, bgHandler, context)
+
+ underTest.onPackageUpdateFinished(PACKAGE, UserHandle.getUid(USER.identifier, 10000))
+ verify(callback).run()
+ }
+
+ @Test
+ fun onPackageUpdated_correctPackage_wrongUser_callbackDoesntRun() {
+ val callback = mock<Runnable>()
+
+ underTest = PackageUpdateMonitor(USER, PACKAGE, callback, bgHandler, context)
+
+ underTest.onPackageUpdateFinished(PACKAGE, UserHandle.getUid(USER.identifier + 1, 10000))
+ verify(callback, never()).run()
+ }
+
+ @Test
+ fun onPackageUpdated_wrongPackage_correctUser_callbackDoesntRun() {
+ val callback = mock<Runnable>()
+
+ underTest = PackageUpdateMonitor(USER, PACKAGE, callback, bgHandler, context)
+
+ underTest.onPackageUpdateFinished("bad", UserHandle.getUid(USER.identifier + 1, 10000))
+ verify(callback, never()).run()
+ }
+
+ companion object {
+ private val USER = UserHandle.of(0)
+ private val PACKAGE = "pkg"
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
index b7c62463899f..039682c88498 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayAnimationsControllerTest.kt
@@ -24,6 +24,7 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Mock
import org.mockito.Mockito.anyLong
+import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.eq
import org.mockito.Mockito.never
import org.mockito.Mockito.times
@@ -49,6 +50,7 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
@Mock private lateinit var stateController: DreamOverlayStateController
@Mock private lateinit var configController: ConfigurationController
@Mock private lateinit var transitionViewModel: DreamingToLockscreenTransitionViewModel
+ @Mock private lateinit var logger: DreamLogger
private lateinit var controller: DreamOverlayAnimationsController
@Before
@@ -67,6 +69,7 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
DREAM_IN_COMPLICATIONS_ANIMATION_DURATION,
DREAM_IN_TRANSLATION_Y_DISTANCE,
DREAM_IN_TRANSLATION_Y_DURATION,
+ logger
)
val mockView: View = mock()
@@ -82,9 +85,9 @@ class DreamOverlayAnimationsControllerTest : SysuiTestCase() {
verify(stateController).setExitAnimationsRunning(true)
val captor = argumentCaptor<Animator.AnimatorListener>()
- verify(mockAnimator).addListener(captor.capture())
+ verify(mockAnimator, atLeastOnce()).addListener(captor.capture())
- captor.value.onAnimationEnd(mockAnimator)
+ captor.allValues.forEach { it.onAnimationEnd(mockAnimator) }
verify(stateController).setExitAnimationsRunning(false)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
index 6f9dedf9dda8..fae637541028 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
@@ -18,9 +18,12 @@
package com.android.systemui.keyboard.data.repository
import android.hardware.input.InputManager
+import android.hardware.input.InputManager.KeyboardBacklightListener
+import android.hardware.input.KeyboardBacklightState
import android.view.InputDevice
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.FlowValue
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
@@ -29,9 +32,11 @@ import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -50,6 +55,7 @@ class KeyboardRepositoryTest : SysuiTestCase() {
@Captor
private lateinit var deviceListenerCaptor: ArgumentCaptor<InputManager.InputDeviceListener>
+ @Captor private lateinit var backlightListenerCaptor: ArgumentCaptor<KeyboardBacklightListener>
@Mock private lateinit var inputManager: InputManager
private lateinit var underTest: KeyboardRepository
@@ -174,7 +180,71 @@ class KeyboardRepositoryTest : SysuiTestCase() {
@Test
fun passesKeyboardBacklightValues_fromBacklightListener() {
- // TODO(b/268645734): implement when implementing backlight listener
+ testScope.runTest {
+ // we want to capture backlight listener but this can only be done after Flow is
+ // subscribed to and listener is actually registered in inputManager
+ val backlight by collectLastValueImmediately(underTest.backlight)
+
+ verify(inputManager)
+ .registerKeyboardBacklightListener(any(), backlightListenerCaptor.capture())
+
+ backlightListenerCaptor.value.onBacklightChanged(current = 1, max = 5)
+
+ assertThat(backlight?.level).isEqualTo(1)
+ assertThat(backlight?.maxLevel).isEqualTo(5)
+ }
+ }
+
+ private fun <T> TestScope.collectLastValueImmediately(flow: Flow<T>): FlowValue<T?> {
+ val lastValue = collectLastValue(flow)
+ // runCurrent() makes us wait for collect that happens in collectLastValue and ensures
+ // Flow is initialized
+ runCurrent()
+ return lastValue
+ }
+
+ @Test
+ fun keyboardBacklightValuesNotPassed_fromBacklightListener_whenNotTriggeredByKeyPress() {
+ testScope.runTest() {
+ val backlight by collectLastValueImmediately(underTest.backlight)
+ verify(inputManager)
+ .registerKeyboardBacklightListener(any(), backlightListenerCaptor.capture())
+
+ backlightListenerCaptor.value.onBacklightChanged(
+ current = 1,
+ max = 5,
+ triggeredByKeyPress = false
+ )
+ assertThat(backlight).isNull()
+ }
+ }
+
+ @Test
+ fun passesKeyboardBacklightValues_fromBacklightListener_whenTriggeredByKeyPress() {
+ testScope.runTest() {
+ val backlight by collectLastValueImmediately(underTest.backlight)
+ verify(inputManager)
+ .registerKeyboardBacklightListener(any(), backlightListenerCaptor.capture())
+
+ backlightListenerCaptor.value.onBacklightChanged(
+ current = 1,
+ max = 5,
+ triggeredByKeyPress = true
+ )
+ assertThat(backlight).isNotNull()
+ }
+ }
+
+ private fun KeyboardBacklightListener.onBacklightChanged(
+ current: Int,
+ max: Int,
+ triggeredByKeyPress: Boolean = true
+ ) {
+ onKeyboardBacklightChanged(
+ /* deviceId= */ 0,
+ TestBacklightState(current, max),
+ triggeredByKeyPress
+ )
}
private companion object {
@@ -199,4 +269,12 @@ class KeyboardRepositoryTest : SysuiTestCase() {
whenever(it.isFullKeyboard).thenReturn(fullKeyboard)
}
}
+
+ private class TestBacklightState(
+ private val brightnessLevel: Int,
+ private val maxBrightnessLevel: Int
+ ) : KeyboardBacklightState() {
+ override fun getBrightnessLevel() = brightnessLevel
+ override fun getMaxBrightnessLevel() = maxBrightnessLevel
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt
index b46d996ddfcd..f8cb40885d21 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt
@@ -19,7 +19,6 @@ package com.android.systemui.keyguard.data.quickaffordance
import androidx.test.filters.SmallTest
import com.android.systemui.R
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.controller.ControlsController
@@ -46,7 +45,6 @@ import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@SmallTest
-@RoboPilotTest
@RunWith(Parameterized::class)
class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index b50cf73b9ec7..1d0b58a8e0f4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -67,6 +67,7 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.util.mockito.KotlinArgumentCaptor
import com.android.systemui.util.mockito.captureMany
+import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.util.time.SystemClock
@@ -193,8 +194,24 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
bypassControllerOverride: KeyguardBypassController? = bypassController
): DeviceEntryFaceAuthRepositoryImpl {
val systemClock = FakeSystemClock()
- val faceAuthBuffer = TableLogBuffer(10, "face auth", systemClock)
- val faceDetectBuffer = TableLogBuffer(10, "face detect", systemClock)
+ val faceAuthBuffer =
+ TableLogBuffer(
+ 10,
+ "face auth",
+ systemClock,
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope
+ )
+ val faceDetectBuffer =
+ TableLogBuffer(
+ 10,
+ "face detect",
+ systemClock,
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope
+ )
keyguardTransitionRepository = FakeKeyguardTransitionRepository()
val keyguardTransitionInteractor =
KeyguardTransitionInteractor(keyguardTransitionRepository)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
index f4d28431a2e9..d0bfaa9bedc9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepositoryTest.kt
@@ -23,7 +23,6 @@ import android.util.Log.TerribleFailureHandler
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.FlakyTest
import androidx.test.filters.SmallTest
-import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.animation.Interpolators
import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -48,7 +47,6 @@ import org.junit.Test
import org.junit.runner.RunWith
@SmallTest
-@RoboPilotTest
@RunWith(AndroidJUnit4::class)
@FlakyTest(bugId = 270760395)
class KeyguardTransitionRepositoryTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/FakeLogProxy.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/FakeLogProxy.kt
new file mode 100644
index 000000000000..471c4615ef0a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/FakeLogProxy.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 The Android Open 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.log.table
+
+/**
+ * Fake [LogProxy] that collects all lines sent to it. Mimics the ADB logcat format without the
+ * timestamp. [FakeLogProxy.d] will write a log like so:
+ * ```
+ * logger.d("TAG", "message here")
+ * // writes this to the [logs] field
+ * "D TAG: message here"
+ * ```
+ *
+ * Logs sent to this class are collected as a list of strings for simple test assertions.
+ */
+class FakeLogProxy : LogProxy {
+ val logs: MutableList<String> = mutableListOf()
+
+ override fun v(tag: String, message: String) {
+ logs.add("V $tag: $message")
+ }
+
+ override fun d(tag: String, message: String) {
+ logs.add("D $tag: $message")
+ }
+
+ override fun i(tag: String, message: String) {
+ logs.add("I $tag: $message")
+ }
+
+ override fun w(tag: String, message: String) {
+ logs.add("W $tag: $message")
+ }
+
+ override fun e(tag: String, message: String) {
+ logs.add("E $tag: $message")
+ }
+
+ override fun wtf(tag: String, message: String) {
+ logs.add("WTF $tag: $message")
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt
index c49337a53970..1d182cfec49c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/LogDiffsForTableTest.kt
@@ -19,6 +19,7 @@ package com.android.systemui.log.table
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.log.table.TableChange.Companion.IS_INITIAL_PREFIX
+import com.android.systemui.util.mockito.mock
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
@@ -39,7 +40,8 @@ import org.junit.Test
@OptIn(ExperimentalCoroutinesApi::class)
class LogDiffsForTableTest : SysuiTestCase() {
- private val testScope = TestScope(UnconfinedTestDispatcher())
+ private val testDispatcher = UnconfinedTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
private lateinit var systemClock: FakeSystemClock
private lateinit var tableLogBuffer: TableLogBuffer
@@ -47,7 +49,15 @@ class LogDiffsForTableTest : SysuiTestCase() {
@Before
fun setUp() {
systemClock = FakeSystemClock()
- tableLogBuffer = TableLogBuffer(MAX_SIZE, BUFFER_NAME, systemClock)
+ tableLogBuffer =
+ TableLogBuffer(
+ MAX_SIZE,
+ BUFFER_NAME,
+ systemClock,
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope,
+ )
}
// ---- Flow<Boolean> tests ----
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
index af83a560d7d0..8ba76437c725 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferFactoryTest.kt
@@ -22,13 +22,20 @@ import com.android.systemui.dump.DumpManager
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
import org.junit.Test
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
class TableLogBufferFactoryTest : SysuiTestCase() {
private val dumpManager: DumpManager = mock()
private val systemClock = FakeSystemClock()
- private val underTest = TableLogBufferFactory(dumpManager, systemClock)
+ private val testDispatcher = UnconfinedTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
+ private val underTest =
+ TableLogBufferFactory(dumpManager, systemClock, mock(), testDispatcher, testScope)
@Test
fun create_alwaysCreatesNewInstance() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
index aed830ae0d53..a2b2322899b7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt
@@ -19,31 +19,66 @@ package com.android.systemui.log.table
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.log.table.TableChange.Companion.IS_INITIAL_PREFIX
+import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
import java.io.StringWriter
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
import org.junit.Before
import org.junit.Test
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
class TableLogBufferTest : SysuiTestCase() {
private lateinit var underTest: TableLogBuffer
private lateinit var systemClock: FakeSystemClock
private lateinit var outputWriter: StringWriter
+ private lateinit var logcatEchoTracker: LogcatEchoTracker
+ private lateinit var localLogcat: FakeLogProxy
+
+ private val testDispatcher = UnconfinedTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
@Before
fun setup() {
+ localLogcat = FakeLogProxy()
+ logcatEchoTracker = mock()
systemClock = FakeSystemClock()
outputWriter = StringWriter()
- underTest = TableLogBuffer(MAX_SIZE, NAME, systemClock)
+ underTest =
+ TableLogBuffer(
+ MAX_SIZE,
+ NAME,
+ systemClock,
+ logcatEchoTracker,
+ testDispatcher,
+ testScope.backgroundScope,
+ localLogcat = localLogcat,
+ )
+ underTest.init()
}
@Test(expected = IllegalArgumentException::class)
fun maxSizeZero_throwsException() {
- TableLogBuffer(maxSize = 0, "name", systemClock)
+ TableLogBuffer(
+ maxSize = 0,
+ "name",
+ systemClock,
+ logcatEchoTracker,
+ testDispatcher,
+ testScope.backgroundScope,
+ localLogcat = localLogcat,
+ )
}
@Test
@@ -791,6 +826,112 @@ class TableLogBufferTest : SysuiTestCase() {
assertThat(dumpedString).contains(evictedColumnLog3)
}
+ @Test
+ fun logcat_bufferNotLoggable_tagNotLoggable_noEcho() {
+ whenever(logcatEchoTracker.isBufferLoggable(eq(NAME), any())).thenReturn(false)
+ whenever(logcatEchoTracker.isTagLoggable(eq("columnName"), any())).thenReturn(false)
+
+ underTest.logChange("prefix", "columnName", true)
+
+ assertThat(localLogcat.logs).isEmpty()
+ }
+
+ @Test
+ fun logcat_bufferIsLoggable_tagNotLoggable_echoes() {
+ whenever(logcatEchoTracker.isBufferLoggable(eq(NAME), any())).thenReturn(true)
+ whenever(logcatEchoTracker.isTagLoggable(eq("columnName"), any())).thenReturn(false)
+
+ underTest.logChange("prefix", "columnName", true)
+
+ assertThat(localLogcat.logs).hasSize(1)
+ }
+
+ @Test
+ fun logcat_bufferNotLoggable_tagIsLoggable_echoes() {
+ whenever(logcatEchoTracker.isBufferLoggable(eq(NAME), any())).thenReturn(false)
+ whenever(logcatEchoTracker.isTagLoggable(eq("columnName"), any())).thenReturn(true)
+
+ underTest.logChange("prefix", "columnName", true)
+
+ assertThat(localLogcat.logs).hasSize(1)
+ }
+
+ @Test
+ fun logcat_echoesDebugLogs_debugDisabled_noEcho() {
+ // Allow any log other than debug
+ whenever(logcatEchoTracker.isBufferLoggable(eq(NAME), any())).thenAnswer { invocation ->
+ (invocation.getArgument(1) as LogLevel) != LogLevel.DEBUG
+ }
+
+ underTest.logChange("prefix", "columnName", true)
+
+ assertThat(localLogcat.logs).isEmpty()
+ }
+
+ @Test
+ fun logcat_echoesDebugLogs_debugEnabled_echoes() {
+ // Only allow debug logs
+ whenever(logcatEchoTracker.isBufferLoggable(eq(NAME), eq(LogLevel.DEBUG))).thenReturn(true)
+
+ underTest.logChange("prefix", "columnName", true)
+
+ assertThat(localLogcat.logs).hasSize(1)
+ }
+
+ @Test
+ fun logcat_bufferNotLoggable_tagIsLoggable_usesColNameForTagCheck() {
+ systemClock.setCurrentTimeMillis(1000L)
+
+ val nonLoggingTag = "nonLoggingColName"
+ val loggingTag = "loggingColName"
+
+ whenever(logcatEchoTracker.isBufferLoggable(eq(NAME), any())).thenReturn(false)
+ whenever(logcatEchoTracker.isTagLoggable(eq(loggingTag), eq(LogLevel.DEBUG)))
+ .thenReturn(true)
+ whenever(logcatEchoTracker.isTagLoggable(eq(nonLoggingTag), eq(LogLevel.DEBUG)))
+ .thenReturn(false)
+
+ underTest.logChange("", nonLoggingTag, true)
+ underTest.logChange("", loggingTag, true)
+
+ assertThat(localLogcat.logs).hasSize(1)
+
+ val timestamp = TABLE_LOG_DATE_FORMAT.format(1000L)
+ val expectedMessage = "${timestamp}${SEPARATOR}${loggingTag}${SEPARATOR}true"
+ val expectedLine = "D $NAME: $expectedMessage"
+
+ assertThat(localLogcat.logs[0]).isEqualTo(expectedLine)
+ }
+
+ @Test
+ fun logcat_bufferLoggable_multipleMessagesAreEchoed() {
+ systemClock.setCurrentTimeMillis(1000L)
+ whenever(logcatEchoTracker.isBufferLoggable(eq(NAME), any())).thenReturn(true)
+
+ val col1 = "column1"
+ val col2 = "column2"
+
+ // Log a couple of columns that flip bits
+ underTest.logChange("", col1, true)
+ underTest.logChange("", col2, false)
+ underTest.logChange("", col1, false)
+ underTest.logChange("", col2, true)
+
+ assertThat(localLogcat.logs).hasSize(4)
+
+ val timestamp = TABLE_LOG_DATE_FORMAT.format(1000L)
+ val msg1 = "${timestamp}${SEPARATOR}${col1}${SEPARATOR}true"
+ val msg2 = "${timestamp}${SEPARATOR}${col2}${SEPARATOR}false"
+ val msg3 = "${timestamp}${SEPARATOR}${col1}${SEPARATOR}false"
+ val msg4 = "${timestamp}${SEPARATOR}${col2}${SEPARATOR}true"
+ val expected = listOf(msg1, msg2, msg3, msg4).map { "D $NAME: $it" }
+
+ // Logs use the same bg dispatcher for writing to logcat, they should be in order
+ for ((msg, logLine) in expected zip localLogcat.logs) {
+ assertThat(logLine).isEqualTo(msg)
+ }
+ }
+
private fun dumpChanges(): String {
underTest.dump(PrintWriter(outputWriter), arrayOf())
return outputWriter.toString()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDeviceManagerTest.kt
index a45e9d9fcacf..0c57e7b82586 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDeviceManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDeviceManagerTest.kt
@@ -468,7 +468,7 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
}
@Test
- fun audioInfoChanged() {
+ fun audioInfoPlaybackTypeChanged() {
whenever(playbackInfo.getPlaybackType()).thenReturn(PlaybackInfo.PLAYBACK_TYPE_LOCAL)
whenever(controller.getPlaybackInfo()).thenReturn(playbackInfo)
// GIVEN a controller with local playback type
@@ -486,6 +486,25 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
}
@Test
+ fun audioInfoVolumeControlIdChanged() {
+ whenever(playbackInfo.getPlaybackType()).thenReturn(PlaybackInfo.PLAYBACK_TYPE_LOCAL)
+ whenever(playbackInfo.getVolumeControlId()).thenReturn(null)
+ whenever(controller.getPlaybackInfo()).thenReturn(playbackInfo)
+ // GIVEN a controller with local playback type
+ manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+ reset(mr2)
+ // WHEN onAudioInfoChanged fires with a volume control id change
+ whenever(playbackInfo.getVolumeControlId()).thenReturn("placeholder id")
+ val captor = ArgumentCaptor.forClass(MediaController.Callback::class.java)
+ verify(controller).registerCallback(captor.capture())
+ captor.value.onAudioInfoChanged(playbackInfo)
+ // THEN the route is checked
+ verify(mr2).getRoutingSessionForMediaController(eq(controller))
+ }
+
+ @Test
fun audioInfoHasntChanged() {
whenever(playbackInfo.getPlaybackType()).thenReturn(PlaybackInfo.PLAYBACK_TYPE_REMOTE)
whenever(controller.getPlaybackInfo()).thenReturn(playbackInfo)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
index 745f094220f2..07f7c158fc4d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/MediaCarouselControllerTest.kt
@@ -19,6 +19,7 @@ package com.android.systemui.media.controls.ui
import android.app.PendingIntent
import android.content.res.ColorStateList
import android.content.res.Configuration
+import android.os.LocaleList
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.util.MathUtils.abs
@@ -56,6 +57,7 @@ import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
+import java.util.Locale
import javax.inject.Provider
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
@@ -71,6 +73,7 @@ import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.floatThat
import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
@@ -123,6 +126,7 @@ class MediaCarouselControllerTest : SysuiTestCase() {
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
+ context.resources.configuration.locales = LocaleList(Locale.US, Locale.UK)
transitionRepository = FakeKeyguardTransitionRepository()
mediaCarouselController =
MediaCarouselController(
@@ -713,6 +717,23 @@ class MediaCarouselControllerTest : SysuiTestCase() {
}
@Test
+ fun testOnLocaleListChanged_playersAreAddedBack() {
+ context.resources.configuration.locales = LocaleList(Locale.US, Locale.UK, Locale.CANADA)
+ testConfigurationChange(configListener.value::onLocaleListChanged)
+
+ verify(pageIndicator, never()).tintList =
+ ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
+
+ context.resources.configuration.locales = LocaleList(Locale.UK, Locale.US, Locale.CANADA)
+ testConfigurationChange(configListener.value::onLocaleListChanged)
+
+ verify(pageIndicator).tintList =
+ ColorStateList.valueOf(context.getColor(R.color.media_paging_indicator))
+ // When recreateMedia is set to true, page indicator is updated on removal and addition.
+ verify(pageIndicator, times(4)).setNumPages(any())
+ }
+
+ @Test
fun testRecommendation_persistentEnabled_newSmartspaceLoaded_updatesSort() {
testRecommendation_persistentEnabled_inactiveSmartspaceDataLoaded_isAdded()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
index 0bdcaf464cfd..299303d38f29 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
@@ -19,6 +19,7 @@ package com.android.systemui.media.dialog;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
@@ -33,7 +34,12 @@ import static org.mockito.Mockito.when;
import android.app.KeyguardManager;
import android.app.Notification;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.graphics.PorterDuffColorFilter;
+import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.media.AudioDeviceAttributes;
import android.media.AudioManager;
@@ -44,6 +50,7 @@ import android.media.NearbyDevice;
import android.media.RoutingSessionInfo;
import android.media.session.MediaController;
import android.media.session.MediaSessionManager;
+import android.media.session.PlaybackState;
import android.os.PowerExemptionManager;
import android.os.RemoteException;
import android.service.notification.StatusBarNotification;
@@ -74,6 +81,9 @@ import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
@@ -93,29 +103,54 @@ public class MediaOutputControllerTest extends SysuiTestCase {
private static final String TEST_SONG = "test_song";
private static final String TEST_SESSION_ID = "test_session_id";
private static final String TEST_SESSION_NAME = "test_session_name";
- private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
- private final ActivityLaunchAnimator.Controller mActivityLaunchAnimatorController = mock(
- ActivityLaunchAnimator.Controller.class);
- private final NearbyMediaDevicesManager mNearbyMediaDevicesManager = mock(
- NearbyMediaDevicesManager.class);
+ @Mock
+ private DialogLaunchAnimator mDialogLaunchAnimator;
+ @Mock
+ private ActivityLaunchAnimator.Controller mActivityLaunchAnimatorController;
+ @Mock
+ private NearbyMediaDevicesManager mNearbyMediaDevicesManager;
// Mock
- private MediaController mMediaController = mock(MediaController.class);
- private MediaSessionManager mMediaSessionManager = mock(MediaSessionManager.class);
- private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager =
- mock(CachedBluetoothDeviceManager.class);
- private LocalBluetoothManager mLocalBluetoothManager = mock(LocalBluetoothManager.class);
- private MediaOutputController.Callback mCb = mock(MediaOutputController.Callback.class);
- private MediaDevice mMediaDevice1 = mock(MediaDevice.class);
- private MediaDevice mMediaDevice2 = mock(MediaDevice.class);
- private NearbyDevice mNearbyDevice1 = mock(NearbyDevice.class);
- private NearbyDevice mNearbyDevice2 = mock(NearbyDevice.class);
- private MediaMetadata mMediaMetadata = mock(MediaMetadata.class);
- private RoutingSessionInfo mRemoteSessionInfo = mock(RoutingSessionInfo.class);
- private ActivityStarter mStarter = mock(ActivityStarter.class);
- private AudioManager mAudioManager = mock(AudioManager.class);
- private KeyguardManager mKeyguardManager = mock(KeyguardManager.class);
- private PowerExemptionManager mPowerExemptionManager = mock(PowerExemptionManager.class);
- private CommonNotifCollection mNotifCollection = mock(CommonNotifCollection.class);
+ @Mock
+ private MediaController mMediaController;
+ @Mock
+ private MediaSessionManager mMediaSessionManager;
+ @Mock
+ private CachedBluetoothDeviceManager mCachedBluetoothDeviceManager;
+ @Mock
+ private LocalBluetoothManager mLocalBluetoothManager;
+ @Mock
+ private MediaOutputController.Callback mCb;
+ @Mock
+ private MediaDevice mMediaDevice1;
+ @Mock
+ private MediaDevice mMediaDevice2;
+ @Mock
+ private NearbyDevice mNearbyDevice1;
+ @Mock
+ private NearbyDevice mNearbyDevice2;
+ @Mock
+ private MediaMetadata mMediaMetadata;
+ @Mock
+ private RoutingSessionInfo mRemoteSessionInfo;
+ @Mock
+ private ActivityStarter mStarter;
+ @Mock
+ private AudioManager mAudioManager;
+ @Mock
+ private KeyguardManager mKeyguardManager;
+ @Mock
+ private ActivityLaunchAnimator.Controller mController;
+ @Mock
+ private PowerExemptionManager mPowerExemptionManager;
+ @Mock
+ private CommonNotifCollection mNotifCollection;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private Drawable mDrawable;
+ @Mock
+ private PlaybackState mPlaybackState;
+
private FeatureFlags mFlags = mock(FeatureFlags.class);
private View mDialogLaunchView = mock(View.class);
private MediaOutputController.Callback mCallback = mock(MediaOutputController.Callback.class);
@@ -131,8 +166,11 @@ public class MediaOutputControllerTest extends SysuiTestCase {
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext.setMockPackageManager(mPackageManager);
mSpyContext = spy(mContext);
when(mMediaController.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState);
mMediaControllers.add(mMediaController);
when(mMediaSessionManager.getActiveSessions(any())).thenReturn(mMediaControllers);
doReturn(mMediaSessionManager).when(mSpyContext).getSystemService(
@@ -258,6 +296,34 @@ public class MediaOutputControllerTest extends SysuiTestCase {
}
@Test
+ public void tryToLaunchMediaApplication_intentNotNull_startActivity() {
+ when(mDialogLaunchAnimator.createActivityLaunchController(any(View.class))).thenReturn(
+ mController);
+ Intent intent = new Intent(TEST_PACKAGE_NAME);
+ doReturn(intent).when(mPackageManager).getLaunchIntentForPackage(TEST_PACKAGE_NAME);
+ mMediaOutputController.start(mCallback);
+
+ mMediaOutputController.tryToLaunchMediaApplication(mDialogLaunchView);
+
+ verify(mStarter).startActivity(any(Intent.class), anyBoolean(),
+ Mockito.eq(mController));
+ }
+
+ @Test
+ public void tryToLaunchInAppRoutingIntent_componentNameNotNull_startActivity() {
+ when(mDialogLaunchAnimator.createActivityLaunchController(any(View.class))).thenReturn(
+ mController);
+ mMediaOutputController.start(mCallback);
+ when(mLocalMediaManager.getLinkedItemComponentName()).thenReturn(
+ new ComponentName(TEST_PACKAGE_NAME, ""));
+
+ mMediaOutputController.tryToLaunchInAppRoutingIntent(TEST_DEVICE_1_ID, mDialogLaunchView);
+
+ verify(mStarter).startActivity(any(Intent.class), anyBoolean(),
+ Mockito.eq(mController));
+ }
+
+ @Test
public void onDevicesUpdated_unregistersNearbyDevicesCallback() throws RemoteException {
mMediaOutputController.start(mCb);
@@ -342,6 +408,30 @@ public class MediaOutputControllerTest extends SysuiTestCase {
}
@Test
+ public void advanced_onDeviceListUpdateWithConnectedDeviceRemote_verifyItemSize() {
+ when(mFlags.isEnabled(Flags.OUTPUT_SWITCHER_ADVANCED_LAYOUT)).thenReturn(true);
+ when(mMediaDevice1.getFeatures()).thenReturn(
+ ImmutableList.of(MediaRoute2Info.FEATURE_REMOTE_PLAYBACK));
+ when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice1);
+ mMediaOutputController.start(mCb);
+ reset(mCb);
+
+ mMediaOutputController.onDeviceListUpdate(mMediaDevices);
+ final List<MediaDevice> devices = new ArrayList<>();
+ for (MediaItem item : mMediaOutputController.getMediaItemList()) {
+ if (item.getMediaDevice().isPresent()) {
+ devices.add(item.getMediaDevice().get());
+ }
+ }
+
+ assertThat(devices.containsAll(mMediaDevices)).isTrue();
+ assertThat(devices.size()).isEqualTo(mMediaDevices.size());
+ assertThat(mMediaOutputController.getMediaItemList().size()).isEqualTo(
+ mMediaDevices.size() + 1);
+ verify(mCb).onDeviceListChanged();
+ }
+
+ @Test
public void advanced_categorizeMediaItems_withSuggestedDevice_verifyDeviceListSize() {
when(mFlags.isEnabled(Flags.OUTPUT_SWITCHER_ADVANCED_LAYOUT)).thenReturn(true);
when(mMediaDevice1.isSuggestedDevice()).thenReturn(true);
@@ -582,6 +672,17 @@ public class MediaOutputControllerTest extends SysuiTestCase {
}
@Test
+ public void isAnyDeviceTransferring_advancedLayoutSupport() {
+ when(mFlags.isEnabled(Flags.OUTPUT_SWITCHER_ADVANCED_LAYOUT)).thenReturn(true);
+ when(mMediaDevice1.getState()).thenReturn(
+ LocalMediaManager.MediaDeviceState.STATE_CONNECTING);
+ mMediaOutputController.start(mCb);
+ mMediaOutputController.onDeviceListUpdate(mMediaDevices);
+
+ assertThat(mMediaOutputController.isAnyDeviceTransferring()).isTrue();
+ }
+
+ @Test
public void isPlaying_stateIsNull() {
when(mMediaController.getPlaybackState()).thenReturn(null);
@@ -661,22 +762,6 @@ public class MediaOutputControllerTest extends SysuiTestCase {
}
@Test
- public void connectDevice_verifyConnect() {
- when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2);
-
- mMediaOutputController.connectDevice(mMediaDevice1);
-
- // Wait for background thread execution
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
-
- verify(mLocalMediaManager).connectDevice(mMediaDevice1);
- }
-
- @Test
public void getActiveRemoteMediaDevice_isSystemSession_returnSession() {
when(mRemoteSessionInfo.getId()).thenReturn(TEST_SESSION_ID);
when(mRemoteSessionInfo.getName()).thenReturn(TEST_SESSION_NAME);
@@ -883,6 +968,56 @@ public class MediaOutputControllerTest extends SysuiTestCase {
}
@Test
+ public void getDeviceIconCompat_deviceIconIsNotNull_returnsIcon() {
+ when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2);
+ when(mMediaDevice1.getIcon()).thenReturn(mDrawable);
+
+ assertThat(mMediaOutputController.getDeviceIconCompat(mMediaDevice1)).isInstanceOf(
+ IconCompat.class);
+ }
+
+ @Test
+ public void getDeviceIconCompat_deviceIconIsNull_returnsIcon() {
+ when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice2);
+ when(mMediaDevice1.getIcon()).thenReturn(null);
+
+ assertThat(mMediaOutputController.getDeviceIconCompat(mMediaDevice1)).isInstanceOf(
+ IconCompat.class);
+ }
+
+ @Test
+ public void setColorFilter_setColorFilterToDrawable() {
+ mMediaOutputController.setColorFilter(mDrawable, true);
+
+ verify(mDrawable).setColorFilter(any(PorterDuffColorFilter.class));
+ }
+
+ @Test
+ public void resetGroupMediaDevices_clearGroupDevices() {
+ final MediaDevice selectedMediaDevice1 = mock(MediaDevice.class);
+ final MediaDevice selectedMediaDevice2 = mock(MediaDevice.class);
+ final MediaDevice selectableMediaDevice1 = mock(MediaDevice.class);
+ final MediaDevice selectableMediaDevice2 = mock(MediaDevice.class);
+ final List<MediaDevice> selectedMediaDevices = new ArrayList<>();
+ final List<MediaDevice> selectableMediaDevices = new ArrayList<>();
+ when(selectedMediaDevice1.getId()).thenReturn(TEST_DEVICE_1_ID);
+ when(selectedMediaDevice2.getId()).thenReturn(TEST_DEVICE_2_ID);
+ when(selectableMediaDevice1.getId()).thenReturn(TEST_DEVICE_3_ID);
+ when(selectableMediaDevice2.getId()).thenReturn(TEST_DEVICE_4_ID);
+ selectedMediaDevices.add(selectedMediaDevice1);
+ selectedMediaDevices.add(selectedMediaDevice2);
+ selectableMediaDevices.add(selectableMediaDevice1);
+ selectableMediaDevices.add(selectableMediaDevice2);
+ doReturn(selectedMediaDevices).when(mLocalMediaManager).getSelectedMediaDevice();
+ doReturn(selectableMediaDevices).when(mLocalMediaManager).getSelectableMediaDevice();
+ assertThat(mMediaOutputController.getGroupMediaDevices().isEmpty()).isFalse();
+
+ mMediaOutputController.resetGroupMediaDevices();
+
+ assertThat(mMediaOutputController.mGroupMediaDevices.isEmpty()).isTrue();
+ }
+
+ @Test
public void isVolumeControlEnabled_isCastWithVolumeFixed_returnsFalse() {
when(mMediaDevice1.getDeviceType()).thenReturn(
MediaDevice.MediaDeviceType.TYPE_CAST_DEVICE);
@@ -919,6 +1054,42 @@ public class MediaOutputControllerTest extends SysuiTestCase {
}
@Test
+ public void setTemporaryAllowListExceptionIfNeeded_packageNameIsNull_NoAction() {
+ MediaOutputController testMediaOutputController = new MediaOutputController(mSpyContext,
+ null,
+ mMediaSessionManager, mLocalBluetoothManager, mStarter,
+ mNotifCollection, mDialogLaunchAnimator,
+ Optional.of(mNearbyMediaDevicesManager), mAudioManager, mPowerExemptionManager,
+ mKeyguardManager, mFlags);
+
+ testMediaOutputController.setTemporaryAllowListExceptionIfNeeded(mMediaDevice2);
+
+ verify(mPowerExemptionManager, never()).addToTemporaryAllowList(anyString(), anyInt(),
+ anyString(),
+ anyLong());
+ }
+
+ @Test
+ public void onMetadataChanged_triggersOnMetadataChanged() {
+ mMediaOutputController.mCallback = this.mCallback;
+
+ mMediaOutputController.mCb.onMetadataChanged(mMediaMetadata);
+
+ verify(mMediaOutputController.mCallback).onMediaChanged();
+ }
+
+ @Test
+ public void onPlaybackStateChanged_updateWithNullState_onMediaStoppedOrPaused() {
+ when(mPlaybackState.getState()).thenReturn(PlaybackState.STATE_PLAYING);
+ mMediaOutputController.mCallback = this.mCallback;
+ mMediaOutputController.start(mCb);
+
+ mMediaOutputController.mCb.onPlaybackStateChanged(null);
+
+ verify(mMediaOutputController.mCallback).onMediaStoppedOrPaused();
+ }
+
+ @Test
public void launchBluetoothPairing_isKeyguardLocked_dismissDialog() {
when(mDialogLaunchAnimator.createActivityLaunchController(mDialogLaunchView)).thenReturn(
mActivityLaunchAnimatorController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
index 55f221df1f0a..5dbcd33ab0e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -45,8 +45,8 @@ import androidx.test.runner.AndroidJUnit4
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.notetask.NoteTaskController.Companion.EXTRA_SHORTCUT_BADGE_OVERRIDE_PACKAGE
+import com.android.systemui.notetask.NoteTaskController.Companion.SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT
import com.android.systemui.notetask.NoteTaskController.Companion.SHORTCUT_ID
-import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity
import com.android.systemui.notetask.shortcut.LaunchNoteTaskManagedProfileProxyActivity
import com.android.systemui.settings.FakeUserTracker
@@ -423,8 +423,8 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
eq(COMPONENT_ENABLED_STATE_ENABLED),
eq(PackageManager.DONT_KILL_APP),
)
- assertThat(argument.value.className)
- .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
+
+ assertThat(argument.value).isEqualTo(SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT)
}
@Test
@@ -438,8 +438,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
eq(COMPONENT_ENABLED_STATE_DISABLED),
eq(PackageManager.DONT_KILL_APP),
)
- assertThat(argument.value.className)
- .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
+ assertThat(argument.value).isEqualTo(SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT)
}
@Test
@@ -458,8 +457,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
eq(COMPONENT_ENABLED_STATE_ENABLED),
eq(PackageManager.DONT_KILL_APP),
)
- assertThat(argument.value.className)
- .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
+ assertThat(argument.value).isEqualTo(SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT)
}
@Test
@@ -479,8 +477,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
eq(COMPONENT_ENABLED_STATE_DISABLED),
eq(PackageManager.DONT_KILL_APP),
)
- assertThat(argument.value.className)
- .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
+ assertThat(argument.value).isEqualTo(SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT)
}
// endregion
@@ -664,8 +661,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
eq(COMPONENT_ENABLED_STATE_ENABLED),
eq(PackageManager.DONT_KILL_APP),
)
- assertThat(actualComponent.value.className)
- .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
+ assertThat(actualComponent.value).isEqualTo(SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT)
verify(shortcutManager, never()).disableShortcuts(any())
verify(shortcutManager).enableShortcuts(listOf(SHORTCUT_ID))
val actualShortcuts = argumentCaptor<List<ShortcutInfo>>()
@@ -696,8 +692,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
eq(COMPONENT_ENABLED_STATE_DISABLED),
eq(PackageManager.DONT_KILL_APP),
)
- assertThat(argument.value.className)
- .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
+ assertThat(argument.value).isEqualTo(SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT)
verify(shortcutManager).disableShortcuts(listOf(SHORTCUT_ID))
verify(shortcutManager, never()).enableShortcuts(any())
verify(shortcutManager, never()).updateShortcuts(any())
@@ -714,8 +709,7 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
eq(COMPONENT_ENABLED_STATE_DISABLED),
eq(PackageManager.DONT_KILL_APP),
)
- assertThat(argument.value.className)
- .isEqualTo(CreateNoteTaskShortcutActivity::class.java.name)
+ assertThat(argument.value).isEqualTo(SETTINGS_CREATE_NOTE_TASK_SHORTCUT_COMPONENT)
verify(shortcutManager).disableShortcuts(listOf(SHORTCUT_ID))
verify(shortcutManager, never()).enableShortcuts(any())
verify(shortcutManager, never()).updateShortcuts(any())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
index f870631bd72b..1edc63c4417e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerBaseTest.java
@@ -115,6 +115,7 @@ import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.screenrecord.RecordingController;
+import com.android.systemui.shade.data.repository.ShadeRepository;
import com.android.systemui.shade.transition.ShadeTransitionController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -304,6 +305,7 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
mEmptySpaceClickListenerCaptor;
@Mock protected ActivityStarter mActivityStarter;
@Mock protected KeyguardFaceAuthInteractor mKeyguardFaceAuthInteractor;
+ @Mock protected ShadeRepository mShadeRepository;
protected final int mMaxUdfpsBurnInOffsetY = 5;
protected KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor;
@@ -672,7 +674,8 @@ public class NotificationPanelViewControllerBaseTest extends SysuiTestCase {
mFeatureFlags,
mInteractionJankMonitor,
mShadeLog,
- mKeyguardFaceAuthInteractor
+ mKeyguardFaceAuthInteractor,
+ mShadeRepository
);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java
index 908f7cbf4801..8a9161e6d46d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/QuickSettingsControllerTest.java
@@ -69,6 +69,7 @@ import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSFragment;
import com.android.systemui.screenrecord.RecordingController;
+import com.android.systemui.shade.data.repository.ShadeRepository;
import com.android.systemui.shade.transition.ShadeTransitionController;
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -88,6 +89,8 @@ import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
+import dagger.Lazy;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -98,8 +101,6 @@ import org.mockito.MockitoAnnotations;
import java.util.List;
-import dagger.Lazy;
-
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@@ -241,7 +242,8 @@ public class QuickSettingsControllerTest extends SysuiTestCase {
mFeatureFlags,
mInteractionJankMonitor,
mShadeLogger,
- mock(KeyguardFaceAuthInteractor.class)
+ mock(KeyguardFaceAuthInteractor.class),
+ mock(ShadeRepository.class)
);
mFragmentListener = mQsController.getQsFragmentListener();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
new file mode 100644
index 000000000000..8f2c93b3bf43
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2023 The Android Open 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.data.repository
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.RoboPilotTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.shade.ShadeExpansionChangeEvent
+import com.android.systemui.shade.ShadeExpansionStateManager
+import com.android.systemui.shade.domain.model.ShadeModel
+import com.android.systemui.util.mockito.withArgCaptor
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RoboPilotTest
+@RunWith(AndroidJUnit4::class)
+class ShadeRepositoryImplTest : SysuiTestCase() {
+
+ @Mock private lateinit var shadeExpansionStateManager: ShadeExpansionStateManager
+ private val testDispatcher = StandardTestDispatcher()
+ private val testScope = TestScope(testDispatcher)
+
+ private lateinit var underTest: ShadeRepositoryImpl
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ underTest = ShadeRepositoryImpl(shadeExpansionStateManager)
+ }
+
+ @Test
+ fun shadeExpansionChangeEvent() =
+ testScope.runTest {
+ var latest: ShadeModel? = null
+ val job = underTest.shadeModel.onEach { latest = it }.launchIn(this)
+ runCurrent()
+ assertThat(latest?.expansionAmount).isEqualTo(0f)
+ assertThat(latest?.isExpanded).isEqualTo(false)
+ assertThat(latest?.isUserDragging).isEqualTo(false)
+
+ val captor = withArgCaptor {
+ verify(shadeExpansionStateManager).addExpansionListener(capture())
+ }
+
+ captor.onPanelExpansionChanged(
+ ShadeExpansionChangeEvent(
+ fraction = 1f,
+ expanded = true,
+ tracking = false,
+ dragDownPxAmount = 0f,
+ )
+ )
+ runCurrent()
+ assertThat(latest?.expansionAmount).isEqualTo(1f)
+ assertThat(latest?.isExpanded).isEqualTo(true)
+ assertThat(latest?.isUserDragging).isEqualTo(false)
+
+ captor.onPanelExpansionChanged(
+ ShadeExpansionChangeEvent(
+ fraction = .67f,
+ expanded = false,
+ tracking = true,
+ dragDownPxAmount = 0f,
+ )
+ )
+ runCurrent()
+ assertThat(latest?.expansionAmount).isEqualTo(.67f)
+ assertThat(latest?.isExpanded).isEqualTo(false)
+ assertThat(latest?.isUserDragging).isEqualTo(true)
+
+ job.cancel()
+ }
+
+ @Test
+ fun updateQsExpansion() =
+ testScope.runTest {
+ assertThat(underTest.qsExpansion.value).isEqualTo(0f)
+
+ underTest.setQsExpansion(.5f)
+ assertThat(underTest.qsExpansion.value).isEqualTo(.5f)
+
+ underTest.setQsExpansion(.82f)
+ assertThat(underTest.qsExpansion.value).isEqualTo(.82f)
+
+ underTest.setQsExpansion(1f)
+ assertThat(underTest.qsExpansion.value).isEqualTo(1f)
+ }
+
+ @Test
+ fun updateUdfpsTransitionToFullShadeProgress() =
+ testScope.runTest {
+ assertThat(underTest.udfpsTransitionToFullShadeProgress.value).isEqualTo(0f)
+
+ underTest.setUdfpsTransitionToFullShadeProgress(.5f)
+ assertThat(underTest.udfpsTransitionToFullShadeProgress.value).isEqualTo(.5f)
+
+ underTest.setUdfpsTransitionToFullShadeProgress(.82f)
+ assertThat(underTest.udfpsTransitionToFullShadeProgress.value).isEqualTo(.82f)
+
+ underTest.setUdfpsTransitionToFullShadeProgress(1f)
+ assertThat(underTest.udfpsTransitionToFullShadeProgress.value).isEqualTo(1f)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
index 78f5bf20e6f9..eef4470c48cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt
@@ -43,6 +43,8 @@ import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit
@@ -172,7 +174,7 @@ class ClockRegistryTest : SysuiTestCase() {
}
@Test
- fun clockIdConflict_ErrorWithoutCrash() {
+ fun clockIdConflict_ErrorWithoutCrash_unloadDuplicate() {
val mockPluginLifecycle1 = mock<PluginLifecycleManager<ClockProviderPlugin>>()
val plugin1 = FakeClockPlugin()
.addClock("clock_1", "clock 1", { mockClock }, { mockThumbnail })
@@ -199,6 +201,8 @@ class ClockRegistryTest : SysuiTestCase() {
assertEquals(registry.createExampleClock("clock_2"), mockClock)
assertEquals(registry.getClockThumbnail("clock_1"), mockThumbnail)
assertEquals(registry.getClockThumbnail("clock_2"), mockThumbnail)
+ verify(mockPluginLifecycle1, never()).unloadPlugin()
+ verify(mockPluginLifecycle2, times(2)).unloadPlugin()
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index 2106da887b44..2351f7600c65 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -15,6 +15,7 @@ import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.qs.QS
import com.android.systemui.shade.ShadeViewController
+import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.NotificationTestHelper
import com.android.systemui.statusbar.notification.stack.AmbientState
@@ -127,6 +128,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
},
qsTransitionControllerFactory = { qsTransitionController },
activityStarter = activityStarter,
+ shadeRepository = FakeShadeRepository(),
)
transitionController.addCallback(transitionControllerCallback)
whenever(nsslController.view).thenReturn(stackscroller)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
deleted file mode 100644
index bd0a556ac670..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
+++ /dev/null
@@ -1,370 +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.stack;
-
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.res.Resources;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
-import android.testing.TestableLooper.RunWithLooper;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
-import com.android.systemui.statusbar.notification.logging.NotificationRoundnessLogger;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.ExpandableView;
-import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
-import com.android.systemui.util.DeviceConfigProxy;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-
-import java.util.HashSet;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper
-public class NotificationRoundnessManagerTest extends SysuiTestCase {
-
- private NotificationRoundnessManager mRoundnessManager;
- private HashSet<ExpandableView> mAnimatedChildren = new HashSet<>();
- private Runnable mRoundnessCallback = mock(Runnable.class);
- private ExpandableNotificationRow mFirst;
- private ExpandableNotificationRow mSecond;
- private NotificationRoundnessLogger mLogger = mock(NotificationRoundnessLogger.class);
- private float mSmallRadiusRatio;
-
- @Before
- public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- final Resources resources = mContext.getResources();
- mSmallRadiusRatio = resources.getDimension(R.dimen.notification_corner_radius_small)
- / resources.getDimension(R.dimen.notification_corner_radius);
- mRoundnessManager = new NotificationRoundnessManager(
- new NotificationSectionsFeatureManager(new DeviceConfigProxy(), mContext),
- mLogger,
- mock(DumpManager.class),
- mock(FeatureFlags.class));
- allowTestableLooperAsMainThread();
- NotificationTestHelper testHelper = new NotificationTestHelper(
- mContext,
- mDependency,
- TestableLooper.get(this));
- mFirst = testHelper.createRow();
- mFirst.setHeadsUpAnimatingAwayListener(animatingAway
- -> mRoundnessManager.updateView(mFirst, false));
- mSecond = testHelper.createRow();
- mSecond.setHeadsUpAnimatingAwayListener(animatingAway
- -> mRoundnessManager.updateView(mSecond, false));
- mRoundnessManager.setOnRoundingChangedCallback(mRoundnessCallback);
- mRoundnessManager.setAnimatedChildren(mAnimatedChildren);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mFirst),
- createSection(null, null)
- });
- mRoundnessManager.setExpanded(1.0f, 1.0f);
- mRoundnessManager.setShouldRoundPulsingViews(true);
- reset(mRoundnessCallback);
- }
-
- @Test
- public void testCallbackCalledWhenSecondChanged() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mSecond),
- createSection(null, null)
- });
- verify(mRoundnessCallback, atLeast(1)).run();
- }
-
- @Test
- public void testCallbackCalledWhenFirstChanged() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mFirst),
- createSection(null, null)
- });
- verify(mRoundnessCallback, atLeast(1)).run();
- }
-
- @Test
- public void testCallbackCalledWhenSecondSectionFirstChanged() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mFirst),
- createSection(mSecond, null)
- });
- verify(mRoundnessCallback, atLeast(1)).run();
- }
-
- @Test
- public void testCallbackCalledWhenSecondSectionLastChanged() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mFirst),
- createSection(null, mSecond)
- });
- verify(mRoundnessCallback, atLeast(1)).run();
- }
-
- @Test
- public void testCallbackNotCalledWhenFirstChangesSections() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(null, mFirst),
- createSection(mFirst, null)
- });
- verify(mRoundnessCallback, never()).run();
- }
-
- @Test
- public void testRoundnessSetOnLast() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(1.0f, mSecond.getBottomRoundness(), 0.0f);
- Assert.assertEquals(mSmallRadiusRatio, mSecond.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundnessPulsing() throws Exception {
- // Let's create a notification that's neither the first or last item of the stack,
- // this way we'll ensure that it won't have any rounded corners by default.
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mSecond),
- createSection(null, null)
- });
- NotificationTestHelper testHelper = new NotificationTestHelper(
- mContext,
- mDependency,
- TestableLooper.get(this));
- ExpandableNotificationRow row = testHelper.createRow();
- NotificationEntry entry = mock(NotificationEntry.class);
- when(entry.getRow()).thenReturn(row);
-
- when(testHelper.getStatusBarStateController().isDozing()).thenReturn(true);
- row.setHeadsUp(true);
- mRoundnessManager.updateView(entry.getRow(), false);
- Assert.assertEquals(1f, row.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1f, row.getTopRoundness(), 0.0f);
-
- row.setHeadsUp(false);
- mRoundnessManager.updateView(entry.getRow(), false);
- Assert.assertEquals(mSmallRadiusRatio, row.getBottomRoundness(), 0.0f);
- Assert.assertEquals(mSmallRadiusRatio, row.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundnessSetOnSecondSectionLast() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mFirst),
- createSection(null, mSecond)
- });
- Assert.assertEquals(1.0f, mSecond.getBottomRoundness(), 0.0f);
- Assert.assertEquals(mSmallRadiusRatio, mSecond.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundnessSetOnSecondSectionFirst() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mFirst),
- createSection(mSecond, null)
- });
- Assert.assertEquals(mSmallRadiusRatio, mSecond.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1.0f, mSecond.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundnessSetOnNew() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, null),
- createSection(null, null)
- });
- Assert.assertEquals(mSmallRadiusRatio, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1.0f, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testCompleteReplacement() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(mSmallRadiusRatio, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(mSmallRadiusRatio, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testNotCalledWhenRemoved() {
- mFirst.setRemoved();
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(1.0f, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1.0f, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundedWhenPinnedAndCollapsed() {
- mFirst.setPinned(true);
- mRoundnessManager.setExpanded(0.0f /* expandedHeight */, 0.0f /* appearFraction */);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(1.0f, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1.0f, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundedWhenGoingAwayAndCollapsed() {
- mFirst.setHeadsUpAnimatingAway(true);
- mRoundnessManager.setExpanded(0.0f /* expandedHeight */, 0.0f /* appearFraction */);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(1.0f, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1.0f, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundedNormalRoundingWhenExpanded() {
- mFirst.setHeadsUpAnimatingAway(true);
- mRoundnessManager.setExpanded(1.0f /* expandedHeight */, 0.0f /* appearFraction */);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(mSmallRadiusRatio, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(mSmallRadiusRatio, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testTrackingHeadsUpRoundedIfPushingUp() {
- mRoundnessManager.setExpanded(1.0f /* expandedHeight */, -0.5f /* appearFraction */);
- mRoundnessManager.setTrackingHeadsUp(mFirst);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(1.0f, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1.0f, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testTrackingHeadsUpPartiallyRoundedIfPushingDown() {
- mRoundnessManager.setExpanded(1.0f /* expandedHeight */, 0.5f /* appearFraction */);
- mRoundnessManager.setTrackingHeadsUp(mFirst);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- Assert.assertEquals(0.5f, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(0.5f, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testRoundingUpdatedWhenAnimatingAwayTrue() {
- mRoundnessManager.setExpanded(0.0f, 0.0f);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- mFirst.setHeadsUpAnimatingAway(true);
- Assert.assertEquals(1.0f, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(1.0f, mFirst.getTopRoundness(), 0.0f);
- }
-
-
- @Test
- public void testRoundingUpdatedWhenAnimatingAwayFalse() {
- mRoundnessManager.setExpanded(0.0f, 0.0f);
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mSecond, mSecond),
- createSection(null, null)
- });
- mFirst.setHeadsUpAnimatingAway(true);
- mFirst.setHeadsUpAnimatingAway(false);
- Assert.assertEquals(mSmallRadiusRatio, mFirst.getBottomRoundness(), 0.0f);
- Assert.assertEquals(mSmallRadiusRatio, mFirst.getTopRoundness(), 0.0f);
- }
-
- @Test
- public void testNoViewsFirstOrLastInSectionWhenSecondSectionEmpty() {
- Assert.assertTrue(mFirst.isFirstInSection());
- Assert.assertTrue(mFirst.isLastInSection());
- }
-
- @Test
- public void testNoViewsFirstOrLastInSectionWhenFirstSectionEmpty() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(null, null),
- createSection(mSecond, mSecond)
- });
- Assert.assertTrue(mSecond.isFirstInSection());
- Assert.assertTrue(mSecond.isLastInSection());
- }
-
- @Test
- public void testFirstAndLastViewsInSectionSetWhenBothSectionsNonEmpty() {
- mRoundnessManager.updateRoundedChildren(new NotificationSection[]{
- createSection(mFirst, mFirst),
- createSection(mSecond, mSecond)
- });
- Assert.assertTrue(mFirst.isFirstInSection());
- Assert.assertTrue(mFirst.isLastInSection());
- Assert.assertTrue(mSecond.isFirstInSection());
- Assert.assertTrue(mSecond.isLastInSection());
- }
-
- @Test
- public void testLoggingOnRoundingUpdate() {
- NotificationSection[] sections = new NotificationSection[]{
- createSection(mFirst, mSecond),
- createSection(null, null)
- };
- mRoundnessManager.updateRoundedChildren(sections);
- verify(mLogger).onSectionCornersUpdated(sections, /*anyChanged=*/ true);
- verify(mLogger, atLeast(1)).onCornersUpdated(eq(mFirst), anyBoolean(),
- anyBoolean(), anyBoolean(), anyBoolean());
- verify(mLogger, atLeast(1)).onCornersUpdated(eq(mSecond), anyBoolean(),
- anyBoolean(), anyBoolean(), anyBoolean());
- }
-
- private NotificationSection createSection(ExpandableNotificationRow first,
- ExpandableNotificationRow last) {
- NotificationSection section = mock(NotificationSection.class);
- when(section.getFirstVisibleChild()).thenReturn(first);
- when(section.getLastVisibleChild()).thenReturn(last);
- return section;
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
index 30da08ebfe7d..f38881c5b521 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
@@ -96,8 +96,7 @@ public class NotificationSectionsManagerTest extends SysuiTestCase {
mIncomingHeaderController,
mPeopleHeaderController,
mAlertingHeaderController,
- mSilentHeaderController,
- mFeatureFlag
+ mSilentHeaderController
);
// Required in order for the header inflation to work properly
when(mNssl.generateLayoutParams(any(AttributeSet.class)))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt
index 81a3f1245efe..45725ced521c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationTargetsHelperTest.kt
@@ -6,7 +6,6 @@ import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.statusbar.notification.row.NotificationTestHelper
import com.android.systemui.util.mockito.mock
import junit.framework.Assert.assertEquals
@@ -30,14 +29,7 @@ class NotificationTargetsHelperTest : SysuiTestCase() {
NotificationTestHelper(mContext, mDependency, TestableLooper.get(this))
}
- private fun notificationTargetsHelper(
- notificationGroupCorner: Boolean = true,
- ) =
- NotificationTargetsHelper(
- FakeFeatureFlags().apply {
- set(Flags.USE_ROUNDNESS_SOURCETYPES, notificationGroupCorner)
- }
- )
+ private fun notificationTargetsHelper() = NotificationTargetsHelper(FakeFeatureFlags())
@Test
fun targetsForFirstNotificationInGroup() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index 205cebdefa49..2f1e372eb33d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -34,8 +34,6 @@ import android.widget.TextView;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.ShadeHeadsUpTracker;
@@ -82,7 +80,6 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
private KeyguardStateController mKeyguardStateController;
private CommandQueue mCommandQueue;
private NotificationRoundnessManager mNotificationRoundnessManager;
- private FeatureFlags mFeatureFlag;
@Before
public void setUp() throws Exception {
@@ -103,9 +100,7 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
mKeyguardStateController = mock(KeyguardStateController.class);
mCommandQueue = mock(CommandQueue.class);
mNotificationRoundnessManager = mock(NotificationRoundnessManager.class);
- mFeatureFlag = mock(FeatureFlags.class);
when(mShadeViewController.getShadeHeadsUpTracker()).thenReturn(mShadeHeadsUpTracker);
- when(mFeatureFlag.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES)).thenReturn(true);
mHeadsUpAppearanceController = new HeadsUpAppearanceController(
mock(NotificationIconAreaController.class),
mHeadsUpManager,
@@ -118,7 +113,6 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
mStackScrollerController,
mShadeViewController,
mNotificationRoundnessManager,
- mFeatureFlag,
mHeadsUpStatusBarView,
new Clock(mContext, null),
Optional.of(mOperatorNameView));
@@ -202,7 +196,6 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
mStackScrollerController,
mShadeViewController,
mNotificationRoundnessManager,
- mFeatureFlag,
mHeadsUpStatusBarView,
new Clock(mContext, null),
Optional.empty());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 6be0e2deaf35..e56f0d6b3b0f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -84,6 +84,7 @@ import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.unfold.SysUIUnfoldComponent;
import com.google.common.truth.Truth;
@@ -151,13 +152,15 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
private WindowOnBackInvokedDispatcher mOnBackInvokedDispatcher;
@Captor
private ArgumentCaptor<OnBackInvokedCallback> mBackCallbackCaptor;
+ @Captor
+ private ArgumentCaptor<KeyguardStateController.Callback> mKeyguardStateControllerCallback;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mContainer.findViewById(anyInt())).thenReturn(mKeyguardMessageArea);
- when(mKeyguardMessageAreaFactory.create(any(KeyguardMessageArea.class)))
+ when(mKeyguardMessageAreaFactory.create(any()))
.thenReturn(mKeyguardMessageAreaController);
when(mBouncerView.getDelegate()).thenReturn(mBouncerViewDelegate);
when(mBouncerViewDelegate.getBackCallback()).thenReturn(mBouncerViewDelegateBackCallback);
@@ -909,4 +912,26 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
// THEN the alternateBouncer doesn't hide
verify(mAlternateBouncerInteractor, never()).hide();
}
+
+ @Test
+ public void onDeviceUnlocked_hideAlternateBouncerAndClearMessageArea() {
+ reset(mKeyguardUpdateMonitor);
+ reset(mKeyguardMessageAreaController);
+
+ // GIVEN keyguard state controller callback is registered
+ verify(mKeyguardStateController).addCallback(mKeyguardStateControllerCallback.capture());
+
+ // GIVEN alternate bouncer state = not visible
+ when(mAlternateBouncerInteractor.isVisibleState()).thenReturn(false);
+
+ // WHEN the device is unlocked
+ mKeyguardStateControllerCallback.getValue().onUnlockedChanged();
+
+ // THEN the false visibility state is propagated to the keyguardUpdateMonitor
+ verify(mKeyguardUpdateMonitor).setAlternateBouncerShowing(eq(false));
+
+ // THEN message area visibility updated to FALSE with empty message
+ verify(mKeyguardMessageAreaController).setIsVisible(eq(false));
+ verify(mKeyguardMessageAreaController).setMessage(eq(""));
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
index 3ec96908dac8..bde05b9f499e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/MobileRepositorySwitcherTest.kt
@@ -53,6 +53,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
import org.junit.After
import org.junit.Before
import org.junit.Test
@@ -92,13 +93,15 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
private val mobileMappings = FakeMobileMappingsProxy()
private val subscriptionManagerProxy = FakeSubscriptionManagerProxy()
+ private val testDispatcher = UnconfinedTestDispatcher()
private val scope = CoroutineScope(IMMEDIATE)
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
- logFactory = TableLogBufferFactory(dumpManager, FakeSystemClock())
+ logFactory =
+ TableLogBufferFactory(dumpManager, FakeSystemClock(), mock(), testDispatcher, scope)
// Never start in demo mode
whenever(demoModeController.isInDemoMode).thenReturn(false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
index 37fac3458c83..7573b28c8a7f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionParameterizedTest.kt
@@ -61,11 +61,18 @@ import org.junit.runners.Parameterized.Parameters
internal class DemoMobileConnectionParameterizedTest(private val testCase: TestCase) :
SysuiTestCase() {
- private val logFactory = TableLogBufferFactory(mock(), FakeSystemClock())
-
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
+ private val logFactory =
+ TableLogBufferFactory(
+ mock(),
+ FakeSystemClock(),
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope,
+ )
+
private val fakeNetworkEventFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
private val fakeWifiEventFlow = MutableStateFlow<FakeWifiEventModel?>(null)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
index 1251dfacddfc..efaf15235b46 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/demo/DemoMobileConnectionsRepositoryTest.kt
@@ -54,13 +54,20 @@ import org.junit.Test
@SmallTest
class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
private val dumpManager: DumpManager = mock()
- private val logFactory = TableLogBufferFactory(dumpManager, FakeSystemClock())
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
private val fakeNetworkEventFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
private val fakeWifiEventFlow = MutableStateFlow<FakeWifiEventModel?>(null)
+ private val logFactory =
+ TableLogBufferFactory(
+ dumpManager,
+ FakeSystemClock(),
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope,
+ )
private lateinit var underTest: DemoMobileConnectionsRepository
private lateinit var mobileDataSource: DemoModeMobileConnectionDataSource
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
index 9f77744e1fec..b701fbd66937 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/FullMobileConnectionRepositoryTest.kt
@@ -66,7 +66,15 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
private val systemClock = FakeSystemClock()
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
- private val tableLogBuffer = TableLogBuffer(maxSize = 100, name = "TestName", systemClock)
+ private val tableLogBuffer =
+ TableLogBuffer(
+ maxSize = 100,
+ name = "TestName",
+ systemClock,
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope,
+ )
private val mobileFactory = mock<MobileConnectionRepositoryImpl.Factory>()
private val carrierMergedFactory = mock<CarrierMergedConnectionRepository.Factory>()
@@ -294,7 +302,14 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
@Test
fun factory_reusesLogBuffersForSameConnection() =
testScope.runTest {
- val realLoggerFactory = TableLogBufferFactory(mock(), FakeSystemClock())
+ val realLoggerFactory =
+ TableLogBufferFactory(
+ mock(),
+ FakeSystemClock(),
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope,
+ )
val factory =
FullMobileConnectionRepository.Factory(
@@ -329,7 +344,14 @@ class FullMobileConnectionRepositoryTest : SysuiTestCase() {
@Test
fun factory_reusesLogBuffersForSameSubIDevenIfCarrierMerged() =
testScope.runTest {
- val realLoggerFactory = TableLogBufferFactory(mock(), FakeSystemClock())
+ val realLoggerFactory =
+ TableLogBufferFactory(
+ mock(),
+ FakeSystemClock(),
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope,
+ )
val factory =
FullMobileConnectionRepository.Factory(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
index c84c9c032225..6e1ab58db56d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/domain/interactor/MobileIconsInteractorTest.kt
@@ -61,6 +61,16 @@ class MobileIconsInteractorTest : SysuiTestCase() {
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
+ private val tableLogBuffer =
+ TableLogBuffer(
+ 8,
+ "MobileIconsInteractorTest",
+ FakeSystemClock(),
+ mock(),
+ testDispatcher,
+ testScope.backgroundScope,
+ )
+
@Mock private lateinit var carrierConfigTracker: CarrierConfigTracker
@Before
@@ -687,16 +697,14 @@ class MobileIconsInteractorTest : SysuiTestCase() {
}
companion object {
- private val tableLogBuffer =
- TableLogBuffer(8, "MobileIconsInteractorTest", FakeSystemClock())
private const val SUB_1_ID = 1
private val SUB_1 = SubscriptionModel(subscriptionId = SUB_1_ID)
- private val CONNECTION_1 = FakeMobileConnectionRepository(SUB_1_ID, tableLogBuffer)
+ private val CONNECTION_1 = FakeMobileConnectionRepository(SUB_1_ID, mock())
private const val SUB_2_ID = 2
private val SUB_2 = SubscriptionModel(subscriptionId = SUB_2_ID)
- private val CONNECTION_2 = FakeMobileConnectionRepository(SUB_2_ID, tableLogBuffer)
+ private val CONNECTION_2 = FakeMobileConnectionRepository(SUB_2_ID, mock())
private const val SUB_3_ID = 3
private val SUB_3_OPP =
@@ -705,7 +713,7 @@ class MobileIconsInteractorTest : SysuiTestCase() {
isOpportunistic = true,
groupUuid = ParcelUuid(UUID.randomUUID()),
)
- private val CONNECTION_3 = FakeMobileConnectionRepository(SUB_3_ID, tableLogBuffer)
+ private val CONNECTION_3 = FakeMobileConnectionRepository(SUB_3_ID, mock())
private const val SUB_4_ID = 4
private val SUB_4_OPP =
@@ -714,6 +722,6 @@ class MobileIconsInteractorTest : SysuiTestCase() {
isOpportunistic = true,
groupUuid = ParcelUuid(UUID.randomUUID()),
)
- private val CONNECTION_4 = FakeMobileConnectionRepository(SUB_4_ID, tableLogBuffer)
+ private val CONNECTION_4 = FakeMobileConnectionRepository(SUB_4_ID, mock())
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
index 2c0a8fde0d77..492e5421b010 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
@@ -21,13 +21,27 @@ import com.android.systemui.shade.domain.model.ShadeModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
-/** Fake implementation of [KeyguardRepository] */
+/** Fake implementation of [ShadeRepository] */
class FakeShadeRepository : ShadeRepository {
private val _shadeModel = MutableStateFlow(ShadeModel())
override val shadeModel: Flow<ShadeModel> = _shadeModel
+ private val _qsExpansion = MutableStateFlow(0f)
+ override val qsExpansion = _qsExpansion
+
+ private val _udfpsTransitionToFullShadeProgress = MutableStateFlow(0f)
+ override val udfpsTransitionToFullShadeProgress = _udfpsTransitionToFullShadeProgress
+
fun setShadeModel(model: ShadeModel) {
_shadeModel.value = model
}
+
+ override fun setQsExpansion(qsExpansion: Float) {
+ _qsExpansion.value = qsExpansion
+ }
+
+ override fun setUdfpsTransitionToFullShadeProgress(progress: Float) {
+ _udfpsTransitionToFullShadeProgress.value = progress
+ }
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index a3b4a0f51c75..e894f1c2879e 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -490,7 +490,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
mMainHandler, context,
new PolicyWarningUIController.NotificationController(context));
mSecurityPolicy = new AccessibilitySecurityPolicy(policyWarningUIController, mContext,
- this);
+ this, LocalServices.getService(PackageManagerInternal.class));
mA11yWindowManager = new AccessibilityWindowManager(mLock, mMainHandler,
mWindowManagerService, this, mSecurityPolicy, this, mTraceManager);
mA11yDisplayListener = new AccessibilityDisplayListener(mContext, mMainHandler);
@@ -1012,8 +1012,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
+ Binder.getCallingPid() + " for device id " + deviceId
+ " with package names " + Arrays.toString(client.mPackageNames));
}
- return IntPair.of(mProxyManager.getStateLocked(deviceId,
- mUiAutomationManager.isUiAutomationRunningLocked()),
+ return IntPair.of(mProxyManager.getStateLocked(deviceId),
client.mLastSentRelevantEventTypes);
}
mGlobalClients.register(callback, client);
@@ -1028,8 +1027,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
+ Binder.getCallingPid() + " for device id " + deviceId
+ " with package names " + Arrays.toString(client.mPackageNames));
}
- return IntPair.of(mProxyManager.getStateLocked(deviceId,
- mUiAutomationManager.isUiAutomationRunningLocked()),
+ return IntPair.of(mProxyManager.getStateLocked(deviceId),
client.mLastSentRelevantEventTypes);
}
userState.mUserClients.register(callback, client);
@@ -4024,9 +4022,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
final long identity = Binder.clearCallingIdentity();
try {
- mProxyManager.registerProxy(client, displayId, mContext,
- sIdCounter++, mMainHandler, mSecurityPolicy, this, getTraceManager(),
- mWindowManagerService);
+ mProxyManager.registerProxy(client, displayId, sIdCounter++, mSecurityPolicy,
+ this, getTraceManager(), mWindowManagerService);
synchronized (mLock) {
notifyClearAccessibilityCacheLocked();
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java b/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
index 88656239e59b..65c1873498a1 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilitySecurityPolicy.java
@@ -29,6 +29,7 @@ import android.appwidget.AppWidgetManagerInternal;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.UserInfo;
@@ -99,6 +100,7 @@ public class AccessibilitySecurityPolicy {
private final Context mContext;
private final PackageManager mPackageManager;
+ private final PackageManagerInternal mPackageManagerInternal;
private final UserManager mUserManager;
private final AppOpsManager mAppOpsManager;
private final AccessibilityUserManager mAccessibilityUserManager;
@@ -116,10 +118,12 @@ public class AccessibilitySecurityPolicy {
*/
public AccessibilitySecurityPolicy(PolicyWarningUIController policyWarningUIController,
@NonNull Context context,
- @NonNull AccessibilityUserManager a11yUserManager) {
+ @NonNull AccessibilityUserManager a11yUserManager,
+ @NonNull PackageManagerInternal packageManagerInternal) {
mContext = context;
mAccessibilityUserManager = a11yUserManager;
mPackageManager = mContext.getPackageManager();
+ mPackageManagerInternal = packageManagerInternal;
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
mPolicyWarningUIController = policyWarningUIController;
@@ -513,12 +517,7 @@ public class AccessibilitySecurityPolicy {
private boolean isValidPackageForUid(String packageName, int uid) {
final long token = Binder.clearCallingIdentity();
try {
- // Since we treat calls from a profile as if made by its parent, using
- // MATCH_ANY_USER to query the uid of the given package name.
- return uid == mPackageManager.getPackageUidAsUser(
- packageName, PackageManager.MATCH_ANY_USER, UserHandle.getUserId(uid));
- } catch (PackageManager.NameNotFoundException e) {
- return false;
+ return mPackageManagerInternal.isSameApp(packageName, uid, UserHandle.getUserId(uid));
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
index d417197e1419..6dc8fb347904 100644
--- a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java
@@ -61,7 +61,6 @@ import java.util.function.Consumer;
* proxy connection will belong to a separate user state.
*
* TODO(241117292): Remove or cut down during simultaneous user refactoring.
- * TODO(262244375): Add unit tests.
*/
public class ProxyManager {
private static final boolean DEBUG = false;
@@ -128,7 +127,7 @@ public class ProxyManager {
RemoteCallbackList<IAccessibilityManagerClient> getCurrentUserClientsLocked();
}
- ProxyManager(Object lock, AccessibilityWindowManager awm,
+ public ProxyManager(Object lock, AccessibilityWindowManager awm,
Context context, Handler mainHandler, UiAutomationManager uiAutomationManager,
SystemSupport systemSupport) {
mLock = lock;
@@ -144,9 +143,7 @@ public class ProxyManager {
* Creates the service connection.
*/
public void registerProxy(IAccessibilityServiceClient client, int displayId,
- Context context,
- int id, Handler mainHandler,
- AccessibilitySecurityPolicy securityPolicy,
+ int id, AccessibilitySecurityPolicy securityPolicy,
AbstractAccessibilityServiceConnection.SystemSupport systemSupport,
AccessibilityTrace trace,
WindowManagerInternal windowManagerInternal) throws RemoteException {
@@ -169,8 +166,8 @@ public class ProxyManager {
info.setComponentName(new ComponentName(PROXY_COMPONENT_PACKAGE_NAME,
componentClassDisplayName));
ProxyAccessibilityServiceConnection connection =
- new ProxyAccessibilityServiceConnection(context, info.getComponentName(), info,
- id, mainHandler, mLock, securityPolicy, systemSupport, trace,
+ new ProxyAccessibilityServiceConnection(mContext, info.getComponentName(), info,
+ id, mMainHandler, mLock, securityPolicy, systemSupport, trace,
windowManagerInternal,
mA11yWindowManager, displayId, deviceId);
@@ -263,7 +260,7 @@ public class ProxyManager {
* When the connection is removed from tracking in ProxyManager, propagate changes to other a11y
* system components like the input filter and IAccessibilityManagerClients.
*/
- public void updateStateForRemovedDisplay(int displayId, int deviceId) {
+ private void updateStateForRemovedDisplay(int displayId, int deviceId) {
mA11yWindowManager.stopTrackingDisplayProxy(displayId);
// A11yInputFilter isn't thread-safe, so post on the system thread.
mMainHandler.post(
@@ -360,8 +357,9 @@ public class ProxyManager {
/**
* If there is at least one proxy, accessibility is enabled.
*/
- public int getStateLocked(int deviceId, boolean automationRunning) {
+ public int getStateLocked(int deviceId) {
int clientState = 0;
+ final boolean automationRunning = mUiAutomationManager.isUiAutomationRunningLocked();
if (automationRunning) {
clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
}
@@ -387,7 +385,7 @@ public class ProxyManager {
/**
* If there is at least one proxy, accessibility is enabled.
*/
- public int getStateForDisplayIdLocked(ProxyAccessibilityServiceConnection proxy) {
+ private int getStateForDisplayIdLocked(ProxyAccessibilityServiceConnection proxy) {
int clientState = 0;
if (proxy != null) {
clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
@@ -409,14 +407,14 @@ public class ProxyManager {
/**
* Gets the last state for a device.
*/
- public int getLastSentStateLocked(int deviceId) {
+ private int getLastSentStateLocked(int deviceId) {
return mLastStates.get(deviceId, 0);
}
/**
* Sets the last state for a device.
*/
- public void setLastStateLocked(int deviceId, int proxyState) {
+ private void setLastStateLocked(int deviceId, int proxyState) {
mLastStates.put(deviceId, proxyState);
}
@@ -429,7 +427,7 @@ public class ProxyManager {
* Virtual Device, the app clients will get the aggregated event types for all proxy-ed displays
* belonging to a VirtualDevice.
*/
- public void updateRelevantEventTypesLocked(int deviceId) {
+ private void updateRelevantEventTypesLocked(int deviceId) {
if (!isProxyedDeviceId(deviceId)) {
return;
}
@@ -452,7 +450,7 @@ public class ProxyManager {
/**
* Returns the relevant event types for a Client.
*/
- int computeRelevantEventTypesLocked(AccessibilityManagerService.Client client) {
+ public int computeRelevantEventTypesLocked(AccessibilityManagerService.Client client) {
int relevantEventTypes = 0;
for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
final ProxyAccessibilityServiceConnection proxy =
@@ -578,9 +576,8 @@ public class ProxyManager {
/**
* Updates the states of the app AccessibilityManagers.
*/
- public void scheduleUpdateProxyClientsIfNeededLocked(int deviceId) {
- final int proxyState = getStateLocked(deviceId,
- mUiAutomationManager.isUiAutomationRunningLocked());
+ private void scheduleUpdateProxyClientsIfNeededLocked(int deviceId) {
+ final int proxyState = getStateLocked(deviceId);
if (DEBUG) {
Slog.v(LOG_TAG, "State for device id " + deviceId + " is " + proxyState);
Slog.v(LOG_TAG, "Last state for device id " + deviceId + " is "
@@ -606,7 +603,7 @@ public class ProxyManager {
*
* @see AccessibilityManager.AccessibilityServicesStateChangeListener
*/
- public void scheduleNotifyProxyClientsOfServicesStateChangeLocked(int deviceId) {
+ private void scheduleNotifyProxyClientsOfServicesStateChangeLocked(int deviceId) {
if (DEBUG) {
Slog.v(LOG_TAG, "Notify services state change at device id " + deviceId);
}
@@ -625,7 +622,7 @@ public class ProxyManager {
/**
* Updates the focus appearance of AccessibilityManagerClients.
*/
- public void updateFocusAppearanceLocked(int deviceId) {
+ private void updateFocusAppearanceLocked(int deviceId) {
if (DEBUG) {
Slog.v(LOG_TAG, "Update proxy focus appearance at device id " + deviceId);
}
@@ -764,7 +761,7 @@ public class ProxyManager {
/**
* Sets a Client device id if the app uid belongs to the virtual device.
*/
- public void updateDeviceIdsIfNeededLocked(int deviceId) {
+ private void updateDeviceIdsIfNeededLocked(int deviceId) {
final RemoteCallbackList<IAccessibilityManagerClient> userClients =
mSystemSupport.getCurrentUserClientsLocked();
final RemoteCallbackList<IAccessibilityManagerClient> globalClients =
@@ -777,7 +774,7 @@ public class ProxyManager {
/**
* Updates the device ids of IAccessibilityManagerClients if needed.
*/
- public void updateDeviceIdsIfNeededLocked(int deviceId,
+ private void updateDeviceIdsIfNeededLocked(int deviceId,
@NonNull RemoteCallbackList<IAccessibilityManagerClient> clients) {
final VirtualDeviceManagerInternal localVdm = getLocalVdm();
if (localVdm == null) {
@@ -809,14 +806,17 @@ public class ProxyManager {
}
}
- void setAccessibilityInputFilter(AccessibilityInputFilter filter) {
+ /**
+ * Sets the input filter for enabling and disabling features for proxy displays.
+ */
+ public void setAccessibilityInputFilter(AccessibilityInputFilter filter) {
if (DEBUG) {
Slog.v(LOG_TAG, "Set proxy input filter to " + filter);
}
mA11yInputFilter = filter;
}
- VirtualDeviceManagerInternal getLocalVdm() {
+ private VirtualDeviceManagerInternal getLocalVdm() {
if (mLocalVdm == null) {
mLocalVdm = LocalServices.getService(VirtualDeviceManagerInternal.class);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
index a13df475d25d..9747579fa231 100644
--- a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
+++ b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
@@ -36,6 +36,7 @@ import android.view.WindowManager;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import com.android.internal.R;
+import com.android.internal.accessibility.util.AccessibilityUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ScreenshotHelper;
@@ -302,8 +303,10 @@ public class SystemActionPerformer {
case AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT:
return takeScreenshot();
case AccessibilityService.GLOBAL_ACTION_KEYCODE_HEADSETHOOK:
- sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HEADSETHOOK,
- InputDevice.SOURCE_KEYBOARD);
+ if (!AccessibilityUtils.interceptHeadsetHookForActiveCall(mContext)) {
+ sendDownAndUpKeyEvents(KeyEvent.KEYCODE_HEADSETHOOK,
+ InputDevice.SOURCE_KEYBOARD);
+ }
return true;
case AccessibilityService.GLOBAL_ACTION_DPAD_UP:
sendDownAndUpKeyEvents(KeyEvent.KEYCODE_DPAD_UP,
diff --git a/services/autofill/java/com/android/server/autofill/Helper.java b/services/autofill/java/com/android/server/autofill/Helper.java
index bc5d6457c945..ac770439a524 100644
--- a/services/autofill/java/com/android/server/autofill/Helper.java
+++ b/services/autofill/java/com/android/server/autofill/Helper.java
@@ -16,13 +16,18 @@
package com.android.server.autofill;
+import static com.android.server.autofill.Helper.sDebug;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.ViewNode;
import android.app.assist.AssistStructure.WindowNode;
import android.content.ComponentName;
+import android.content.Context;
+import android.hardware.display.DisplayManager;
import android.metrics.LogMaker;
+import android.os.UserManager;
import android.service.autofill.Dataset;
import android.service.autofill.InternalSanitizer;
import android.service.autofill.SaveInfo;
@@ -30,6 +35,7 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
+import android.view.Display;
import android.view.View;
import android.view.WindowManager;
import android.view.autofill.AutofillId;
@@ -37,6 +43,7 @@ import android.view.autofill.AutofillValue;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.ArrayUtils;
+import com.android.server.utils.Slogf;
import java.io.PrintWriter;
import java.util.ArrayDeque;
@@ -281,6 +288,38 @@ public final class Helper {
return true;
}
+ /**
+ * Gets a context with the proper display id.
+ *
+ * <p>For most cases it will return the provided context, but on devices that
+ * {@link UserManager#isVisibleBackgroundUsersEnabled() support visible background users}, it
+ * will return a context with the display pased as parameter.
+ */
+ static Context getDisplayContext(Context context, int displayId) {
+ if (!UserManager.isVisibleBackgroundUsersEnabled()) {
+ return context;
+ }
+ if (context.getDisplayId() == displayId) {
+ if (sDebug) {
+ Slogf.d(TAG, "getDisplayContext(): context %s already has displayId %d", context,
+ displayId);
+ }
+ return context;
+ }
+ if (sDebug) {
+ Slogf.d(TAG, "Creating context for display %d", displayId);
+ }
+ Display display = context.getSystemService(DisplayManager.class).getDisplay(displayId);
+ if (display == null) {
+ Slogf.wtf(TAG, "Could not get context with displayId %d, Autofill operations will "
+ + "probably fail)", displayId);
+ return context;
+ }
+
+ return context.createDisplayContext(display);
+ }
+
+
private interface ViewNodeFilter {
boolean matches(ViewNode node);
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 3ab5bca215dc..f83d7342b6e3 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -164,10 +164,12 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.ArrayUtils;
+import com.android.server.LocalServices;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.autofill.ui.InlineFillUi;
import com.android.server.autofill.ui.PendingUi;
import com.android.server.inputmethod.InputMethodManagerInternal;
+import com.android.server.wm.ActivityTaskManagerInternal;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -214,7 +216,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
private final AutofillManagerServiceImpl mService;
private final Handler mHandler;
private final AutoFillUI mUi;
- @NonNull private final Context mContext;
+
+ /**
+ * Context associated with the session, it has the same {@link Context#getDisplayId() displayId}
+ * of the activity being autofilled.
+ */
+ private final Context mContext;
private final MetricsLogger mMetricsLogger = new MetricsLogger();
@@ -1352,7 +1359,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mHasCallback = hasCallback;
mUiLatencyHistory = uiLatencyHistory;
mWtfHistory = wtfHistory;
- mContext = context;
+ int displayId = LocalServices.getService(ActivityTaskManagerInternal.class)
+ .getDisplayId(activityToken);
+ mContext = Helper.getDisplayContext(context, displayId);
mComponentName = componentName;
mCompatMode = compatMode;
mSessionState = STATE_ACTIVE;
@@ -3401,7 +3410,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
final long saveUiDisplayStartTimestamp = SystemClock.elapsedRealtime();
getUiForShowing().showSaveUi(serviceLabel, serviceIcon,
mService.getServicePackageName(), saveInfo, this,
- mComponentName, this, userId, mPendingSaveUi, isUpdate, mCompatMode,
+ mComponentName, this, mContext, mPendingSaveUi, isUpdate, mCompatMode,
response.getShowSaveDialogIcon());
mSaveEventLogger.maybeSetLatencySaveUiDisplayMillis(
SystemClock.elapsedRealtime()- saveUiDisplayStartTimestamp);
@@ -4272,7 +4281,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
getUiForShowing().showFillUi(filledId, response, filterText,
mService.getServicePackageName(), mComponentName,
- targetLabel, targetIcon, this, userId, id, mCompatMode);
+ targetLabel, targetIcon, this, mContext, id, mCompatMode);
synchronized (mLock) {
mPresentationStatsEventLogger.maybeSetCountShown(
@@ -5453,6 +5462,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
pw.print(prefix); pw.print("uid: "); pw.println(uid);
pw.print(prefix); pw.print("taskId: "); pw.println(taskId);
pw.print(prefix); pw.print("flags: "); pw.println(mFlags);
+ pw.print(prefix); pw.print("displayId: "); pw.println(mContext.getDisplayId());
pw.print(prefix); pw.print("state: "); pw.println(sessionStateAsString(mSessionState));
pw.print(prefix); pw.print("mComponentName: "); pw.println(mComponentName);
pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index cfd66f1e7351..b3cbe45ea4a7 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -23,7 +23,6 @@ import static com.android.server.autofill.Helper.sVerbose;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UserIdInt;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -53,6 +52,7 @@ import com.android.server.LocalServices;
import com.android.server.UiModeManagerInternal;
import com.android.server.UiThread;
import com.android.server.autofill.Helper;
+import com.android.server.utils.Slogf;
import java.io.PrintWriter;
@@ -198,6 +198,7 @@ public final class AutoFillUI {
* @param serviceIcon icon of autofill service
* @param callback identifier for the caller
* @param userId the user associated wit the session
+ * @param context context with the proper state (like display id) to show the UI
* @param sessionId id of the autofill session
* @param compatMode whether the app is being autofilled in compatibility mode.
*/
@@ -205,11 +206,11 @@ public final class AutoFillUI {
@Nullable String filterText, @Nullable String servicePackageName,
@NonNull ComponentName componentName, @NonNull CharSequence serviceLabel,
@NonNull Drawable serviceIcon, @NonNull AutoFillUiCallback callback,
- @UserIdInt int userId, int sessionId, boolean compatMode) {
+ @NonNull Context context, int sessionId, boolean compatMode) {
if (sDebug) {
final int size = filterText == null ? 0 : filterText.length();
- Slog.d(TAG, "showFillUi(): id=" + focusedId + ", filter=" + size + " chars, userId="
- + userId);
+ Slogf.d(TAG, "showFillUi(): id=%s, filter=%d chars, displayId=%d", focusedId, size,
+ context.getDisplayId());
}
final LogMaker log = Helper
.newLogMaker(MetricsEvent.AUTOFILL_FILL_UI, componentName, servicePackageName,
@@ -224,10 +225,8 @@ public final class AutoFillUI {
return;
}
hideAllUiThread(callback);
- mFillUi = new FillUi(mContext, userId, response, focusedId,
- filterText, mOverlayControl, serviceLabel, serviceIcon,
- mUiModeMgr.isNightMode(),
- new FillUi.Callback() {
+ mFillUi = new FillUi(context, response, focusedId, filterText, mOverlayControl,
+ serviceLabel, serviceIcon, mUiModeMgr.isNightMode(), new FillUi.Callback() {
@Override
public void onResponsePicked(FillResponse response) {
log.setType(MetricsEvent.TYPE_DETAIL);
@@ -325,12 +324,12 @@ public final class AutoFillUI {
public void showSaveUi(@NonNull CharSequence serviceLabel, @NonNull Drawable serviceIcon,
@Nullable String servicePackageName, @NonNull SaveInfo info,
@NonNull ValueFinder valueFinder, @NonNull ComponentName componentName,
- @NonNull AutoFillUiCallback callback, @UserIdInt int userId,
+ @NonNull AutoFillUiCallback callback, @NonNull Context context,
@NonNull PendingUi pendingSaveUi, boolean isUpdate, boolean compatMode,
boolean showServiceIcon) {
if (sVerbose) {
- Slog.v(TAG, "showSaveUi(update=" + isUpdate + ") for " + componentName.toShortString()
- + " and user " + userId + ": " + info);
+ Slogf.v(TAG, "showSaveUi(update=%b) for %s and display %d: %s", isUpdate,
+ componentName.toShortString(), context.getDisplayId(), info);
}
int numIds = 0;
numIds += info.getRequiredIds() == null ? 0 : info.getRequiredIds().length;
@@ -350,7 +349,7 @@ public final class AutoFillUI {
}
hideAllUiThread(callback);
mSaveUiCallback = callback;
- mSaveUi = new SaveUi(mContext, userId, pendingSaveUi, serviceLabel, serviceIcon,
+ mSaveUi = new SaveUi(context, pendingSaveUi, serviceLabel, serviceIcon,
servicePackageName, componentName, info, valueFinder, mOverlayControl,
new SaveUi.OnSaveListener() {
@Override
diff --git a/services/autofill/java/com/android/server/autofill/ui/DisplayHelper.java b/services/autofill/java/com/android/server/autofill/ui/DisplayHelper.java
deleted file mode 100644
index 53534809a1ae..000000000000
--- a/services/autofill/java/com/android/server/autofill/ui/DisplayHelper.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open 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.autofill.ui;
-
-import static com.android.server.autofill.Helper.sDebug;
-
-import android.annotation.UserIdInt;
-import android.content.Context;
-import android.hardware.display.DisplayManager;
-import android.os.UserManager;
-import android.view.Display;
-
-import com.android.server.LocalServices;
-import com.android.server.pm.UserManagerInternal;
-import com.android.server.utils.Slogf;
-
-/**
- * Helper for display-related needs.
- */
-final class DisplayHelper {
-
- private static final String TAG = "AutofillDisplayHelper";
-
- private static final UserManagerInternal sUmi = LocalServices
- .getService(UserManagerInternal.class);
-
- /**
- * Gets a context with the proper display id set for the given user.
- *
- * <p>For most cases it will return the provided context, but on devices that
- * {@link UserManager#isVisibleBackgroundUsersEnabled() support visible background users}, it
- * will return a context with the display the user started visible on.
- */
- static Context getDisplayContext(Context context, @UserIdInt int userId) {
- if (!UserManager.isVisibleBackgroundUsersEnabled()) {
- return context;
- }
- int displayId = sUmi.getMainDisplayAssignedToUser(userId);
- if (sDebug) {
- Slogf.d(TAG, "Creating context for display %d for user %d", displayId, userId);
- }
- Display display = context.getSystemService(DisplayManager.class).getDisplay(displayId);
- if (display == null) {
- Slogf.wtf(TAG, "Could not get display with id %d (which is associated with user %d; "
- + "FillUi operations will probably fail", displayId, userId);
- return context;
- }
-
- return context.createDisplayContext(display);
- }
-
- private DisplayHelper() {
- throw new UnsupportedOperationException("Contains only static methods");
- }
-}
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index b651ae592866..129ce72e037d 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -22,7 +22,6 @@ import static com.android.server.autofill.Helper.sVerbose;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UserIdInt;
import android.content.Context;
import android.content.IntentSender;
import android.content.pm.PackageManager;
@@ -61,6 +60,7 @@ import com.android.internal.R;
import com.android.server.UiThread;
import com.android.server.autofill.AutofillManagerService;
import com.android.server.autofill.Helper;
+import com.android.server.utils.Slogf;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -134,14 +134,15 @@ final class FillUi {
return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK);
}
- FillUi(@NonNull Context systemContext, @UserIdInt int userId, @NonNull FillResponse response,
+ FillUi(@NonNull Context context, @NonNull FillResponse response,
@NonNull AutofillId focusedViewId, @Nullable String filterText,
@NonNull OverlayControl overlayControl, @NonNull CharSequence serviceLabel,
@NonNull Drawable serviceIcon, boolean nightMode, @NonNull Callback callback) {
- if (sVerbose) Slog.v(TAG, "nightMode: " + nightMode);
+ if (sVerbose) {
+ Slogf.v(TAG, "nightMode: %b displayId: %d", nightMode, context.getDisplayId());
+ }
mThemeId = nightMode ? THEME_ID_DARK : THEME_ID_LIGHT;
mCallback = callback;
- Context context = DisplayHelper.getDisplayContext(systemContext, userId);
mFullScreen = isFullScreen(context);
mContext = new ContextThemeWrapper(context, mThemeId);
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index aec0bdfa3a76..12042594fefb 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -21,7 +21,6 @@ import static com.android.server.autofill.Helper.sVerbose;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.UserIdInt;
import android.app.Dialog;
import android.app.PendingIntent;
import android.content.ComponentName;
@@ -71,6 +70,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.ArrayUtils;
import com.android.server.UiThread;
import com.android.server.autofill.Helper;
+import com.android.server.utils.Slogf;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -173,14 +173,15 @@ final class SaveUi {
private boolean mDestroyed;
- SaveUi(@NonNull Context systemContext, @UserIdInt int userId, @NonNull PendingUi pendingUi,
+ SaveUi(@NonNull Context context, @NonNull PendingUi pendingUi,
@NonNull CharSequence serviceLabel, @NonNull Drawable serviceIcon,
@Nullable String servicePackageName, @NonNull ComponentName componentName,
@NonNull SaveInfo info, @NonNull ValueFinder valueFinder,
@NonNull OverlayControl overlayControl, @NonNull OnSaveListener listener,
boolean nightMode, boolean isUpdate, boolean compatMode, boolean showServiceIcon) {
- Context context = DisplayHelper.getDisplayContext(systemContext, userId);
- if (sVerbose) Slog.v(TAG, "nightMode: " + nightMode);
+ if (sVerbose) {
+ Slogf.v(TAG, "nightMode: %b displayId: %d", nightMode, context.getDisplayId());
+ }
mThemeId = nightMode ? THEME_ID_DARK : THEME_ID_LIGHT;
mPendingUi = pendingUi;
mListener = new OneActionThenDestroyListener(listener);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index df3c95bdfaf3..678d58232f15 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -3866,7 +3866,7 @@ public final class ActiveServices {
if (UserHandle.isCore(callingUid)) {
return;
}
- final int callingUserId = UserHandle.getCallingUserId();
+ final int callingUserId = UserHandle.getUserId(callingUid);
if (callingUserId == userId
|| !mAm.mUserController.isSameProfileGroup(callingUserId, userId)) {
return;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index d140403f77c3..6360e2a0d089 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -167,7 +167,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE)
.replaceWith("?");
- private static final int MAX_LOW_POWER_STATS_SIZE = 16384;
+ private static final int MAX_LOW_POWER_STATS_SIZE = 32768;
private static final int POWER_STATS_QUERY_TIMEOUT_MILLIS = 2000;
private static final String EMPTY = "Empty";
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
index 0767218ec065..5c68e6759083 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -242,8 +242,7 @@ class BroadcastProcessQueue {
*/
@Nullable
public BroadcastRecord enqueueOrReplaceBroadcast(@NonNull BroadcastRecord record,
- int recordIndex, boolean wouldBeSkipped,
- @NonNull BroadcastConsumer deferredStatesApplyConsumer) {
+ int recordIndex, @NonNull BroadcastConsumer deferredStatesApplyConsumer) {
// When updateDeferredStates() has already applied a deferred state to
// all pending items, apply to this new broadcast too
if (mLastDeferredStates && record.deferUntilActive
@@ -252,8 +251,7 @@ class BroadcastProcessQueue {
}
if (record.isReplacePending()) {
- final BroadcastRecord replacedBroadcastRecord = replaceBroadcast(record, recordIndex,
- wouldBeSkipped);
+ final BroadcastRecord replacedBroadcastRecord = replaceBroadcast(record, recordIndex);
if (replacedBroadcastRecord != null) {
return replacedBroadcastRecord;
}
@@ -264,14 +262,13 @@ class BroadcastProcessQueue {
SomeArgs newBroadcastArgs = SomeArgs.obtain();
newBroadcastArgs.arg1 = record;
newBroadcastArgs.argi1 = recordIndex;
- newBroadcastArgs.argi2 = (wouldBeSkipped ? 1 : 0);
// Cross-broadcast prioritization policy: some broadcasts might warrant being
// issued ahead of others that are already pending, for example if this new
// broadcast is in a different delivery class or is tied to a direct user interaction
// with implicit responsiveness expectations.
getQueueForBroadcast(record).addLast(newBroadcastArgs);
- onBroadcastEnqueued(record, recordIndex, wouldBeSkipped);
+ onBroadcastEnqueued(record, recordIndex);
return null;
}
@@ -285,10 +282,9 @@ class BroadcastProcessQueue {
* wasn't any broadcast that was replaced.
*/
@Nullable
- private BroadcastRecord replaceBroadcast(@NonNull BroadcastRecord record, int recordIndex,
- boolean wouldBeSkipped) {
+ private BroadcastRecord replaceBroadcast(@NonNull BroadcastRecord record, int recordIndex) {
final ArrayDeque<SomeArgs> queue = getQueueForBroadcast(record);
- return replaceBroadcastInQueue(queue, record, recordIndex, wouldBeSkipped);
+ return replaceBroadcastInQueue(queue, record, recordIndex);
}
/**
@@ -302,15 +298,13 @@ class BroadcastProcessQueue {
*/
@Nullable
private BroadcastRecord replaceBroadcastInQueue(@NonNull ArrayDeque<SomeArgs> queue,
- @NonNull BroadcastRecord record, int recordIndex,
- boolean wouldBeSkipped) {
+ @NonNull BroadcastRecord record, int recordIndex) {
final Iterator<SomeArgs> it = queue.descendingIterator();
final Object receiver = record.receivers.get(recordIndex);
while (it.hasNext()) {
final SomeArgs args = it.next();
final BroadcastRecord testRecord = (BroadcastRecord) args.arg1;
final int testRecordIndex = args.argi1;
- final boolean testWouldBeSkipped = (args.argi2 == 1);
final Object testReceiver = testRecord.receivers.get(testRecordIndex);
if ((record.callingUid == testRecord.callingUid)
&& (record.userId == testRecord.userId)
@@ -320,10 +314,9 @@ class BroadcastProcessQueue {
// Exact match found; perform in-place swap
args.arg1 = record;
args.argi1 = recordIndex;
- args.argi2 = (wouldBeSkipped ? 1 : 0);
record.copyEnqueueTimeFrom(testRecord);
- onBroadcastDequeued(testRecord, testRecordIndex, testWouldBeSkipped);
- onBroadcastEnqueued(record, recordIndex, wouldBeSkipped);
+ onBroadcastDequeued(testRecord, testRecordIndex);
+ onBroadcastEnqueued(record, recordIndex);
return testRecord;
}
}
@@ -383,13 +376,12 @@ class BroadcastProcessQueue {
final SomeArgs args = it.next();
final BroadcastRecord record = (BroadcastRecord) args.arg1;
final int recordIndex = args.argi1;
- final boolean recordWouldBeSkipped = (args.argi2 == 1);
if (predicate.test(record, recordIndex)) {
consumer.accept(record, recordIndex);
if (andRemove) {
args.recycle();
it.remove();
- onBroadcastDequeued(record, recordIndex, recordWouldBeSkipped);
+ onBroadcastDequeued(record, recordIndex);
} else {
// Even if we're leaving broadcast in queue, it may have
// been mutated in such a way to change our runnable time
@@ -539,12 +531,11 @@ class BroadcastProcessQueue {
final SomeArgs next = removeNextBroadcast();
mActive = (BroadcastRecord) next.arg1;
mActiveIndex = next.argi1;
- final boolean wouldBeSkipped = (next.argi2 == 1);
mActiveCountSinceIdle++;
mActiveViaColdStart = false;
mActiveWasStopped = false;
next.recycle();
- onBroadcastDequeued(mActive, mActiveIndex, wouldBeSkipped);
+ onBroadcastDequeued(mActive, mActiveIndex);
}
/**
@@ -561,8 +552,7 @@ class BroadcastProcessQueue {
/**
* Update summary statistics when the given record has been enqueued.
*/
- private void onBroadcastEnqueued(@NonNull BroadcastRecord record, int recordIndex,
- boolean wouldBeSkipped) {
+ private void onBroadcastEnqueued(@NonNull BroadcastRecord record, int recordIndex) {
mCountEnqueued++;
if (record.deferUntilActive) {
mCountDeferred++;
@@ -594,8 +584,7 @@ class BroadcastProcessQueue {
if (record.callerInstrumented) {
mCountInstrumented++;
}
- if (!wouldBeSkipped
- && (record.receivers.get(recordIndex) instanceof ResolveInfo)) {
+ if (record.receivers.get(recordIndex) instanceof ResolveInfo) {
mCountManifest++;
}
invalidateRunnableAt();
@@ -604,8 +593,7 @@ class BroadcastProcessQueue {
/**
* Update summary statistics when the given record has been dequeued.
*/
- private void onBroadcastDequeued(@NonNull BroadcastRecord record, int recordIndex,
- boolean wouldBeSkipped) {
+ private void onBroadcastDequeued(@NonNull BroadcastRecord record, int recordIndex) {
mCountEnqueued--;
if (record.deferUntilActive) {
mCountDeferred--;
@@ -637,8 +625,7 @@ class BroadcastProcessQueue {
if (record.callerInstrumented) {
mCountInstrumented--;
}
- if (!wouldBeSkipped
- && (record.receivers.get(recordIndex) instanceof ResolveInfo)) {
+ if (record.receivers.get(recordIndex) instanceof ResolveInfo) {
mCountManifest--;
}
invalidateRunnableAt();
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 8735f8a37b8b..96e152320282 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -606,24 +606,18 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
final BroadcastProcessQueue queue = getOrCreateProcessQueue(
getReceiverProcessName(receiver), getReceiverUid(receiver));
- boolean wouldBeSkipped = false;
- if (receiver instanceof ResolveInfo) {
- // If the app is running but would not have been started if the process weren't
- // running, we're going to deliver the broadcast but mark that it's not a manifest
- // broadcast that would have started the app. This allows BroadcastProcessQueue to
- // defer the broadcast as though it were a normal runtime receiver.
- wouldBeSkipped = (mSkipPolicy.shouldSkipMessage(r, receiver) != null);
- if (wouldBeSkipped && queue.app == null && !queue.getActiveViaColdStart()) {
- // Skip receiver if there's no running app, the app is not being started, and
- // the app wouldn't be launched for this broadcast
- setDeliveryState(null, null, r, i, receiver, BroadcastRecord.DELIVERY_SKIPPED,
- "skipped by policy to avoid cold start");
- continue;
- }
+ // If this receiver is going to be skipped, skip it now itself and don't even enqueue
+ // it.
+ final boolean wouldBeSkipped = (mSkipPolicy.shouldSkipMessage(r, receiver) != null);
+ if (wouldBeSkipped) {
+ setDeliveryState(null, null, r, i, receiver, BroadcastRecord.DELIVERY_SKIPPED,
+ "skipped by policy at enqueue");
+ continue;
}
+
enqueuedBroadcast = true;
final BroadcastRecord replacedBroadcast = queue.enqueueOrReplaceBroadcast(
- r, i, wouldBeSkipped, mBroadcastConsumerDeferApply);
+ r, i, mBroadcastConsumerDeferApply);
if (replacedBroadcast != null) {
replacedBroadcasts.add(replacedBroadcast);
}
diff --git a/services/core/java/com/android/server/broadcastradio/RadioServiceUserController.java b/services/core/java/com/android/server/broadcastradio/RadioServiceUserController.java
index 38b323395329..4b847a27c4de 100644
--- a/services/core/java/com/android/server/broadcastradio/RadioServiceUserController.java
+++ b/services/core/java/com/android/server/broadcastradio/RadioServiceUserController.java
@@ -39,18 +39,24 @@ public final class RadioServiceUserController {
*/
public static boolean isCurrentOrSystemUser() {
int callingUser = Binder.getCallingUserHandle().getIdentifier();
+ return callingUser == getCurrentUser() || callingUser == UserHandle.USER_SYSTEM;
+ }
+
+ /**
+ * Get current foreground user for Broadcast Radio Service
+ *
+ * @return foreground user id.
+ */
+ public static int getCurrentUser() {
final long identity = Binder.clearCallingIdentity();
+ int userId = UserHandle.USER_NULL;
try {
- int currentUser = ActivityManager.getCurrentUser();
- if (callingUser != currentUser && callingUser != UserHandle.USER_SYSTEM) {
- return false;
- }
- return true;
+ userId = ActivityManager.getCurrentUser();
} catch (RuntimeException e) {
// Activity manager not running, nothing we can do assume user 0.
} finally {
Binder.restoreCallingIdentity(identity);
}
- return false;
+ return userId;
}
}
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java b/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java
index 132fb8ef8a95..7c87c6c55289 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java
@@ -36,11 +36,13 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.broadcastradio.RadioServiceUserController;
import com.android.server.utils.Slogf;
import java.util.ArrayList;
@@ -419,8 +421,13 @@ final class RadioModule {
@GuardedBy("mLock")
private void fanoutAidlCallbackLocked(AidlCallbackRunnable runnable) {
+ int currentUserId = RadioServiceUserController.getCurrentUser();
List<TunerSession> deadSessions = null;
for (int i = 0; i < mAidlTunerSessions.size(); i++) {
+ if (mAidlTunerSessions.valueAt(i).mUserId != currentUserId
+ && mAidlTunerSessions.valueAt(i).mUserId != UserHandle.USER_SYSTEM) {
+ continue;
+ }
try {
runnable.run(mAidlTunerSessions.valueAt(i).mCallback,
mAidlTunerSessions.valueAt(i).getUid());
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java b/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java
index 0a3823f038fa..beff7bd3cffd 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java
@@ -46,6 +46,7 @@ final class TunerSession extends ITuner.Stub {
private final RadioLogger mLogger;
private final RadioModule mModule;
+ final int mUserId;
final android.hardware.radio.ITunerCallback mCallback;
private final int mUid;
private final IBroadcastRadio mService;
@@ -65,6 +66,7 @@ final class TunerSession extends ITuner.Stub {
android.hardware.radio.ITunerCallback callback) {
mModule = Objects.requireNonNull(radioModule, "radioModule cannot be null");
mService = Objects.requireNonNull(service, "service cannot be null");
+ mUserId = Binder.getCallingUserHandle().getIdentifier();
mCallback = Objects.requireNonNull(callback, "callback cannot be null");
mUid = Binder.getCallingUid();
mLogger = new RadioLogger(TAG, TUNER_EVENT_LOGGER_QUEUE_SIZE);
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
index 59a81544d8ef..7b5cb898b6b5 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
@@ -38,12 +38,14 @@ import android.os.DeadObjectException;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.IndentingPrintWriter;
import android.util.MutableInt;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.broadcastradio.RadioServiceUserController;
import java.util.ArrayList;
import java.util.HashSet;
@@ -374,8 +376,13 @@ final class RadioModule {
@GuardedBy("mLock")
private void fanoutAidlCallbackLocked(AidlCallbackRunnable runnable) {
+ int currentUserId = RadioServiceUserController.getCurrentUser();
List<TunerSession> deadSessions = null;
for (TunerSession tunerSession : mAidlTunerSessions) {
+ if (tunerSession.mUserId != currentUserId && tunerSession.mUserId
+ != UserHandle.USER_SYSTEM) {
+ continue;
+ }
try {
runnable.run(tunerSession.mCallback);
} catch (DeadObjectException ex) {
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index 204b9649135e..1efc4a50aa08 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -26,6 +26,7 @@ import android.hardware.radio.ITuner;
import android.hardware.radio.ProgramList;
import android.hardware.radio.ProgramSelector;
import android.hardware.radio.RadioManager;
+import android.os.Binder;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
@@ -52,6 +53,7 @@ class TunerSession extends ITuner.Stub {
private final RadioModule mModule;
private final ITunerSession mHwSession;
+ final int mUserId;
final android.hardware.radio.ITunerCallback mCallback;
@GuardedBy("mLock")
@@ -68,6 +70,7 @@ class TunerSession extends ITuner.Stub {
@NonNull android.hardware.radio.ITunerCallback callback) {
mModule = Objects.requireNonNull(module);
mHwSession = Objects.requireNonNull(hwSession);
+ mUserId = Binder.getCallingUserHandle().getIdentifier();
mCallback = Objects.requireNonNull(callback);
mEventLogger = new RadioEventLogger(TAG, TUNER_EVENT_LOGGER_QUEUE_SIZE);
}
diff --git a/services/core/java/com/android/server/cpu/CpuMonitorService.java b/services/core/java/com/android/server/cpu/CpuMonitorService.java
index df8cfad4ab03..7ea2c1b02040 100644
--- a/services/core/java/com/android/server/cpu/CpuMonitorService.java
+++ b/services/core/java/com/android/server/cpu/CpuMonitorService.java
@@ -653,8 +653,17 @@ public final class CpuMonitorService extends SystemService {
}
public int getAverageAvailableCpuFreqPercent() {
- return (int) ((totalNormalizedAvailableCpuFreqKHz * 100.0)
+ int percent = (int) ((totalNormalizedAvailableCpuFreqKHz * 100.0)
/ totalOnlineMaxCpuFreqKHz);
+ if (percent < 0) {
+ // TODO(b/279478586): This case should never happen. But this case happens
+ // rarely on certain hardware, which indicates a deeper issue. Once this
+ // issue is reproduced, use this log to debug the issue and fix it.
+ Slogf.wtf(TAG, "Computed negative CPU availability percent(%d) for %s ",
+ percent, toString());
+ return 0;
+ }
+ return percent;
}
@Override
diff --git a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
index a3f8c4d16cd1..7574de841440 100644
--- a/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
+++ b/services/core/java/com/android/server/display/brightness/DisplayBrightnessController.java
@@ -437,6 +437,7 @@ public final class DisplayBrightnessController {
* persist the nit value, the nit value for the default display will be loaded.
*/
private void loadNitBasedBrightnessSetting() {
+ float currentBrightnessSetting = Float.NaN;
if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) {
float brightnessNitsForDefaultDisplay =
mBrightnessSetting.getBrightnessNitsForDefaultDisplay();
@@ -445,15 +446,17 @@ public final class DisplayBrightnessController {
brightnessNitsForDefaultDisplay);
if (BrightnessUtils.isValidBrightnessValue(brightnessForDefaultDisplay)) {
mBrightnessSetting.setBrightness(brightnessForDefaultDisplay);
- synchronized (mLock) {
- mCurrentScreenBrightness = brightnessForDefaultDisplay;
- }
- return;
+ currentBrightnessSetting = brightnessForDefaultDisplay;
}
}
}
+
+ if (Float.isNaN(currentBrightnessSetting)) {
+ currentBrightnessSetting = getScreenBrightnessSetting();
+ }
+
synchronized (mLock) {
- mCurrentScreenBrightness = getScreenBrightnessSetting();
+ mCurrentScreenBrightness = currentBrightnessSetting;
}
}
}
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 7a51126eff2d..377b8cf1230e 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -395,8 +395,8 @@ public final class MediaProjectionManagerService extends SystemService
synchronized (mLock) {
final boolean consentGranted =
consentResult == RECORD_CONTENT_DISPLAY || consentResult == RECORD_CONTENT_TASK;
- if (consentGranted && projection == null || !isCurrentProjection(
- projection.asBinder())) {
+ if (consentGranted && !isCurrentProjection(
+ projection == null ? null : projection.asBinder())) {
Slog.v(TAG, "Reusing token: Ignore consent result of " + consentResult + " for a "
+ "token that isn't current");
return;
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 402fb30437b0..9b1a80bed17b 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -1120,12 +1120,12 @@ public class LauncherAppsService extends SystemService {
return shortcutOverridesInfo;
}
- List<String> packagesToOverride =
+ Map<String, String> packagesToOverride =
DevicePolicyCache.getInstance().getLauncherShortcutOverrides();
- for (String packageName : packagesToOverride) {
+ for (Map.Entry<String, String> packageNames : packagesToOverride.entrySet()) {
Intent intent = new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_LAUNCHER)
- .setPackage(packageName);
+ .setPackage(packageNames.getValue());
List<LauncherActivityInfoInternal> possibleShortcutOverrides =
queryIntentLauncherActivities(
@@ -1135,7 +1135,8 @@ public class LauncherAppsService extends SystemService {
);
if (!possibleShortcutOverrides.isEmpty()) {
- shortcutOverridesInfo.put(packageName, possibleShortcutOverrides.get(0));
+ shortcutOverridesInfo.put(packageNames.getKey(),
+ possibleShortcutOverrides.get(0));
}
}
return shortcutOverridesInfo;
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index b669ba238880..84a9888d2458 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -1716,6 +1716,11 @@ public class ShortcutService extends IShortcutService.Stub {
if (si == null) {
return;
}
+
+ if (isCallerSystem()) {
+ return; // no check
+ }
+
if (!Objects.equals(callerPackage, si.getPackage())) {
android.util.EventLog.writeEvent(0x534e4554, "109824443", -1, "");
throw new SecurityException("Shortcut package name mismatch");
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 51872b339c40..98d2d3d4b997 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -803,6 +803,20 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
protected WallpaperData mLastLockWallpaper;
private IWallpaperManagerCallback mKeyguardListener;
private boolean mWaitingForUnlock;
+
+ /**
+ * Flag set to true after reboot if the home wallpaper is waiting for the device to be unlocked.
+ * This happens for wallpapers that are not direct-boot aware; they can only be rendered after
+ * the user unlocks the device for the first time after a reboot. In the meantime, the default
+ * wallpaper is shown instead.
+ */
+ private boolean mHomeWallpaperWaitingForUnlock;
+
+ /**
+ * Flag set to true after reboot if the lock wallpaper is waiting for the device to be unlocked.
+ */
+ private boolean mLockWallpaperWaitingForUnlock;
+
private boolean mShuttingDown;
/**
@@ -1790,7 +1804,23 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
public void onUnlockUser(final int userId) {
synchronized (mLock) {
if (mCurrentUserId == userId) {
- if (mWaitingForUnlock) {
+ if (mIsLockscreenLiveWallpaperEnabled) {
+ if (mHomeWallpaperWaitingForUnlock) {
+ final WallpaperData systemWallpaper =
+ getWallpaperSafeLocked(userId, FLAG_SYSTEM);
+ switchWallpaper(systemWallpaper, null);
+ // TODO(b/278261563): call notifyCallbacksLocked inside switchWallpaper
+ notifyCallbacksLocked(systemWallpaper);
+ }
+ if (mLockWallpaperWaitingForUnlock) {
+ final WallpaperData lockWallpaper =
+ getWallpaperSafeLocked(userId, FLAG_LOCK);
+ switchWallpaper(lockWallpaper, null);
+ notifyCallbacksLocked(lockWallpaper);
+ }
+ }
+
+ if (mWaitingForUnlock && !mIsLockscreenLiveWallpaperEnabled) {
// the desired wallpaper is not direct-boot aware, load it now
final WallpaperData systemWallpaper =
getWallpaperSafeLocked(userId, FLAG_SYSTEM);
@@ -1845,13 +1875,23 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
mCurrentUserId = userId;
systemWallpaper = getWallpaperSafeLocked(userId, FLAG_SYSTEM);
- final WallpaperData tmpLockWallpaper = mLockWallpaperMap.get(userId);
- lockWallpaper = tmpLockWallpaper == null ? systemWallpaper : tmpLockWallpaper;
+
+ if (mIsLockscreenLiveWallpaperEnabled) {
+ lockWallpaper = systemWallpaper.mWhich == (FLAG_LOCK | FLAG_SYSTEM)
+ ? systemWallpaper : getWallpaperSafeLocked(userId, FLAG_LOCK);
+ } else {
+ final WallpaperData tmpLockWallpaper = mLockWallpaperMap.get(userId);
+ lockWallpaper = tmpLockWallpaper == null ? systemWallpaper : tmpLockWallpaper;
+ }
+
// Not started watching yet, in case wallpaper data was loaded for other reasons.
if (systemWallpaper.wallpaperObserver == null) {
systemWallpaper.wallpaperObserver = new WallpaperObserver(systemWallpaper);
systemWallpaper.wallpaperObserver.startWatching();
}
+ if (mIsLockscreenLiveWallpaperEnabled && lockWallpaper != systemWallpaper) {
+ switchWallpaper(lockWallpaper, null);
+ }
switchWallpaper(systemWallpaper, reply);
}
@@ -1870,6 +1910,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
synchronized (mLock) {
mWaitingForUnlock = false;
+ if (mIsLockscreenLiveWallpaperEnabled) {
+ if ((wallpaper.mWhich & FLAG_SYSTEM) != 0) mHomeWallpaperWaitingForUnlock = false;
+ if ((wallpaper.mWhich & FLAG_LOCK) != 0) mLockWallpaperWaitingForUnlock = false;
+ }
+
final ComponentName cname = wallpaper.wallpaperComponent != null ?
wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
if (!bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
@@ -1882,6 +1927,11 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
} catch (RemoteException ignored) {
}
+ if (mIsLockscreenLiveWallpaperEnabled) {
+ onSwitchWallpaperFailLocked(wallpaper, reply, si);
+ return;
+ }
+
if (si == null) {
Slog.w(TAG, "Failure starting previous wallpaper; clearing");
clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, reply);
@@ -1899,6 +1949,43 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
}
+ /**
+ * Fallback method if a wallpaper fails to load on boot or after a user switch.
+ * Only called if mIsLockscreenLiveWallpaperEnabled is true.
+ */
+ private void onSwitchWallpaperFailLocked(
+ WallpaperData wallpaper, IRemoteCallback reply, ServiceInfo serviceInfo) {
+
+ if (serviceInfo == null) {
+ Slog.w(TAG, "Failure starting previous wallpaper; clearing");
+
+ if (wallpaper.mWhich == (FLAG_LOCK | FLAG_SYSTEM)) {
+ clearWallpaperLocked(false, FLAG_SYSTEM, wallpaper.userId, null);
+ clearWallpaperLocked(false, FLAG_LOCK, wallpaper.userId, reply);
+ } else {
+ clearWallpaperLocked(false, wallpaper.mWhich, wallpaper.userId, reply);
+ }
+ return;
+ }
+ Slog.w(TAG, "Wallpaper isn't direct boot aware; using fallback until unlocked");
+ // We might end up persisting the current wallpaper data
+ // while locked, so pretend like the component was actually
+ // bound into place
+ wallpaper.wallpaperComponent = wallpaper.nextWallpaperComponent;
+ final WallpaperData fallback = new WallpaperData(wallpaper.userId, wallpaper.mWhich);
+
+ // files from the previous static wallpaper may still be stored in memory.
+ // delete them in order to show the default wallpaper.
+ if (wallpaper.wallpaperFile.exists()) {
+ wallpaper.wallpaperFile.delete();
+ wallpaper.cropFile.delete();
+ }
+
+ bindWallpaperComponentLocked(mImageWallpaper, true, false, fallback, reply);
+ if ((wallpaper.mWhich & FLAG_SYSTEM) != 0) mHomeWallpaperWaitingForUnlock = true;
+ if ((wallpaper.mWhich & FLAG_LOCK) != 0) mLockWallpaperWaitingForUnlock = true;
+ }
+
@Override
public void clearWallpaper(String callingPackage, int which, int userId) {
if (DEBUG) Slog.v(TAG, "clearWallpaper");
diff --git a/services/core/java/com/android/server/wm/AbsAppSnapshotController.java b/services/core/java/com/android/server/wm/AbsAppSnapshotController.java
index 32f7b9682fb7..5c929a93bf12 100644
--- a/services/core/java/com/android/server/wm/AbsAppSnapshotController.java
+++ b/services/core/java/com/android/server/wm/AbsAppSnapshotController.java
@@ -239,7 +239,17 @@ abstract class AbsAppSnapshotController<TYPE extends WindowContainer,
}
return null;
}
- source.getBounds(mTmpRect);
+ mTmpRect.setEmpty();
+ if (source.mTransitionController.inFinishingTransition(source)) {
+ final Transition.ChangeInfo changeInfo = source.mTransitionController
+ .mFinishingTransition.mChanges.get(source);
+ if (changeInfo != null) {
+ mTmpRect.set(changeInfo.mAbsoluteBounds);
+ }
+ }
+ if (mTmpRect.isEmpty()) {
+ source.getBounds(mTmpRect);
+ }
mTmpRect.offsetTo(0, 0);
SurfaceControl[] excludeLayers;
final WindowState imeWindow = source.getDisplayContent().mInputMethodWindow;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index f843b7c5e3ab..78c066bdc212 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -5296,6 +5296,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (isCollecting) {
mTransitionController.collect(this);
} else {
+ // Failsafe to make sure that we show any activities that were incorrectly hidden
+ // during a transition. If this vis-change is a result of finishing, ignore it.
+ // Finish should only ever commit visibility=false, so we can check full containment
+ // rather than just direct membership.
inFinishingTransition = mTransitionController.inFinishingTransition(this);
if (!inFinishingTransition && !mDisplayContent.isSleeping()) {
Slog.e(TAG, "setVisibility=" + visible
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 4949ebc46b80..3f4a775bc37a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -755,4 +755,10 @@ public abstract class ActivityTaskManagerInternal {
/** Unregister a task stack listener so that it stops receiving callbacks. */;
public abstract void unregisterTaskStackListener(ITaskStackListener listener);
+
+ /**
+ * Gets the id of the display the activity was launched on.
+ * @param token The activity token.
+ */
+ public abstract int getDisplayId(IBinder token);
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index b37703204b7b..1f4606b09396 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5816,6 +5816,18 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
@Override
+ public int getDisplayId(IBinder token) {
+ synchronized (mGlobalLock) {
+ ActivityRecord r = ActivityRecord.forTokenLocked(token);
+ if (r == null) {
+ throw new IllegalArgumentException(
+ "setFocusedActivity: No activity record matching token=" + token);
+ }
+ return r.getDisplayId();
+ }
+ }
+
+ @Override
public void registerScreenObserver(ScreenObserver observer) {
mScreenObservers.add(observer);
}
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 747819e93ff2..ce4362853b23 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1882,6 +1882,12 @@ public class DisplayPolicy {
static final int DECOR_TYPES = Type.displayCutout() | Type.navigationBars();
+ /**
+ * The types that may affect display configuration. This excludes cutout because it is
+ * known from display info.
+ */
+ static final int CONFIG_TYPES = Type.statusBars() | Type.navigationBars();
+
private final DisplayContent mDisplayContent;
private final Info[] mInfoForRotation = new Info[4];
final Info mTmpInfo = new Info();
@@ -1921,7 +1927,7 @@ public class DisplayPolicy {
final DecorInsets.Info newInfo = mDecorInsets.mTmpInfo;
newInfo.update(mDisplayContent, rotation, dw, dh);
final DecorInsets.Info currentInfo = getDecorInsetsInfo(rotation, dw, dh);
- if (newInfo.mNonDecorFrame.equals(currentInfo.mNonDecorFrame)) {
+ if (newInfo.mConfigFrame.equals(currentInfo.mConfigFrame)) {
return false;
}
mDecorInsets.invalidate();
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index a5e652cce41e..a3d233df7b61 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -123,6 +123,7 @@ public class DisplayRotation {
public final boolean isDefaultDisplay;
private final boolean mSupportAutoRotation;
+ private final boolean mAllowRotationResolver;
private final int mLidOpenRotation;
private final int mCarDockRotation;
private final int mDeskDockRotation;
@@ -272,6 +273,8 @@ public class DisplayRotation {
mSupportAutoRotation =
mContext.getResources().getBoolean(R.bool.config_supportAutoRotation);
+ mAllowRotationResolver =
+ mContext.getResources().getBoolean(R.bool.config_allowRotationResolver);
mLidOpenRotation = readRotation(R.integer.config_lidOpenRotation);
mCarDockRotation = readRotation(R.integer.config_carDockRotation);
mDeskDockRotation = readRotation(R.integer.config_deskDockRotation);
@@ -2041,7 +2044,8 @@ public class DisplayRotation {
@Override
public boolean isRotationResolverEnabled() {
- return mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
+ return mAllowRotationResolver
+ && mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
&& mCameraRotationMode == CAMERA_ROTATION_ENABLED
&& !mService.mPowerManager.isPowerSaveMode();
}
diff --git a/services/core/java/com/android/server/wm/RemoteAnimationController.java b/services/core/java/com/android/server/wm/RemoteAnimationController.java
index b879d1a8ec56..eb639b6f2033 100644
--- a/services/core/java/com/android/server/wm/RemoteAnimationController.java
+++ b/services/core/java/com/android/server/wm/RemoteAnimationController.java
@@ -362,15 +362,8 @@ class RemoteAnimationController implements DeathRecipient {
private void invokeAnimationCancelled(String reason) {
ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "cancelAnimation(): reason=%s", reason);
- final boolean isKeyguardOccluded = mDisplayContent.isKeyguardOccluded();
-
try {
- EventLogTags.writeWmSetKeyguardOccluded(
- isKeyguardOccluded ? 1 : 0,
- 0 /* animate */,
- 0 /* transit */,
- "onAnimationCancelled");
- mRemoteAnimationAdapter.getRunner().onAnimationCancelled(isKeyguardOccluded);
+ mRemoteAnimationAdapter.getRunner().onAnimationCancelled();
} catch (RemoteException e) {
Slog.e(TAG, "Failed to notify cancel", e);
}
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index abc9f8a48584..d531ad175f10 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -244,6 +244,16 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
private IContainerFreezer mContainerFreezer = null;
private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
+ /**
+ * {@code true} if some other operation may have caused the originally-recorded state (in
+ * mChanges) to be dirty. This is usually due to finishTransition being called mid-collect;
+ * and, the reason that finish can alter the "start" state of other transitions is because
+ * setVisible(false) is deferred until then.
+ * Instead of adding this conditional, we could re-check always; but, this situation isn't
+ * common so it'd be wasted work.
+ */
+ boolean mPriorVisibilityMightBeDirty = false;
+
final TransitionController.Logger mLogger = new TransitionController.Logger();
/** Whether this transition was forced to play early (eg for a SLEEP signal). */
@@ -966,28 +976,30 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
mController.mFinishingTransition = this;
if (mTransientHideTasks != null && !mTransientHideTasks.isEmpty()) {
- // Record all the now-hiding activities so that they are committed after
- // recalculating visibilities. We just use mParticipants because we can and it will
- // ensure proper reporting of `isInFinishTransition`.
+ // The transient hide tasks could be occluded now, e.g. returning to home. So trigger
+ // the update to make the activities in the tasks invisible-requested, then the next
+ // step can continue to commit the visibility.
+ mController.mAtm.mRootWindowContainer.ensureActivitiesVisible(null /* starting */,
+ 0 /* configChanges */, true /* preserveWindows */);
+ // Record all the now-hiding activities so that they are committed. Just use
+ // mParticipants because we can avoid a new list this way.
for (int i = 0; i < mTransientHideTasks.size(); ++i) {
+ // Only worry about tasks that were actually hidden. Otherwise, we could end-up
+ // committing visibility for activity-level changes that aren't part of this
+ // transition.
+ if (mTransientHideTasks.get(i).isVisibleRequested()) continue;
mTransientHideTasks.get(i).forAllActivities(r -> {
// Only check leaf-tasks that were collected
if (!mParticipants.contains(r.getTask())) return;
- // Only concern ourselves with anything that can become invisible
- if (!r.isVisible()) return;
mParticipants.add(r);
});
}
- // The transient hide tasks could be occluded now, e.g. returning to home. So trigger
- // the update to make the activities in the tasks invisible-requested, then the next
- // step can continue to commit the visibility.
- mController.mAtm.mRootWindowContainer.ensureActivitiesVisible(null /* starting */,
- 0 /* configChanges */, true /* preserveWindows */);
}
boolean hasParticipatedDisplay = false;
boolean hasVisibleTransientLaunch = false;
boolean enterAutoPip = false;
+ boolean committedSomeInvisible = false;
// Commit all going-invisible containers
for (int i = 0; i < mParticipants.size(); ++i) {
final WindowContainer<?> participant = mParticipants.valueAt(i);
@@ -1023,6 +1035,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
}
ar.commitVisibility(false /* visible */, false /* performLayout */,
true /* fromTransition */);
+ committedSomeInvisible = true;
} else {
enterAutoPip = true;
}
@@ -1081,6 +1094,9 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
}
}
}
+ if (committedSomeInvisible) {
+ mController.onCommittedInvisibles();
+ }
if (hasVisibleTransientLaunch) {
// Notify the change about the transient-below task if entering auto-pip.
@@ -1293,6 +1309,9 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
// leftover order changes.
collectOrderChanges(mController.mWaitingTransitions.isEmpty());
+ if (mPriorVisibilityMightBeDirty) {
+ updatePriorVisibility();
+ }
// Resolve the animating targets from the participants.
mTargets = calculateTargets(mParticipants, mChanges);
// Check whether the participants were animated from back navigation.
@@ -1806,6 +1825,20 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
}
}
+ private void updatePriorVisibility() {
+ for (int i = 0; i < mChanges.size(); ++i) {
+ final ChangeInfo chg = mChanges.valueAt(i);
+ // For task/activity, recalculate the current "real" visibility.
+ if (chg.mContainer.asActivityRecord() == null && chg.mContainer.asTask() == null) {
+ continue;
+ }
+ // This ONLY works in the visible -> invisible case (and is only needed for this case)
+ // because commitVisible(false) is deferred until finish.
+ if (!chg.mVisible) continue;
+ chg.mVisible = chg.mContainer.isVisible();
+ }
+ }
+
/**
* Under some conditions (eg. all visible targets within a parent container are transitioning
* the same way) the transition can be "promoted" to the parent container. This means an
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index b0feefe2a3b0..7950edaaa267 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -408,9 +408,9 @@ class TransitionController {
return false;
}
- /** Returns {@code true} if the `wc` is a participant of the finishing transition. */
+ /** Returns {@code true} if the finishing transition contains `wc`. */
boolean inFinishingTransition(WindowContainer<?> wc) {
- return mFinishingTransition != null && mFinishingTransition.mParticipants.contains(wc);
+ return mFinishingTransition != null && mFinishingTransition.isInTransition(wc);
}
/** @return {@code true} if a transition is running */
@@ -827,6 +827,16 @@ class TransitionController {
}
}
+ /** Called by {@link Transition#finishTransition} if it committed invisible to any activities */
+ void onCommittedInvisibles() {
+ if (mCollectingTransition != null) {
+ mCollectingTransition.mPriorVisibilityMightBeDirty = true;
+ }
+ for (int i = mWaitingTransitions.size() - 1; i >= 0; --i) {
+ mWaitingTransitions.get(i).mPriorVisibilityMightBeDirty = true;
+ }
+ }
+
private void validateStates() {
for (int i = 0; i < mStateValidators.size(); ++i) {
mStateValidators.get(i).run();
@@ -964,6 +974,7 @@ class TransitionController {
if (sync) {
info.setFlags(info.getFlags() | TransitionInfo.FLAG_SYNC);
}
+ transition.mAnimationTrack = track;
info.setTrack(track);
mTrackCount = Math.max(mTrackCount, track + 1);
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index f4a1765d4663..510e6756b8ef 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -3839,7 +3839,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
// This can still happen if WMCore starts a new transition when there is ongoing
// sync transaction from Shell. Please file a bug if it happens.
throw new IllegalStateException("Can't sync on 2 groups simultaneously"
- + " currentSyncId=" + mSyncGroup.mSyncId + " newSyncId=" + group.mSyncId);
+ + " currentSyncId=" + mSyncGroup.mSyncId + " newSyncId=" + group.mSyncId
+ + " wc=" + this);
}
mSyncGroup = group;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 40b8274d4e51..6cb6d9d7bcea 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1831,7 +1831,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean needToSendNewConfiguration =
win.isVisibleRequestedOrAdding() && displayContent.updateOrientation();
- if (win.providesNonDecorInsets()) {
+ if (win.providesDisplayDecorInsets()) {
needToSendNewConfiguration |= displayPolicy.updateDecorInsetsInfo();
}
if (needToSendNewConfiguration) {
@@ -2274,7 +2274,7 @@ public class WindowManagerService extends IWindowManager.Stub
& WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED) != 0) {
win.mLayoutNeeded = true;
}
- if (layoutChanged && win.providesNonDecorInsets()) {
+ if (layoutChanged && win.providesDisplayDecorInsets()) {
configChanged = displayPolicy.updateDecorInsetsInfo();
}
if (win.mActivityRecord != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 2920652674d3..6f07b7719be0 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1834,13 +1834,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return (mPolicyVisibility & POLICY_VISIBILITY_ALL) == POLICY_VISIBILITY_ALL;
}
- boolean providesNonDecorInsets() {
+ boolean providesDisplayDecorInsets() {
if (mInsetsSourceProviders == null) {
return false;
}
for (int i = mInsetsSourceProviders.size() - 1; i >= 0; i--) {
final InsetsSource source = mInsetsSourceProviders.valueAt(i).getSource();
- if (source.getType() == WindowInsets.Type.navigationBars()) {
+ if ((source.getType() & DisplayPolicy.DecorInsets.CONFIG_TYPES) != 0) {
return true;
}
}
@@ -2507,13 +2507,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
// Check if window provides non decor insets before clearing its provided insets.
- final boolean windowProvidesNonDecorInsets = providesNonDecorInsets();
+ final boolean windowProvidesDisplayDecorInsets = providesDisplayDecorInsets();
removeImmediately();
// Removing a visible window may affect the display orientation so just update it if
// needed. Also recompute configuration if it provides screen decor insets.
boolean needToSendNewConfiguration = wasVisible && displayContent.updateOrientation();
- if (windowProvidesNonDecorInsets) {
+ if (windowProvidesDisplayDecorInsets) {
needToSendNewConfiguration |=
displayContent.getDisplayPolicy().updateDecorInsetsInfo();
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
index 80100a927e82..c681b884d2ed 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyCacheImpl.java
@@ -19,13 +19,13 @@ import android.annotation.UserIdInt;
import android.app.admin.DevicePolicyCache;
import android.app.admin.DevicePolicyManager;
import android.os.UserHandle;
+import android.util.ArrayMap;
import android.util.IndentingPrintWriter;
import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -55,8 +55,7 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache {
private final SparseIntArray mPermissionPolicy = new SparseIntArray();
@GuardedBy("mLock")
- private List<String> mLauncherShortcutOverrides =
- new ArrayList<>();
+ private ArrayMap<String, String> mLauncherShortcutOverrides = new ArrayMap<>();
/** Maps to {@code ActiveAdmin.mAdminCanGrantSensorsPermissions}. */
@@ -130,18 +129,20 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache {
}
@Override
- public List<String> getLauncherShortcutOverrides() {
+ public Map<String, String> getLauncherShortcutOverrides() {
synchronized (mLock) {
- return new ArrayList<>(mLauncherShortcutOverrides);
+ return new ArrayMap<>(mLauncherShortcutOverrides);
}
}
/**
- * Sets a list of packages for which shortcuts should be replaced by their badged version.
+ * Sets a map of packages names to package names, for which all launcher shortcuts which
+ * match a key package name should be modified to launch the corresponding value package
+ * name in the managed profile. The overridden shortcut should be badged accordingly.
*/
- public void setLauncherShortcutOverrides(List<String> launcherShortcutOverrides) {
+ public void setLauncherShortcutOverrides(ArrayMap<String, String> launcherShortcutOverrides) {
synchronized (mLock) {
- mLauncherShortcutOverrides = new ArrayList<>(launcherShortcutOverrides);
+ mLauncherShortcutOverrides = new ArrayMap<>(launcherShortcutOverrides);
}
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index 415440b1f46d..cf49dcf8004e 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -130,12 +130,11 @@ final class DevicePolicyEngine {
<V> void setLocalPolicy(
@NonNull PolicyDefinition<V> policyDefinition,
@NonNull EnforcingAdmin enforcingAdmin,
- @NonNull PolicyValue<V> value,
+ @Nullable PolicyValue<V> value,
int userId,
boolean skipEnforcePolicy) {
Objects.requireNonNull(policyDefinition);
Objects.requireNonNull(enforcingAdmin);
- Objects.requireNonNull(value);
synchronized (mLock) {
PolicyState<V> localPolicyState = getLocalPolicyStateLocked(policyDefinition, userId);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 22f684bea73d..a35f34dcde86 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -80,6 +80,7 @@ import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIFI;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WINDOWS;
import static android.Manifest.permission.MANAGE_DEVICE_POLICY_WIPE_DATA;
import static android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS;
+import static android.Manifest.permission.MASTER_CLEAR;
import static android.Manifest.permission.QUERY_ADMIN_POLICY;
import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
import static android.Manifest.permission.SET_TIME;
@@ -7552,9 +7553,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
boolean calledByProfileOwnerOnOrgOwnedDevice =
isProfileOwnerOfOrganizationOwnedDevice(caller.getUserId());
if (isPolicyEngineForFinanceFlagEnabled()) {
- EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
+ EnforcingAdmin enforcingAdmin = enforcePermissionsAndGetEnforcingAdmin(
/*admin=*/ null,
- /*permission= */ MANAGE_DEVICE_POLICY_WIPE_DATA,
+ /*permission=*/ new String[]{MANAGE_DEVICE_POLICY_WIPE_DATA, MASTER_CLEAR},
USES_POLICY_WIPE_DATA,
caller.getPackageName(),
factoryReset ? UserHandle.USER_ALL : getAffectedUser(calledOnParentInstance));
@@ -7576,12 +7577,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
admin = getActiveAdminWithPolicyForUidLocked(/* who= */ null,
DeviceAdminInfo.USES_POLICY_WIPE_DATA, caller.getUid());
}
+ Preconditions.checkCallAuthorization(
+ (admin != null) || hasCallingOrSelfPermission(permission.MASTER_CLEAR),
+ "No active admin for user %d and caller %d does not hold MASTER_CLEAR "
+ + "permission",
+ caller.getUserId(), caller.getUid());
}
- Preconditions.checkCallAuthorization(
- (admin != null) || hasCallingOrSelfPermission(permission.MASTER_CLEAR),
- "No active admin for user %d and caller %d does not hold MASTER_CLEAR permission",
- caller.getUserId(), caller.getUid());
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_WIPE_DATA);
if (TextUtils.isEmpty(wipeReasonForUser)) {
@@ -7721,7 +7723,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
private void clearLauncherShortcutOverrides() {
- mPolicyCache.setLauncherShortcutOverrides(new ArrayList<>());
+ mPolicyCache.setLauncherShortcutOverrides(new ArrayMap<>());
}
private void updateTelephonyCrossProfileIntentFilters(int parentUserId, int profileUserId,
@@ -7836,15 +7838,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} else {
// Explicit behaviour
if (factoryReset) {
- // TODO(b/254031494) Replace with new factory reset permission checks
- if (!isPermissionCheckFlagEnabled()) {
- boolean hasPermission = isDeviceOwnerUserId(userId)
- || (isOrganizationOwnedDeviceWithManagedProfile()
- && calledOnParentInstance);
- Preconditions.checkCallAuthorization(hasPermission,
- "Admin %s does not have permission to factory reset the device.",
- userId);
- }
+ EnforcingAdmin enforcingAdmin = enforcePermissionsAndGetEnforcingAdmin(
+ /*admin=*/ null,
+ /*permission=*/ new String[]{MANAGE_DEVICE_POLICY_WIPE_DATA,
+ MASTER_CLEAR},
+ USES_POLICY_WIPE_DATA,
+ adminPackage,
+ factoryReset ? UserHandle.USER_ALL :
+ getAffectedUser(calledOnParentInstance));
wipeDevice = true;
} else {
Preconditions.checkCallAuthorization(!isSystemUser,
@@ -12214,17 +12215,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
synchronized (getLockObject()) {
- ActiveAdmin admin;
- if (isPermissionCheckFlagEnabled()) {
- admin = enforcePermissionAndGetEnforcingAdmin(
- who, MANAGE_DEVICE_POLICY_INPUT_METHODS,
- caller.getPackageName(), userId).getActiveAdmin();
+ if (isPolicyEngineForFinanceFlagEnabled()) {
+ EnforcingAdmin admin = getEnforcingAdminForCaller(who, callerPackageName);
+ mDevicePolicyEngine.setLocalPolicy(
+ PolicyDefinition.PERMITTED_INPUT_METHODS,
+ admin,
+ packageList == null
+ ? null
+ : new StringSetPolicyValue(new HashSet<>(packageList)),
+ userId);
} else {
- admin = getParentOfAdminIfRequired(
- getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()), calledOnParentInstance);
+ ActiveAdmin admin = getParentOfAdminIfRequired(
+ getProfileOwnerOrDeviceOwnerLocked(caller.getUserId()),
+ calledOnParentInstance);
+ admin.permittedInputMethods = packageList;
+ saveSettingsLocked(caller.getUserId());
}
- admin.permittedInputMethods = packageList;
- saveSettingsLocked(caller.getUserId());
}
DevicePolicyEventLogger
@@ -12272,19 +12278,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
synchronized (getLockObject()) {
- ActiveAdmin admin;
- if (isPermissionCheckFlagEnabled()) {
+ if (isPolicyEngineForFinanceFlagEnabled()) {
int affectedUser = calledOnParentInstance ? getProfileParentId(
caller.getUserId()) : caller.getUserId();
- admin = enforcePermissionAndGetEnforcingAdmin(
- who, MANAGE_DEVICE_POLICY_INPUT_METHODS, caller.getPackageName(),
- affectedUser).getActiveAdmin();
+ Set<String> policy = mDevicePolicyEngine.getResolvedPolicy(
+ PolicyDefinition.PERMITTED_INPUT_METHODS, affectedUser);
+ return policy == null ? null : new ArrayList<>(policy);
} else {
- admin = getParentOfAdminIfRequired(
+ ActiveAdmin admin = getParentOfAdminIfRequired(
getProfileOwnerOrDeviceOwnerLocked(
caller.getUserId()), calledOnParentInstance);
+ return admin.permittedInputMethods;
}
- return admin.permittedInputMethods;
}
}
@@ -12302,37 +12307,45 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
private @Nullable List<String> getPermittedInputMethodsUnchecked(@UserIdInt int userId) {
- synchronized (getLockObject()) {
- List<String> result = null;
- // Only device or profile owners can have permitted lists set.
- List<ActiveAdmin> admins = getActiveAdminsForAffectedUserInclPermissionBasedAdminLocked(userId);
- for (ActiveAdmin admin: admins) {
- List<String> fromAdmin = admin.permittedInputMethods;
- if (fromAdmin != null) {
- if (result == null) {
- result = new ArrayList<String>(fromAdmin);
- } else {
- result.retainAll(fromAdmin);
+ List<String> result = null;
+ if (isPolicyEngineForFinanceFlagEnabled()) {
+ Set<String> policy = mDevicePolicyEngine.getResolvedPolicy(
+ PolicyDefinition.PERMITTED_INPUT_METHODS, userId);
+ result = policy == null ? null : new ArrayList<>(policy);
+ } else {
+ synchronized (getLockObject()) {
+ // Only device or profile owners can have permitted lists set.
+ List<ActiveAdmin> admins =
+ getActiveAdminsForAffectedUserInclPermissionBasedAdminLocked(
+ userId);
+ for (ActiveAdmin admin : admins) {
+ List<String> fromAdmin = admin.permittedInputMethods;
+ if (fromAdmin != null) {
+ if (result == null) {
+ result = new ArrayList<String>(fromAdmin);
+ } else {
+ result.retainAll(fromAdmin);
+ }
}
}
}
+ }
- // If we have a permitted list add all system input methods.
- if (result != null) {
- List<InputMethodInfo> imes = InputMethodManagerInternal
- .get().getInputMethodListAsUser(userId);
- if (imes != null) {
- for (InputMethodInfo ime : imes) {
- ServiceInfo serviceInfo = ime.getServiceInfo();
- ApplicationInfo applicationInfo = serviceInfo.applicationInfo;
- if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
- result.add(serviceInfo.packageName);
- }
+ // If we have a permitted list add all system input methods.
+ if (result != null) {
+ List<InputMethodInfo> imes = InputMethodManagerInternal
+ .get().getInputMethodListAsUser(userId);
+ if (imes != null) {
+ for (InputMethodInfo ime : imes) {
+ ServiceInfo serviceInfo = ime.getServiceInfo();
+ ApplicationInfo applicationInfo = serviceInfo.applicationInfo;
+ if ((applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ result.add(serviceInfo.packageName);
}
}
}
- return result;
}
+ return result;
}
@Override
@@ -12347,17 +12360,38 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
String.format(NOT_SYSTEM_CALLER_MSG,
"query if an input method is disabled by admin"));
- synchronized (getLockObject()) {
- ActiveAdmin admin = getParentOfAdminIfRequired(
- getActiveAdminUncheckedLocked(who, userHandle), calledOnParentInstance);
- if (admin == null) {
- return false;
+ if (isPolicyEngineForFinanceFlagEnabled()) {
+ int affectedUser = calledOnParentInstance ? getProfileParentId(userHandle) : userHandle;
+ Map<EnforcingAdmin, PolicyValue<Set<String>>> policies =
+ mDevicePolicyEngine.getLocalPoliciesSetByAdmins(
+ PolicyDefinition.PERMITTED_INPUT_METHODS, affectedUser);
+ EnforcingAdmin admin = null;
+ for (EnforcingAdmin a : policies.keySet()) {
+ if (a.getPackageName().equals(who.getPackageName())) {
+ if (policies.get(a).getValue() == null) {
+ return true;
+ } else {
+ return checkPackagesInPermittedListOrSystem(
+ Collections.singletonList(packageName),
+ new ArrayList<>(policies.get(a).getValue()), affectedUser);
+ }
+ }
}
- if (admin.permittedInputMethods == null) {
- return true;
+ // Admin didn't set a policy
+ return false;
+ } else {
+ synchronized (getLockObject()) {
+ ActiveAdmin admin = getParentOfAdminIfRequired(
+ getActiveAdminUncheckedLocked(who, userHandle), calledOnParentInstance);
+ if (admin == null) {
+ return false;
+ }
+ if (admin.permittedInputMethods == null) {
+ return true;
+ }
+ return checkPackagesInPermittedListOrSystem(Collections.singletonList(packageName),
+ admin.permittedInputMethods, userHandle);
}
- return checkPackagesInPermittedListOrSystem(Collections.singletonList(packageName),
- admin.permittedInputMethods, userHandle);
}
}
@@ -21613,7 +21647,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
copyAccount(targetUser, sourceUser, accountToMigrate, callerPackage);
if (!keepAccountMigrated) {
- removeAccount(accountToMigrate);
+ removeAccount(accountToMigrate, sourceUserId);
}
}
@@ -21657,9 +21691,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
.write();
}
- private void removeAccount(Account account) {
- final AccountManager accountManager =
- mContext.getSystemService(AccountManager.class);
+ private void removeAccount(Account account, @UserIdInt int sourceUserId) {
+ final AccountManager accountManager = mContext.createContextAsUser(
+ UserHandle.of(sourceUserId), /* flags= */ 0)
+ .getSystemService(AccountManager.class);
final AccountManagerFuture<Bundle> bundle = accountManager.removeAccount(account,
null, null /* callback */, null /* handler */);
try {
@@ -23191,6 +23226,28 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
/**
+ * Checks if the calling process has been granted permission to apply a device policy on a
+ * specific user. Only one permission provided in the list needs to be granted to pass this
+ * check.
+ * The given permissions will be checked along with their associated cross-user permissions if
+ * they exist and the target user is different to the calling user.
+ * Returns an {@link EnforcingAdmin} for the caller.
+ *
+ * @param admin the component name of the admin.
+ * @param callerPackageName The package name of the calling application.
+ * @param permissions The names of the permissions being checked.
+ * @param deviceAdminPolicy The userId of the user which the caller needs permission to act on.
+ * @throws SecurityException if the caller has not been granted the given permission,
+ * the associated cross-user permission if the caller's user is different to the target user.
+ */
+ private EnforcingAdmin enforcePermissionsAndGetEnforcingAdmin(@Nullable ComponentName admin,
+ String[] permissions, int deviceAdminPolicy, String callerPackageName,
+ int targetUserId) {
+ enforcePermissions(permissions, deviceAdminPolicy, callerPackageName, targetUserId);
+ return getEnforcingAdminForCaller(admin, callerPackageName);
+ }
+
+ /**
* Checks whether the calling process has been granted permission to query a device policy on
* a specific user.
* The given permission will be checked along with its associated cross-user permission if it
@@ -23236,12 +23293,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
/**
* Checks if the calling process has been granted permission to apply a device policy on a
- * specific user.
- * The given permission will be checked along with its associated cross-user permission if it
- * exists and the target user is different to the calling user.
+ * specific user. Only one permission provided in the list needs to be granted to pass this
+ * check.
+ * The given permissions will be checked along with their associated cross-user permissions if
+ * they exists and the target user is different to the calling user.
*
* @param callerPackageName The package name of the calling application.
- * @param permission The name of the permission being checked.
+ * @param permissions The names of the permissions being checked.
* @param targetUserId The userId of the user which the caller needs permission to act on.
* @throws SecurityException if the caller has not been granted the given permission,
* the associated cross-user permission if the caller's user is different to the target user.
@@ -23306,6 +23364,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
/**
+ * Checks if the calling process has been granted permission to apply a device policy on a
+ * specific user.
+ * The given permission will be checked along with its associated cross-user permission if it
+ * exists and the target user is different to the calling user.
+ *
+ * @param callerPackageName The package name of the calling application.
+ * @param adminPolicy The admin policy that should grant holders permission.
+ * @param permission The name of the permission being checked.
+ * @param targetUserId The userId of the user which the caller needs permission to act on.
+ * @throws SecurityException if the caller has not been granted the given permission,
+ * the associated cross-user permission if the caller's user is different to the target user.
+ */
+ private void enforcePermissions(String[] permissions, int adminPolicy,
+ String callerPackageName, int targetUserId) throws SecurityException {
+ if (hasAdminPolicy(adminPolicy, callerPackageName)) {
+ return;
+ }
+ enforcePermissions(permissions, callerPackageName, targetUserId);
+ }
+
+ /**
* Checks whether the calling process has been granted permission to query a device policy on
* a specific user.
* The given permission will be checked along with its associated cross-user permission if it
@@ -23432,7 +23511,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Check for non-DPC active admins.
admin = getActiveAdminForCaller(who, caller);
if (admin != null) {
- return EnforcingAdmin.createDeviceAdminEnforcingAdmin(who, userId, admin);
+ return EnforcingAdmin.createDeviceAdminEnforcingAdmin(admin.info.getComponent(), userId,
+ admin);
}
admin = getUserData(userId).createOrGetPermissionBasedAdmin(userId);
return EnforcingAdmin.createEnforcingAdmin(caller.getPackageName(), userId, admin);
@@ -23720,15 +23800,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private void updateDialerAndSmsManagedShortcutsOverrideCache(
String defaultDialerPackageName, String defaultSmsPackageName) {
-
- List<String> shortcutOverrides = new ArrayList<>();
+ ArrayMap<String, String> shortcutOverrides = new ArrayMap<>();
if (defaultDialerPackageName != null) {
- shortcutOverrides.add(defaultDialerPackageName);
+ shortcutOverrides.put(defaultDialerPackageName, defaultDialerPackageName);
}
if (defaultSmsPackageName != null) {
- shortcutOverrides.add(defaultSmsPackageName);
+ shortcutOverrides.put(defaultSmsPackageName, defaultSmsPackageName);
}
mPolicyCache.setLauncherShortcutOverrides(shortcutOverrides);
}
@@ -23793,6 +23872,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
public DevicePolicyState getDevicePolicyState() {
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(MANAGE_PROFILE_AND_DEVICE_OWNERS));
+
return mInjector.binderWithCleanCallingIdentity(mDevicePolicyEngine::getDevicePolicyState);
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
index 638596b5cc20..43a2c9bbf5c5 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyDefinition.java
@@ -308,6 +308,13 @@ final class PolicyDefinition<V> {
DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY, accountType));
}
+ static PolicyDefinition<Set<String>> PERMITTED_INPUT_METHODS = new PolicyDefinition<>(
+ new NoArgsPolicyKey(DevicePolicyIdentifiers.PERMITTED_INPUT_METHODS_POLICY),
+ new MostRecent<>(),
+ POLICY_FLAG_LOCAL_ONLY_POLICY,
+ (Set<String> value, Context context, Integer userId, PolicyKey policyKey) -> true,
+ new StringSetPolicySerializer());
+
private static final Map<String, PolicyDefinition<?>> POLICY_DEFINITIONS = new HashMap<>();
private static Map<String, Integer> USER_RESTRICTION_FLAGS = new HashMap<>();
@@ -333,6 +340,8 @@ final class PolicyDefinition<V> {
GENERIC_APPLICATION_HIDDEN);
POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.ACCOUNT_MANAGEMENT_DISABLED_POLICY,
GENERIC_ACCOUNT_MANAGEMENT_DISABLED);
+ POLICY_DEFINITIONS.put(DevicePolicyIdentifiers.PERMITTED_INPUT_METHODS_POLICY,
+ PERMITTED_INPUT_METHODS);
// User Restriction Policies
USER_RESTRICTION_FLAGS.put(UserManager.DISALLOW_MODIFY_ACCOUNTS, /* flags= */ 0);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java
index 741f209a90c3..dd4c6afdcfb6 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyState.java
@@ -67,9 +67,8 @@ final class PolicyState<V> {
/**
* Returns {@code true} if the resolved policy has changed, {@code false} otherwise.
*/
- boolean addPolicy(@NonNull EnforcingAdmin admin, @NonNull PolicyValue<V> policy) {
+ boolean addPolicy(@NonNull EnforcingAdmin admin, @Nullable PolicyValue<V> policy) {
Objects.requireNonNull(admin);
- Objects.requireNonNull(policy);
//LinkedHashMap doesn't update the insertion order of existing keys, removing the existing
// key will cause it to update.
@@ -89,9 +88,9 @@ final class PolicyState<V> {
* Returns {@code true} if the resolved policy has changed, {@code false} otherwise.
*/
boolean addPolicy(
- @NonNull EnforcingAdmin admin, @NonNull PolicyValue<V> policy,
+ @NonNull EnforcingAdmin admin, @Nullable PolicyValue<V> policy,
LinkedHashMap<EnforcingAdmin, PolicyValue<V>> globalPoliciesSetByAdmins) {
- mPoliciesSetByAdmins.put(Objects.requireNonNull(admin), Objects.requireNonNull(policy));
+ mPoliciesSetByAdmins.put(Objects.requireNonNull(admin), policy);
return resolvePolicy(globalPoliciesSetByAdmins);
}
@@ -210,10 +209,12 @@ final class PolicyState<V> {
for (EnforcingAdmin admin : mPoliciesSetByAdmins.keySet()) {
serializer.startTag(/* namespace= */ null, TAG_ADMIN_POLICY_ENTRY);
- serializer.startTag(/* namespace= */ null, TAG_POLICY_VALUE_ENTRY);
- mPolicyDefinition.savePolicyValueToXml(
- serializer, mPoliciesSetByAdmins.get(admin).getValue());
- serializer.endTag(/* namespace= */ null, TAG_POLICY_VALUE_ENTRY);
+ if (mPoliciesSetByAdmins.get(admin) != null) {
+ serializer.startTag(/* namespace= */ null, TAG_POLICY_VALUE_ENTRY);
+ mPolicyDefinition.savePolicyValueToXml(
+ serializer, mPoliciesSetByAdmins.get(admin).getValue());
+ serializer.endTag(/* namespace= */ null, TAG_POLICY_VALUE_ENTRY);
+ }
serializer.startTag(/* namespace= */ null, TAG_ENFORCING_ADMIN_ENTRY);
admin.saveToXml(serializer);
@@ -250,7 +251,7 @@ final class PolicyState<V> {
break;
}
}
- if (admin != null && value != null) {
+ if (admin != null) {
policiesSetByAdmins.put(admin, value);
} else {
Log.e(TAG, "Error Parsing TAG_ADMIN_POLICY_ENTRY");
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index a5adf3f9bf80..f1d4de9369f0 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -54,6 +54,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_HIGH;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_ALLOW_LIST;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_COMPAT;
+import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_LISTENER;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_NOT_APPLICABLE;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION;
import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_POLICY_PERMISSION;
@@ -2728,6 +2729,66 @@ public final class AlarmManagerServiceTest {
}
@Test
+ public void exactListenerBinderCallWithoutPermissionWithoutAllowlist() throws RemoteException {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+ mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true);
+
+ mockScheduleExactAlarmState(false);
+ mockUseExactAlarmState(false);
+ when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(false);
+
+ final IAlarmListener listener = getNewListener(() -> {});
+ mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
+ 0, null, listener, "test-tag", null, null);
+
+ verify(mService, never()).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID);
+ verify(mService, never()).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE,
+ TEST_CALLING_UID);
+ verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt());
+
+ final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L),
+ isNull(), eq(listener), eq("test-tag"), eq(FLAG_STANDALONE), isNull(), isNull(),
+ eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(),
+ eq(EXACT_ALLOW_REASON_LISTENER));
+
+ final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue());
+ final int type = idleOptions.getTemporaryAppAllowlistType();
+ assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
+ }
+
+ @Test
+ public void exactAllowWhileIdleListenerBinderCallWithoutPermissionWithoutAllowlist()
+ throws RemoteException {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+ mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true);
+
+ mockScheduleExactAlarmState(false);
+ mockUseExactAlarmState(false);
+ when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(false);
+
+ final IAlarmListener listener = getNewListener(() -> {});
+ mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
+ FLAG_ALLOW_WHILE_IDLE, null, listener, "test-tag", null, null);
+
+ verify(mService, never()).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID);
+ verify(mService, never()).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE,
+ TEST_CALLING_UID);
+ verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt());
+
+ final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(mService).setImpl(eq(ELAPSED_REALTIME_WAKEUP), eq(1234L), eq(WINDOW_EXACT), eq(0L),
+ isNull(), eq(listener), eq("test-tag"),
+ eq(FLAG_STANDALONE | FLAG_ALLOW_WHILE_IDLE_COMPAT), isNull(), isNull(),
+ eq(TEST_CALLING_UID), eq(TEST_CALLING_PACKAGE), bundleCaptor.capture(),
+ eq(EXACT_ALLOW_REASON_LISTENER));
+
+ final BroadcastOptions idleOptions = new BroadcastOptions(bundleCaptor.getValue());
+ final int type = idleOptions.getTemporaryAppAllowlistType();
+ assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
+ }
+
+ @Test
public void inexactAllowWhileIdleBinderCall() throws RemoteException {
// Both permission and power exemption status don't matter for these alarms.
// We only want to test that the flags and idleOptions are correct.
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
index 3fb7fb4e6aea..acfea85d60a2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -40,6 +40,7 @@ import static com.android.server.am.BroadcastQueueTest.PACKAGE_YELLOW;
import static com.android.server.am.BroadcastQueueTest.getUidForPackage;
import static com.android.server.am.BroadcastQueueTest.makeManifestReceiver;
import static com.android.server.am.BroadcastQueueTest.withPriority;
+import static com.android.server.am.BroadcastRecord.isReceiverEquals;
import static com.google.common.truth.Truth.assertThat;
@@ -49,13 +50,16 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import android.annotation.NonNull;
@@ -116,6 +120,7 @@ public final class BroadcastQueueModernImplTest {
TestLooperManager mLooper;
BroadcastConstants mConstants;
+ private BroadcastSkipPolicy mSkipPolicy;
BroadcastQueueModernImpl mImpl;
BroadcastProcessQueue mHead;
@@ -139,29 +144,18 @@ public final class BroadcastQueueModernImplTest {
mConstants.DELAY_NORMAL_MILLIS = 10_000;
mConstants.DELAY_CACHED_MILLIS = 120_000;
- final BroadcastSkipPolicy emptySkipPolicy = new BroadcastSkipPolicy(mAms) {
- public boolean shouldSkip(BroadcastRecord r, Object o) {
- // Ignored
- return false;
- }
- public String shouldSkipMessage(BroadcastRecord r, Object o) {
- // Ignored
- return null;
- }
- public boolean disallowBackgroundStart(BroadcastRecord r) {
- // Ignored
- return false;
- }
- };
+ mSkipPolicy = spy(new BroadcastSkipPolicy(mAms));
+ doReturn(null).when(mSkipPolicy).shouldSkipMessage(any(), any());
+ doReturn(false).when(mSkipPolicy).disallowBackgroundStart(any());
+
final BroadcastHistory emptyHistory = new BroadcastHistory(mConstants) {
public void addBroadcastToHistoryLocked(BroadcastRecord original) {
// Ignored
}
};
-
mImpl = new BroadcastQueueModernImpl(mAms, mHandlerThread.getThreadHandler(),
- mConstants, mConstants, emptySkipPolicy, emptyHistory);
+ mConstants, mConstants, mSkipPolicy, emptyHistory);
doReturn(1L).when(mQueue1).getRunnableAt();
doReturn(2L).when(mQueue2).getRunnableAt();
@@ -256,17 +250,12 @@ public final class BroadcastQueueModernImplTest {
private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue,
BroadcastRecord record, int recordIndex) {
- enqueueOrReplaceBroadcast(queue, record, recordIndex, false, 42_000_000L);
+ enqueueOrReplaceBroadcast(queue, record, recordIndex, 42_000_000L);
}
private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue,
BroadcastRecord record, int recordIndex, long enqueueTime) {
- enqueueOrReplaceBroadcast(queue, record, recordIndex, false, enqueueTime);
- }
-
- private void enqueueOrReplaceBroadcast(BroadcastProcessQueue queue,
- BroadcastRecord record, int recordIndex, boolean wouldBeSkipped, long enqueueTime) {
- queue.enqueueOrReplaceBroadcast(record, recordIndex, wouldBeSkipped, (r, i) -> {
+ queue.enqueueOrReplaceBroadcast(record, recordIndex, (r, i) -> {
throw new UnsupportedOperationException();
});
record.enqueueTime = enqueueTime;
@@ -1199,6 +1188,42 @@ public final class BroadcastQueueModernImplTest {
assertEquals(ProcessList.SCHED_GROUP_DEFAULT, queue.getPreferredSchedulingGroupLocked());
}
+ @Test
+ public void testSkipPolicy_atEnqueueTime() throws Exception {
+ final Intent userPresent = new Intent(Intent.ACTION_USER_PRESENT);
+ final Object greenReceiver = makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN);
+ final Object redReceiver = makeManifestReceiver(PACKAGE_RED, CLASS_RED);
+
+ final BroadcastRecord userPresentRecord = makeBroadcastRecord(userPresent,
+ List.of(greenReceiver, redReceiver));
+
+ final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK);
+ final BroadcastRecord timeTickRecord = makeBroadcastRecord(timeTick,
+ List.of(greenReceiver, redReceiver));
+
+ doAnswer(invocation -> {
+ final BroadcastRecord r = invocation.getArgument(0);
+ final Object o = invocation.getArgument(1);
+ if (userPresent.getAction().equals(r.intent.getAction())
+ && isReceiverEquals(o, greenReceiver)) {
+ return "receiver skipped by test";
+ }
+ return null;
+ }).when(mSkipPolicy).shouldSkipMessage(any(BroadcastRecord.class), any());
+
+ mImpl.enqueueBroadcastLocked(userPresentRecord);
+ mImpl.enqueueBroadcastLocked(timeTickRecord);
+
+ final BroadcastProcessQueue greenQueue = mImpl.getProcessQueue(PACKAGE_GREEN,
+ getUidForPackage(PACKAGE_GREEN));
+ // There should be only one broadcast for green process as the other would have
+ // been skipped.
+ verifyPendingRecords(greenQueue, List.of(timeTick));
+ final BroadcastProcessQueue redQueue = mImpl.getProcessQueue(PACKAGE_RED,
+ getUidForPackage(PACKAGE_RED));
+ verifyPendingRecords(redQueue, List.of(userPresent, timeTick));
+ }
+
private Intent createPackageChangedIntent(int uid, List<String> componentNameList) {
final Intent packageChangedIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED);
packageChangedIntent.putExtra(Intent.EXTRA_UID, uid);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
index 96eca7171af0..8cfc150afe56 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityManagerServiceTest.java
@@ -281,8 +281,8 @@ public class AccessibilityManagerServiceTest {
@Test
public void testRegisterProxy() throws Exception {
mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY);
- verify(mProxyManager).registerProxy(eq(mMockServiceClient), eq(TEST_DISPLAY),
- eq(mTestableContext), anyInt(), any(), eq(mMockSecurityPolicy),
+ verify(mProxyManager).registerProxy(eq(mMockServiceClient), eq(TEST_DISPLAY), anyInt(),
+ eq(mMockSecurityPolicy),
eq(mA11yms), eq(mA11yms.getTraceManager()),
eq(mMockWindowManagerService));
}
@@ -295,7 +295,7 @@ public class AccessibilityManagerServiceTest {
assertThrows(SecurityException.class,
() -> mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY));
- verify(mProxyManager, never()).registerProxy(any(), anyInt(), any(), anyInt(), any(), any(),
+ verify(mProxyManager, never()).registerProxy(any(), anyInt(), anyInt(), any(),
any(), any(), any());
}
@@ -307,7 +307,7 @@ public class AccessibilityManagerServiceTest {
assertThrows(SecurityException.class,
() -> mA11yms.registerProxyForDisplay(mMockServiceClient, TEST_DISPLAY));
- verify(mProxyManager, never()).registerProxy(any(), anyInt(), any(), anyInt(), any(), any(),
+ verify(mProxyManager, never()).registerProxy(any(), anyInt(), anyInt(), any(),
any(), any(), any());
}
@@ -316,7 +316,7 @@ public class AccessibilityManagerServiceTest {
public void testRegisterProxyForDefaultDisplay() throws Exception {
assertThrows(IllegalArgumentException.class,
() -> mA11yms.registerProxyForDisplay(mMockServiceClient, Display.DEFAULT_DISPLAY));
- verify(mProxyManager, never()).registerProxy(any(), anyInt(), any(), anyInt(), any(), any(),
+ verify(mProxyManager, never()).registerProxy(any(), anyInt(), anyInt(), any(),
any(), any(), any());
}
@@ -325,7 +325,7 @@ public class AccessibilityManagerServiceTest {
public void testRegisterProxyForInvalidDisplay() throws Exception {
assertThrows(IllegalArgumentException.class,
() -> mA11yms.registerProxyForDisplay(mMockServiceClient, Display.INVALID_DISPLAY));
- verify(mProxyManager, never()).registerProxy(any(), anyInt(), any(), anyInt(), any(), any(),
+ verify(mProxyManager, never()).registerProxy(any(), anyInt(), anyInt(), any(),
any(), any(), any());
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java
index eb6670ee964c..8f0d0144a40e 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilitySecurityPolicyTest.java
@@ -146,7 +146,7 @@ public class AccessibilitySecurityPolicyTest {
@Mock
private PolicyWarningUIController mPolicyWarningUIController;
@Mock
- private PackageManagerInternal mPackageManagerInternal;
+ private PackageManagerInternal mMockPackageManagerInternal;
@Before
public void setUp() {
@@ -158,7 +158,8 @@ public class AccessibilitySecurityPolicyTest {
R.dimen.accessibility_focus_highlight_stroke_width, 1);
mA11ySecurityPolicy = new AccessibilitySecurityPolicy(
- mPolicyWarningUIController, mContext, mMockA11yUserManager);
+ mPolicyWarningUIController, mContext, mMockA11yUserManager,
+ mMockPackageManagerInternal);
mA11ySecurityPolicy.setSendingNonA11yToolNotificationLocked(true);
mA11ySecurityPolicy.setAccessibilityWindowManager(mMockA11yWindowManager);
mA11ySecurityPolicy.setAppWidgetManager(mMockAppWidgetManager);
@@ -237,8 +238,8 @@ public class AccessibilitySecurityPolicyTest {
@Test
public void resolveValidReportedPackage_uidAndPkgNameMatched_returnPkgName()
throws PackageManager.NameNotFoundException {
- when(mMockPackageManager.getPackageUidAsUser(PACKAGE_NAME,
- PackageManager.MATCH_ANY_USER, TEST_USER_ID)).thenReturn(APP_UID);
+ when(mMockPackageManagerInternal.isSameApp(PACKAGE_NAME, APP_UID, TEST_USER_ID))
+ .thenReturn(true);
assertEquals(mA11ySecurityPolicy.resolveValidReportedPackageLocked(
PACKAGE_NAME, APP_UID, TEST_USER_ID, APP_PID),
@@ -257,8 +258,8 @@ public class AccessibilitySecurityPolicyTest {
when(mMockAppWidgetManager.getHostedWidgetPackages(widgetHostUid))
.thenReturn(widgetPackages);
- when(mMockPackageManager.getPackageUidAsUser(hostPackageName, TEST_USER_ID))
- .thenReturn(widgetHostUid);
+ when(mMockPackageManagerInternal.isSameApp(hostPackageName, widgetHostUid, TEST_USER_ID))
+ .thenReturn(true);
assertEquals(mA11ySecurityPolicy.resolveValidReportedPackageLocked(
widgetPackageName, widgetHostUid, TEST_USER_ID, widgetHostPid),
@@ -272,8 +273,8 @@ public class AccessibilitySecurityPolicyTest {
final String[] uidPackages = {PACKAGE_NAME, PACKAGE_NAME2};
when(mMockPackageManager.getPackagesForUid(APP_UID))
.thenReturn(uidPackages);
- when(mMockPackageManager.getPackageUidAsUser(invalidPackageName, TEST_USER_ID))
- .thenThrow(PackageManager.NameNotFoundException.class);
+ when(mMockPackageManagerInternal.isSameApp(invalidPackageName, APP_UID, TEST_USER_ID))
+ .thenReturn(false);
when(mMockAppWidgetManager.getHostedWidgetPackages(APP_UID))
.thenReturn(new ArraySet<>());
mContext.getTestablePermissions().setPermission(
@@ -292,8 +293,8 @@ public class AccessibilitySecurityPolicyTest {
final String[] uidPackages = {PACKAGE_NAME};
when(mMockPackageManager.getPackagesForUid(APP_UID))
.thenReturn(uidPackages);
- when(mMockPackageManager.getPackageUidAsUser(wantedPackageName, TEST_USER_ID))
- .thenReturn(wantedUid);
+ when(mMockPackageManagerInternal.isSameApp(wantedPackageName, wantedUid, TEST_USER_ID))
+ .thenReturn(true);
when(mMockAppWidgetManager.getHostedWidgetPackages(APP_UID))
.thenReturn(new ArraySet<>());
mContext.getTestablePermissions().setPermission(
@@ -312,8 +313,8 @@ public class AccessibilitySecurityPolicyTest {
final String[] uidPackages = {PACKAGE_NAME};
when(mMockPackageManager.getPackagesForUid(APP_UID))
.thenReturn(uidPackages);
- when(mMockPackageManager.getPackageUidAsUser(wantedPackageName, TEST_USER_ID))
- .thenReturn(wantedUid);
+ when(mMockPackageManagerInternal.isSameApp(wantedPackageName, wantedUid, TEST_USER_ID))
+ .thenReturn(true);
when(mMockAppWidgetManager.getHostedWidgetPackages(APP_UID))
.thenReturn(new ArraySet<>());
mContext.getTestablePermissions().setPermission(
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/ProxyAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/ProxyAccessibilityServiceConnectionTest.java
index dd44a7968639..6ac3658bc3b4 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/ProxyAccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/ProxyAccessibilityServiceConnectionTest.java
@@ -29,12 +29,14 @@ import android.accessibilityservice.AccessibilityTrace;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Color;
import android.os.Handler;
import android.view.accessibility.AccessibilityEvent;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -79,12 +81,15 @@ public class ProxyAccessibilityServiceConnectionTest {
WindowManagerInternal mMockWindowManagerInternal;
ProxyAccessibilityServiceConnection mProxyConnection;
AccessibilityServiceInfo mAccessibilityServiceInfo;
+ private int mFocusStrokeWidthDefaultValue;
+ private int mFocusColorDefaultValue;
@Before
public void setup() {
final Resources resources = getInstrumentation().getContext().getResources();
MockitoAnnotations.initMocks(this);
when(mMockContext.getResources()).thenReturn(resources);
+ when(mMockSecurityPolicy.checkAccessibilityAccess(any())).thenReturn(true);
mAccessibilityServiceInfo = new AccessibilityServiceInfo();
mProxyConnection = new ProxyAccessibilityServiceConnection(mMockContext, COMPONENT_NAME,
@@ -92,10 +97,13 @@ public class ProxyAccessibilityServiceConnectionTest {
getInstrumentation().getContext().getMainLooper()),
mMockLock, mMockSecurityPolicy, mMockSystemSupport, mMockA11yTrace,
mMockWindowManagerInternal, mMockA11yWindowManager, DISPLAY_ID, DEVICE_ID);
+
+ mFocusStrokeWidthDefaultValue = mProxyConnection.getFocusStrokeWidthLocked();
+ mFocusColorDefaultValue = mProxyConnection.getFocusColorLocked();
}
@Test
- public void testSetInstalledAndEnabledServices_clientChanged() {
+ public void testSetInstalledAndEnabledServices_updateInfos_notifiesSystemOfProxyChange() {
final List<AccessibilityServiceInfo> infos = new ArrayList<>();
final AccessibilityServiceInfo info1 = new AccessibilityServiceInfo();
infos.add(info1);
@@ -106,6 +114,17 @@ public class ProxyAccessibilityServiceConnectionTest {
}
@Test
+ public void testSetFocusAppearance_updateAppearance_notifiesSystemOfProxyChange() {
+ final int updatedWidth = mFocusStrokeWidthDefaultValue + 10;
+ final int updatedColor = mFocusColorDefaultValue
+ == Color.BLUE ? Color.RED : Color.BLUE;
+
+ mProxyConnection.setFocusAppearance(updatedWidth, updatedColor);
+
+ verify(mMockSystemSupport).onProxyChanged(DEVICE_ID);
+ }
+
+ @Test
public void testSetInstalledAndEnabledServices_returnList() {
final List<AccessibilityServiceInfo> infos = new ArrayList<>();
final AccessibilityServiceInfo info1 = new AccessibilityServiceInfo();
@@ -196,7 +215,7 @@ public class ProxyAccessibilityServiceConnectionTest {
}
@Test
- public void testSetServiceInfo_setIllegalOperationExceptionThrown_() {
+ public void testSetServiceInfo_setIllegalOperationExceptionThrown() {
UnsupportedOperationException thrown =
assertThrows(
UnsupportedOperationException.class,
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java
new file mode 100644
index 000000000000..6c7b995d07a2
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.accessibility;
+
+import static com.android.server.accessibility.ProxyAccessibilityServiceConnectionTest.INTERACTIVE_UI_TIMEOUT_100MS;
+import static com.android.server.accessibility.ProxyAccessibilityServiceConnectionTest.INTERACTIVE_UI_TIMEOUT_200MS;
+import static com.android.server.accessibility.ProxyAccessibilityServiceConnectionTest.NON_INTERACTIVE_UI_TIMEOUT_100MS;
+import static com.android.server.accessibility.ProxyAccessibilityServiceConnectionTest.NON_INTERACTIVE_UI_TIMEOUT_200MS;
+import static com.android.server.accessibility.ProxyManager.PROXY_COMPONENT_CLASS_NAME;
+import static com.android.server.accessibility.ProxyManager.PROXY_COMPONENT_PACKAGE_NAME;
+
+import static org.junit.Assert.fail;
+
+import android.accessibilityservice.AccessibilityGestureEvent;
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.accessibilityservice.AccessibilityTrace;
+import android.accessibilityservice.IAccessibilityServiceClient;
+import android.accessibilityservice.IAccessibilityServiceConnection;
+import android.accessibilityservice.MagnificationConfig;
+import android.companion.virtual.IVirtualDeviceManager;
+import android.companion.virtual.VirtualDeviceManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Region;
+import android.os.IBinder;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
+import android.util.ArraySet;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+import android.view.accessibility.IAccessibilityManagerClient;
+import android.view.inputmethod.EditorInfo;
+
+import com.android.internal.R;
+import com.android.internal.inputmethod.IAccessibilityInputMethodSession;
+import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback;
+import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
+import com.android.internal.util.IntPair;
+import com.android.server.LocalServices;
+import com.android.server.accessibility.test.MessageCapturingHandler;
+import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
+import com.android.server.wm.WindowManagerInternal;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.InstrumentationRegistry;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Tests for ProxyManager.
+ */
+public class ProxyManagerTest {
+ private static final int DISPLAY_ID = 1000;
+ private static final int DISPLAY_2_ID = 1001;
+ private static final int DEVICE_ID = 10;
+ private static final int STREAMED_CALLING_UID = 9876;
+
+ @Mock private Context mMockContext;
+ @Mock private AccessibilitySecurityPolicy mMockSecurityPolicy;
+ @Mock private AccessibilityWindowManager mMockA11yWindowManager;
+ @Mock private ProxyManager.SystemSupport mMockProxySystemSupport;
+ @Mock private AbstractAccessibilityServiceConnection.SystemSupport mMockConnectionSystemSupport;
+ @Mock private AccessibilityTrace mMockA11yTrace;
+ @Mock private WindowManagerInternal mMockWindowManagerInternal;
+ @Mock private IAccessibilityServiceClient mMockAccessibilityServiceClient;
+ @Mock private IBinder mMockServiceAsBinder;
+ @Mock private VirtualDeviceManagerInternal mMockVirtualDeviceManagerInternal;
+ @Mock private IVirtualDeviceManager mMockIVirtualDeviceManager;
+
+ private int mFocusStrokeWidthDefaultValue;
+ private int mFocusColorDefaultValue;
+
+ private MessageCapturingHandler mMessageCapturingHandler = new MessageCapturingHandler(null);
+ private ProxyManager mProxyManager;
+
+ @Before
+ public void setup() throws RemoteException {
+ MockitoAnnotations.initMocks(this);
+ final Resources resources = InstrumentationRegistry.getContext().getResources();
+
+ mFocusStrokeWidthDefaultValue =
+ resources.getDimensionPixelSize(R.dimen.accessibility_focus_highlight_stroke_width);
+ mFocusColorDefaultValue = resources.getColor(R.color.accessibility_focus_highlight_color);
+ when(mMockContext.getResources()).thenReturn(resources);
+
+ when(mMockVirtualDeviceManagerInternal.getDeviceIdsForUid(anyInt())).thenReturn(
+ new ArraySet(Set.of(DEVICE_ID)));
+ LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class);
+ LocalServices.addService(VirtualDeviceManagerInternal.class,
+ mMockVirtualDeviceManagerInternal);
+
+ when(mMockIVirtualDeviceManager.getDeviceIdForDisplayId(anyInt())).thenReturn(DEVICE_ID);
+ final VirtualDeviceManager virtualDeviceManager =
+ new VirtualDeviceManager(mMockIVirtualDeviceManager, mMockContext);
+ when(mMockContext.getSystemServiceName(VirtualDeviceManager.class)).thenReturn(
+ Context.VIRTUAL_DEVICE_SERVICE);
+ when(mMockContext.getSystemService(VirtualDeviceManager.class))
+ .thenReturn(virtualDeviceManager);
+
+ when(mMockA11yTrace.isA11yTracingEnabled()).thenReturn(false);
+
+ final RemoteCallbackList<IAccessibilityManagerClient> userClients =
+ new RemoteCallbackList<>();
+ final RemoteCallbackList<IAccessibilityManagerClient> globalClients =
+ new RemoteCallbackList<>();
+ when(mMockProxySystemSupport.getCurrentUserClientsLocked()).thenReturn(userClients);
+ when(mMockProxySystemSupport.getGlobalClientsLocked()).thenReturn(globalClients);
+
+ when(mMockAccessibilityServiceClient.asBinder()).thenReturn(mMockServiceAsBinder);
+
+ mProxyManager = new ProxyManager(new Object(), mMockA11yWindowManager, mMockContext,
+ mMessageCapturingHandler, new UiAutomationManager(new Object()),
+ mMockProxySystemSupport);
+ }
+
+ @After
+ public void tearDown() {
+ mMessageCapturingHandler.removeAllMessages();
+ }
+
+ /**
+ * Tests that the proxy’s backing AccessibilityServiceClient is initialized when registering a
+ * proxy.
+ */
+ @Test
+ public void registerProxy_always_connectsServiceClient() throws RemoteException {
+ registerProxy(DISPLAY_ID);
+ verify(mMockAccessibilityServiceClient).init(any(), anyInt(), any());
+ }
+
+ /** Tests that unregistering a proxy removes its display from tracking. */
+ @Test
+ public void unregisterProxy_always_stopsTrackingDisplay() {
+ registerProxy(DISPLAY_ID);
+
+ mProxyManager.unregisterProxy(DISPLAY_ID);
+
+ verify(mMockA11yWindowManager).stopTrackingDisplayProxy(DISPLAY_ID);
+ assertThat(mProxyManager.isProxyedDisplay(DISPLAY_ID)).isFalse();
+ }
+ /**
+ * Tests that unregistering a proxied display of a virtual device, where that virtual device
+ * owned only that one proxied display, removes the device from tracking.
+ */
+ @Test
+ public void unregisterProxy_deviceAssociatedWithSingleDisplay_stopsTrackingDevice() {
+ registerProxy(DISPLAY_ID);
+
+ mProxyManager.unregisterProxy(DISPLAY_ID);
+
+ assertThat(mProxyManager.isProxyedDeviceId(DEVICE_ID)).isFalse();
+ verify(mMockProxySystemSupport).removeDeviceIdLocked(DEVICE_ID);
+ }
+
+ /**
+ * Tests that unregistering a proxied display of a virtual device, where that virtual device
+ * owns more than one proxied display, does not remove the device from tracking.
+ */
+ @Test
+ public void unregisterProxy_deviceAssociatedWithMultipleDisplays_tracksRemainingProxy() {
+ registerProxy(DISPLAY_ID);
+ registerProxy(DISPLAY_2_ID);
+
+ mProxyManager.unregisterProxy(DISPLAY_ID);
+
+ assertThat(mProxyManager.isProxyedDeviceId(DEVICE_ID)).isTrue();
+ verify(mMockProxySystemSupport, never()).removeDeviceIdLocked(DEVICE_ID);
+ }
+
+ /**
+ * Tests that changing a proxy, e.g. registering/unregistering a proxy or updating its service
+ * info, notifies the apps being streamed and AccessibilityManagerService.
+ */
+ @Test
+ public void testOnProxyChanged_always_propagatesChange() {
+ registerProxy(DISPLAY_ID);
+ mMessageCapturingHandler.sendAllMessages();
+
+ mProxyManager.onProxyChanged(DEVICE_ID);
+
+ // Messages to notify IAccessibilityManagerClients should be posted.
+ assertThat(mMessageCapturingHandler.hasMessages()).isTrue();
+
+ verify(mMockProxySystemSupport).updateWindowsForAccessibilityCallbackLocked();
+ verify(mMockProxySystemSupport).notifyClearAccessibilityCacheLocked();
+ }
+
+ /**
+ * Tests that getting the first device id for an app uid, such as when an app queries for
+ * device-specific state, returns the right device id.
+ */
+ @Test
+ public void testGetFirstDeviceForUid_streamedAppQueriesState_getsHostDeviceId() {
+ registerProxy(DISPLAY_ID);
+ assertThat(mProxyManager.getFirstDeviceIdForUidLocked(STREAMED_CALLING_UID))
+ .isEqualTo(DEVICE_ID);
+ }
+
+ /**
+ * Tests that the app client state retrieved for a device reflects that touch exploration is
+ * enabled since a proxy info has requested touch exploration.
+ */
+ @Test
+ public void testGetClientState_proxyWantsTouchExploration_returnsTouchExplorationEnabled() {
+ registerProxy(DISPLAY_ID);
+
+ final AccessibilityServiceInfo secondDisplayInfo = new AccessibilityServiceInfo();
+ secondDisplayInfo.flags |= AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
+ AccessibilityServiceClientImpl client = new AccessibilityServiceClientImpl(
+ secondDisplayInfo);
+ registerProxy(DISPLAY_2_ID, client);
+
+ final int deviceClientState = mProxyManager.getStateLocked(DEVICE_ID);
+ assertThat((deviceClientState
+ & AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0).isTrue();
+ }
+
+ /**
+ * Tests that the highest interactive and non-interactive timeout is returned if there are
+ * multiple proxied displays belonging to a device.
+ */
+ @Test
+ public void testGetRecommendedTimeout_multipleProxies_returnsHighestTimeout() {
+ final AccessibilityServiceInfo firstDisplayInfo = new AccessibilityServiceInfo();
+ firstDisplayInfo.setInteractiveUiTimeoutMillis(INTERACTIVE_UI_TIMEOUT_100MS);
+ firstDisplayInfo.setNonInteractiveUiTimeoutMillis(NON_INTERACTIVE_UI_TIMEOUT_200MS);
+
+ final AccessibilityServiceInfo secondDisplayInfo = new AccessibilityServiceInfo();
+ secondDisplayInfo.setInteractiveUiTimeoutMillis(INTERACTIVE_UI_TIMEOUT_200MS);
+ secondDisplayInfo.setNonInteractiveUiTimeoutMillis(NON_INTERACTIVE_UI_TIMEOUT_100MS);
+
+ registerProxy(DISPLAY_ID, new AccessibilityServiceClientImpl(firstDisplayInfo));
+ registerProxy(DISPLAY_2_ID, new AccessibilityServiceClientImpl(secondDisplayInfo));
+
+ final long timeout = mProxyManager.getRecommendedTimeoutMillisLocked(DEVICE_ID);
+ final int interactiveTimeout = IntPair.first(timeout);
+ final int nonInteractiveTimeout = IntPair.second(timeout);
+
+ assertThat(interactiveTimeout).isEqualTo(INTERACTIVE_UI_TIMEOUT_200MS);
+ assertThat(nonInteractiveTimeout).isEqualTo(NON_INTERACTIVE_UI_TIMEOUT_200MS);
+ }
+ /**
+ * Tests that getting the installed and enabled services returns the info of the registered
+ * proxy. (The component name reflects the display id.)
+ */
+ @Test
+ public void testGetInstalledAndEnabledServices_defaultInfo_returnsInfoForDisplayId() {
+ final AccessibilityServiceInfo info = new AccessibilityServiceInfo();
+ registerProxy(DISPLAY_ID, new AccessibilityServiceClientImpl(info));
+ final List<AccessibilityServiceInfo> installedAndEnabledServices =
+ mProxyManager.getInstalledAndEnabledServiceInfosLocked(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK, DEVICE_ID);
+ assertThat(installedAndEnabledServices.size()).isEqualTo(1);
+ AccessibilityServiceInfo proxyInfo = installedAndEnabledServices.get(0);
+
+ assertThat(proxyInfo.getComponentName()).isEqualTo(new ComponentName(
+ PROXY_COMPONENT_PACKAGE_NAME, PROXY_COMPONENT_CLASS_NAME + DISPLAY_ID));
+ }
+
+ /**
+ * Tests that the app client state retrieved for a device reflects that accessibility is
+ * enabled.
+ */
+ @Test
+ public void testGetClientState_always_returnsAccessibilityEnabled() {
+ registerProxy(DISPLAY_ID);
+
+ final int deviceClientState = mProxyManager.getStateLocked(DEVICE_ID);
+ assertThat((deviceClientState
+ & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0).isTrue();
+ }
+
+ /**
+ * Tests that the manager can retrieve interactive windows if a proxy sets
+ * AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS.
+ */
+ @Test
+ public void testCanRetrieveInteractiveWindows_atLeastOneProxyWantsWindows_returnsTrue() {
+ registerProxy(DISPLAY_ID);
+
+ final AccessibilityServiceInfo secondDisplayInfo = new AccessibilityServiceInfo();
+ secondDisplayInfo.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
+ registerProxy(DISPLAY_2_ID, new AccessibilityServiceClientImpl(secondDisplayInfo));
+
+ assertThat(mProxyManager.canRetrieveInteractiveWindowsLocked()).isTrue();
+ }
+
+ /**
+ * Tests that getting service interfaces to interrupt when AccessibilityManager#interrupt
+ * returns the registered proxy interface.
+ */
+ @Test
+ public void testGetServiceInterfacesForInterrupt_defaultProxy_returnsProxyInterface() {
+ registerProxy(DISPLAY_ID);
+ final List<IAccessibilityServiceClient> interfacesToInterrupt = new ArrayList<>();
+ mProxyManager.addServiceInterfacesLocked(interfacesToInterrupt, DEVICE_ID);
+
+ assertThat(interfacesToInterrupt.size()).isEqualTo(1);
+ assertThat(interfacesToInterrupt.get(0).asBinder()).isEqualTo(mMockServiceAsBinder);
+ }
+
+ /** Tests that the default timeout (0) is returned when the proxy is registered. */
+ @Test
+ public void getRecommendedTimeout_defaultProxyInfo_getsDefaultTimeout() {
+ registerProxy(DISPLAY_ID);
+ final long timeout = mProxyManager.getRecommendedTimeoutMillisLocked(DEVICE_ID);
+ final int interactiveTimeout = IntPair.first(timeout);
+ final int nonInteractiveTimeout = IntPair.second(timeout);
+
+ assertThat(interactiveTimeout).isEqualTo(0);
+ assertThat(nonInteractiveTimeout).isEqualTo(0);
+ }
+
+ /** Tests that the manager returns the updated timeout when the proxy’s timeout is updated. */
+ @Test
+ public void getRecommendedTimeout_updateTimeout_getsUpdatedTimeout() {
+ registerProxy(DISPLAY_ID);
+
+ mProxyManager.updateTimeoutsIfNeeded(NON_INTERACTIVE_UI_TIMEOUT_100MS,
+ INTERACTIVE_UI_TIMEOUT_200MS);
+
+ final long updatedTimeout = mProxyManager.getRecommendedTimeoutMillisLocked(DEVICE_ID);
+ final int updatedInteractiveTimeout = IntPair.first(updatedTimeout);
+ final int updatedNonInteractiveTimeout = IntPair.second(updatedTimeout);
+
+ assertThat(updatedInteractiveTimeout).isEqualTo(INTERACTIVE_UI_TIMEOUT_200MS);
+ assertThat(updatedNonInteractiveTimeout).isEqualTo(NON_INTERACTIVE_UI_TIMEOUT_100MS);
+ }
+
+ /** Tests that the system’s default focus color is returned. */
+ @Test
+ public void testGetFocusColor_defaultProxy_getsDefaultSystemColor() {
+ registerProxy(DISPLAY_ID);
+ final int focusColor = mProxyManager.getFocusColorLocked(DEVICE_ID);
+ assertThat(focusColor).isEqualTo(mFocusColorDefaultValue);
+ }
+
+ /** Tests that the system’s default focus stroke width is returned. */
+ @Test
+ public void testGetFocusStrokeWidth_defaultProxy_getsDefaultSystemWidth() {
+ registerProxy(DISPLAY_ID);
+ final int focusStrokeWidth = mProxyManager.getFocusStrokeWidthLocked(DEVICE_ID);
+ assertThat(focusStrokeWidth).isEqualTo(mFocusStrokeWidthDefaultValue);
+ }
+
+ private void registerProxy(int displayId) {
+ try {
+ mProxyManager.registerProxy(mMockAccessibilityServiceClient, displayId, anyInt(),
+ mMockSecurityPolicy, mMockConnectionSystemSupport,
+ mMockA11yTrace, mMockWindowManagerInternal);
+ } catch (RemoteException e) {
+ fail("Failed to register proxy " + e);
+ }
+ }
+
+ private void registerProxy(int displayId, AccessibilityServiceClientImpl serviceClient) {
+ try {
+ mProxyManager.registerProxy(serviceClient, displayId, anyInt(),
+ mMockSecurityPolicy, mMockConnectionSystemSupport,
+ mMockA11yTrace, mMockWindowManagerInternal);
+ } catch (RemoteException e) {
+ fail("Failed to register proxy " + e);
+ }
+ }
+
+ /**
+ * IAccessibilityServiceClient implementation.
+ * A proxy connection does not populate non-default AccessibilityServiceInfo values until the
+ * proxy is connected in A11yDisplayProxy#onServiceConnected. For tests that check for
+ * non-default values, populate immediately in this testing class, since a real Service is not
+ * being used and connected.
+ */
+ static class AccessibilityServiceClientImpl extends IAccessibilityServiceClient.Stub {
+ List<AccessibilityServiceInfo> mInstalledAndEnabledServices;
+
+ AccessibilityServiceClientImpl(AccessibilityServiceInfo
+ installedAndEnabledService) {
+ mInstalledAndEnabledServices = List.of(installedAndEnabledService);
+ }
+
+ @Override
+ public void init(IAccessibilityServiceConnection connection, int connectionId,
+ IBinder windowToken) throws RemoteException {
+ connection.setInstalledAndEnabledServices(mInstalledAndEnabledServices);
+ }
+
+ @Override
+ public void onAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void onInterrupt() throws RemoteException {
+
+ }
+
+ @Override
+ public void onGesture(AccessibilityGestureEvent gestureEvent) throws RemoteException {
+
+ }
+
+ @Override
+ public void clearAccessibilityCache() throws RemoteException {
+
+ }
+
+ @Override
+ public void onKeyEvent(KeyEvent event, int sequence) throws RemoteException {
+
+ }
+
+ @Override
+ public void onMagnificationChanged(int displayId, Region region, MagnificationConfig config)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void onMotionEvent(MotionEvent event) throws RemoteException {
+
+ }
+
+ @Override
+ public void onTouchStateChanged(int displayId, int state) throws RemoteException {
+
+ }
+
+ @Override
+ public void onSoftKeyboardShowModeChanged(int showMode) throws RemoteException {
+
+ }
+
+ @Override
+ public void onPerformGestureResult(int sequence, boolean completedSuccessfully)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void onFingerprintCapturingGesturesChanged(boolean capturing)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void onFingerprintGesture(int gesture) throws RemoteException {
+
+ }
+
+ @Override
+ public void onAccessibilityButtonClicked(int displayId) throws RemoteException {
+
+ }
+
+ @Override
+ public void onAccessibilityButtonAvailabilityChanged(boolean available)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void onSystemActionsChanged() throws RemoteException {
+
+ }
+
+ @Override
+ public void createImeSession(IAccessibilityInputMethodSessionCallback callback)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void setImeSessionEnabled(IAccessibilityInputMethodSession session, boolean enabled)
+ throws RemoteException {
+
+ }
+
+ @Override
+ public void bindInput() throws RemoteException {
+
+ }
+
+ @Override
+ public void unbindInput() throws RemoteException {
+
+ }
+
+ @Override
+ public void startInput(IRemoteAccessibilityInputConnection connection,
+ EditorInfo editorInfo, boolean restarting) throws RemoteException {
+
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
index d7b12e031c35..e6d3bbc53c83 100644
--- a/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/brightness/DisplayBrightnessControllerTest.java
@@ -19,10 +19,13 @@ package com.android.server.display.brightness;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -66,25 +69,27 @@ public final class DisplayBrightnessControllerTest {
@Mock
private HandlerExecutor mBrightnessChangeExecutor;
+ private final DisplayBrightnessController.Injector mInjector = new
+ DisplayBrightnessController.Injector() {
+ @Override
+ DisplayBrightnessStrategySelector getDisplayBrightnessStrategySelector(
+ Context context, int displayId) {
+ return mDisplayBrightnessStrategySelector;
+ }
+ };
+
private DisplayBrightnessController mDisplayBrightnessController;
@Before
public void before() {
MockitoAnnotations.initMocks(this);
when(mContext.getResources()).thenReturn(mResources);
- DisplayBrightnessController.Injector injector = new DisplayBrightnessController.Injector() {
- @Override
- DisplayBrightnessStrategySelector getDisplayBrightnessStrategySelector(
- Context context, int displayId) {
- return mDisplayBrightnessStrategySelector;
- }
- };
when(mBrightnessSetting.getBrightness()).thenReturn(Float.NaN);
when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(-1f);
when(mResources.getBoolean(
com.android.internal.R.bool.config_persistBrightnessNitsForDefaultDisplay))
.thenReturn(true);
- mDisplayBrightnessController = new DisplayBrightnessController(mContext, injector,
+ mDisplayBrightnessController = new DisplayBrightnessController(mContext, mInjector,
DISPLAY_ID, DEFAULT_BRIGHTNESS, mBrightnessSetting, mOnBrightnessChangeRunnable,
mBrightnessChangeExecutor);
}
@@ -257,27 +262,6 @@ public final class DisplayBrightnessControllerTest {
}
@Test
- public void testBrightnessNitsForDefaultDisplay() {
- float brightness = 0.3f;
- float nits = 500;
- AutomaticBrightnessController automaticBrightnessController =
- mock(AutomaticBrightnessController.class);
- when(automaticBrightnessController.convertToFloatScale(nits)).thenReturn(brightness);
- when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits);
-
- mDisplayBrightnessController.setAutomaticBrightnessController(
- automaticBrightnessController);
- assertEquals(brightness, mDisplayBrightnessController.getCurrentBrightness(),
- /* delta= */ 0);
-
- float newBrightness = 0.5f;
- float newNits = 700;
- when(automaticBrightnessController.convertToNits(newBrightness)).thenReturn(newNits);
- mDisplayBrightnessController.setBrightness(newBrightness);
- verify(mBrightnessSetting).setBrightnessNitsForDefaultDisplay(newNits);
- }
-
- @Test
public void testConvertToNits() {
final float brightness = 0.5f;
final float nits = 300;
@@ -330,4 +314,48 @@ public final class DisplayBrightnessControllerTest {
mDisplayBrightnessController.stop();
verify(mBrightnessSetting).unregisterListener(brightnessSettingListener);
}
+
+ @Test
+ public void testLoadNitBasedBrightnessSetting() {
+ // When the nits value is valid, the brightness is set from the old default display nits
+ // value
+ float nits = 200f;
+ float brightness = 0.3f;
+ AutomaticBrightnessController automaticBrightnessController =
+ mock(AutomaticBrightnessController.class);
+ when(automaticBrightnessController.convertToFloatScale(nits)).thenReturn(brightness);
+ when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits);
+ mDisplayBrightnessController.setAutomaticBrightnessController(
+ automaticBrightnessController);
+ verify(mBrightnessSetting).setBrightness(brightness);
+ assertEquals(brightness, mDisplayBrightnessController.getCurrentBrightness(), 0.01f);
+ clearInvocations(automaticBrightnessController, mBrightnessSetting);
+
+ // When the nits value is invalid, the brightness is resumed from where it was last set
+ nits = -1;
+ brightness = 0.4f;
+ when(automaticBrightnessController.convertToFloatScale(nits)).thenReturn(brightness);
+ when(mBrightnessSetting.getBrightnessNitsForDefaultDisplay()).thenReturn(nits);
+ when(mBrightnessSetting.getBrightness()).thenReturn(brightness);
+ mDisplayBrightnessController.setAutomaticBrightnessController(
+ automaticBrightnessController);
+ verify(mBrightnessSetting, never()).setBrightness(brightness);
+ assertEquals(brightness, mDisplayBrightnessController.getCurrentBrightness(), 0.01f);
+ clearInvocations(automaticBrightnessController, mBrightnessSetting);
+
+ // When the display is a non-default display, the brightness is resumed from where it was
+ // last set
+ int nonDefaultDisplayId = 1;
+ mDisplayBrightnessController = new DisplayBrightnessController(mContext, mInjector,
+ nonDefaultDisplayId, DEFAULT_BRIGHTNESS, mBrightnessSetting,
+ mOnBrightnessChangeRunnable, mBrightnessChangeExecutor);
+ brightness = 0.5f;
+ when(mBrightnessSetting.getBrightness()).thenReturn(brightness);
+ mDisplayBrightnessController.setAutomaticBrightnessController(
+ automaticBrightnessController);
+ assertEquals(brightness, mDisplayBrightnessController.getCurrentBrightness(), 0.01f);
+ verifyZeroInteractions(automaticBrightnessController);
+ verify(mBrightnessSetting, never()).getBrightnessNitsForDefaultDisplay();
+ verify(mBrightnessSetting, never()).setBrightness(brightness);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
index 5751db0727e7..275533fb1c37 100644
--- a/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/media/projection/MediaProjectionManagerServiceTest.java
@@ -446,6 +446,25 @@ public class MediaProjectionManagerServiceTest {
}
@Test
+ public void testSetUserReviewGrantedConsentResult_projectionNull_consentNotGranted()
+ throws Exception {
+ MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
+ projection.start(mIMediaProjectionCallback);
+ assertThat(mService.isCurrentProjection(projection)).isTrue();
+ doReturn(true).when(mWindowManagerInternal).setContentRecordingSession(
+ any(ContentRecordingSession.class));
+ // Some other token.
+ final IMediaProjection otherProjection = null;
+ // Waiting for user to review consent.
+ mService.setContentRecordingSession(mWaitingDisplaySession);
+ mService.setUserReviewGrantedConsentResult(RECORD_CANCEL, otherProjection);
+
+ // Display result is ignored; only the first session is set.
+ verify(mWindowManagerInternal, times(1)).setContentRecordingSession(
+ eq(mWaitingDisplaySession));
+ }
+
+ @Test
public void testSetUserReviewGrantedConsentResult_noVirtualDisplay() throws Exception {
MediaProjectionManagerService.MediaProjection projection = startProjectionPreconditions();
projection.start(mIMediaProjectionCallback);
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 0033e3e368c6..cb984f814f1a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -851,7 +851,7 @@ public class ActivityRecordTests extends WindowTestsBase {
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
}
}, 0, 0));
activity.updateOptionsLocked(opts);
@@ -3124,7 +3124,7 @@ public class ActivityRecordTests extends WindowTestsBase {
.setSystemDecorations(true).build();
// Add a decor insets provider window.
final WindowState navbar = createNavBarWithProvidedInsets(squareDisplay);
- assertTrue(navbar.providesNonDecorInsets()
+ assertTrue(navbar.providesDisplayDecorInsets()
&& squareDisplay.getDisplayPolicy().updateDecorInsetsInfo());
squareDisplay.sendNewConfiguration();
final Task task = new TaskBuilder(mSupervisor).setDisplay(squareDisplay).build();
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index 6d1312458ce2..169968c75fc5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -87,7 +87,7 @@ public class AppChangeTransitionTests extends WindowTestsBase {
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
}
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 0ae579bab413..a11079be85ab 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -735,7 +735,7 @@ public class AppTransitionControllerTest extends WindowTestsBase {
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) throws RemoteException {
+ public void onAnimationCancelled() throws RemoteException {
mFinishedCallback = null;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index 59cc4f5b0948..ba8c94dd9218 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -549,7 +549,7 @@ public class AppTransitionTests extends WindowTestsBase {
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
mCancelled = true;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java b/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
index 06b4ad975a87..7b4392b5e15d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AssistDataRequesterTest.java
@@ -50,7 +50,6 @@ import android.platform.test.annotations.Presubmit;
import android.util.Log;
import android.view.IWindowManager;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import com.android.server.am.AssistDataRequester;
@@ -155,7 +154,6 @@ public class AssistDataRequesterTest {
}
@Test
- @FlakyTest(bugId = 130388718)
public void testRequestData() throws Exception {
setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
CALLER_ASSIST_SCREENSHOT_ALLOWED);
@@ -263,7 +261,6 @@ public class AssistDataRequesterTest {
}
@Test
- @FlakyTest(bugId = 130388718)
public void testNoFetchScreenshots_expectNoScreenshotCallbacks() throws Exception {
setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
CALLER_ASSIST_SCREENSHOT_ALLOWED);
@@ -275,7 +272,6 @@ public class AssistDataRequesterTest {
}
@Test
- @FlakyTest(bugId = 130388718)
public void testDisallowAssistScreenshot_expectNullScreenshotCallback() throws Exception {
setupMocks(CURRENT_ACTIVITY_ASSIST_ALLOWED, CALLER_ASSIST_STRUCTURE_ALLOWED,
!CALLER_ASSIST_SCREENSHOT_ALLOWED);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index c8fdee06f3e4..353a8ecaf13d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -45,6 +45,8 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -298,20 +300,27 @@ public class DisplayPolicyTests extends WindowTestsBase {
@Test
public void testUpdateDisplayConfigurationByDecor() {
+ doReturn(NO_CUTOUT).when(mDisplayContent).calculateDisplayCutoutForRotation(anyInt());
final WindowState navbar = createNavBarWithProvidedInsets(mDisplayContent);
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
final DisplayInfo di = mDisplayContent.getDisplayInfo();
final int prevScreenHeightDp = mDisplayContent.getConfiguration().screenHeightDp;
- assertTrue(navbar.providesNonDecorInsets() && displayPolicy.updateDecorInsetsInfo());
+ assertTrue(navbar.providesDisplayDecorInsets() && displayPolicy.updateDecorInsetsInfo());
assertEquals(NAV_BAR_HEIGHT, displayPolicy.getDecorInsetsInfo(di.rotation,
di.logicalWidth, di.logicalHeight).mConfigInsets.bottom);
mDisplayContent.sendNewConfiguration();
assertNotEquals(prevScreenHeightDp, mDisplayContent.getConfiguration().screenHeightDp);
- assertFalse(navbar.providesNonDecorInsets() && displayPolicy.updateDecorInsetsInfo());
+ assertFalse(navbar.providesDisplayDecorInsets() && displayPolicy.updateDecorInsetsInfo());
navbar.removeIfPossible();
assertEquals(0, displayPolicy.getDecorInsetsInfo(di.rotation, di.logicalWidth,
di.logicalHeight).mNonDecorInsets.bottom);
+
+ final WindowState statusBar = createStatusBarWithProvidedInsets(mDisplayContent);
+ assertTrue(statusBar.providesDisplayDecorInsets()
+ && displayPolicy.updateDecorInsetsInfo());
+ assertEquals(STATUS_BAR_HEIGHT, displayPolicy.getDecorInsetsInfo(di.rotation,
+ di.logicalWidth, di.logicalHeight).mConfigInsets.top);
}
@SetupWindows(addWindows = { W_NAVIGATION_BAR, W_INPUT_METHOD })
diff --git a/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java b/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
index 027f90333561..8cf2776b85e9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/PersisterQueueTests.java
@@ -27,7 +27,6 @@ import static org.junit.Assert.assertTrue;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import org.junit.After;
@@ -110,7 +109,6 @@ public class PersisterQueueTests {
}
@Test
- @FlakyTest(bugId = 131005232)
public void testProcessOneItem_Flush() throws Exception {
mFactory.setExpectedProcessedItemNumber(1);
mListener.setExpectedOnPreProcessItemCallbackTimes(1);
@@ -162,7 +160,6 @@ public class PersisterQueueTests {
}
@Test
- @FlakyTest(bugId = 128526085)
public void testProcessTwoItems_OneAfterAnother() throws Exception {
// First item
mFactory.setExpectedProcessedItemNumber(1);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
index 0db983c6396c..c4d03bebc751 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java
@@ -37,7 +37,6 @@ import android.view.Surface;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import com.android.server.wm.RefreshRatePolicy.FrameRateVote;
@@ -53,7 +52,6 @@ import org.junit.runner.RunWith;
@SmallTest
@Presubmit
@RunWith(WindowTestRunner.class)
-@FlakyTest
public class RefreshRatePolicyTest extends WindowTestsBase {
private static final int HI_MODE_ID = 1;
private static final float HI_REFRESH_RATE = 90;
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index eb26415c2b21..11d9629cf25e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -211,7 +211,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
adapter.onAnimationCancelled(mMockLeash);
- verify(mMockRunner).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner).onAnimationCancelled();
}
@Test
@@ -227,7 +227,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
mClock.fastForward(10500);
mHandler.timeAdvance();
- verify(mMockRunner).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner).onAnimationCancelled();
verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
eq(adapter));
}
@@ -248,12 +248,12 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
mClock.fastForward(10500);
mHandler.timeAdvance();
- verify(mMockRunner, never()).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner, never()).onAnimationCancelled();
mClock.fastForward(52500);
mHandler.timeAdvance();
- verify(mMockRunner).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner).onAnimationCancelled();
verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
eq(adapter));
} finally {
@@ -265,7 +265,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
public void testZeroAnimations() throws Exception {
mController.goodToGo(TRANSIT_OLD_NONE);
verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
- verify(mMockRunner).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner).onAnimationCancelled();
}
@Test
@@ -275,7 +275,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false);
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
- verify(mMockRunner).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner).onAnimationCancelled();
}
@Test
@@ -317,7 +317,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
win.mActivityRecord.removeImmediately();
mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
- verify(mMockRunner).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner).onAnimationCancelled();
verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
eq(adapter));
}
@@ -575,7 +575,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
// Cancel the wallpaper window animator and ensure the runner is not canceled
wallpaperWindowToken.cancelAnimation();
- verify(mMockRunner, never()).onAnimationCancelled(anyBoolean());
+ verify(mMockRunner, never()).onAnimationCancelled();
} finally {
mDisplayContent.mOpeningApps.clear();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
index ff753f21d01b..339162a02301 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -98,7 +98,6 @@ public class SurfaceAnimationRunnerTest {
mFinishCallbackLatch.countDown();
}
- @FlakyTest(bugId = 144611135)
@Test
public void testAnimation() throws Exception {
mSurfaceAnimationRunner
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
index 790b15443198..453e4684e859 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackChangedListenerTest.java
@@ -52,7 +52,6 @@ import android.view.Display;
import android.view.ViewGroup;
import android.widget.LinearLayout;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.MediumTest;
import org.junit.After;
@@ -319,7 +318,6 @@ public class TaskStackChangedListenerTest {
};
@Presubmit
- @FlakyTest(bugId = 150409355)
@Test
public void testNotifyTaskRequestedOrientationChanged() throws Exception {
final ArrayBlockingQueue<int[]> taskIdAndOrientationQueue = new ArrayBlockingQueue<>(10);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index a1ddd5748002..ad606cb90841 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -1112,7 +1112,7 @@ public class WindowContainerTests extends WindowTestsBase {
}
@Override
- public void onAnimationCancelled(boolean isKeyguardOccluded) {
+ public void onAnimationCancelled() {
}
}, 0, 0, false);
adapter.setCallingPidUid(123, 456);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java
index 0b1b877c27de..2ae117214dd3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerThumbnailTest.java
@@ -26,7 +26,6 @@ import static org.mockito.ArgumentMatchers.any;
import android.hardware.HardwareBuffer;
import android.platform.test.annotations.Presubmit;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import org.junit.Test;
@@ -55,7 +54,6 @@ public class WindowContainerThumbnailTest extends WindowTestsBase {
}
@Test
- @FlakyTest(bugId = 131005232)
public void testDestroy_nullsSurface() {
final WindowContainerThumbnail t = buildThumbnail();
assertNotNull(t.getSurfaceControl());
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 07244a4f2478..a63807d23a14 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -471,6 +471,17 @@ class WindowTestsBase extends SystemServiceTestsBase {
return navbar;
}
+ WindowState createStatusBarWithProvidedInsets(DisplayContent dc) {
+ final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, dc, "statusBar");
+ final Binder owner = new Binder();
+ statusBar.mAttrs.providedInsets = new InsetsFrameProvider[] {
+ new InsetsFrameProvider(owner, 0, WindowInsets.Type.statusBars())
+ .setInsetsSize(Insets.of(0, STATUS_BAR_HEIGHT, 0, 0))
+ };
+ dc.getDisplayPolicy().addWindowLw(statusBar, statusBar.mAttrs);
+ return statusBar;
+ }
+
WindowState createAppWindow(Task task, int type, String name) {
final ActivityRecord activity = createNonAttachedActivityRecord(task.getDisplayContent());
task.addChild(activity, 0);
diff --git a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
index 10b7952acab2..ba178845a536 100644
--- a/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
+++ b/services/usb/java/com/android/server/usb/descriptors/UsbDescriptorParser.java
@@ -584,15 +584,34 @@ public final class UsbDescriptorParser {
}
/**
+ * Returns true only if there is a terminal whose subtype and terminal type are the same as
+ * the given values.
* @hide
*/
- public boolean hasAudioTerminal(int subType) {
+ public boolean hasAudioTerminal(int subType, int terminalType) {
for (UsbDescriptor descriptor : mDescriptors) {
- if (descriptor instanceof UsbACInterface) {
- if (((UsbACInterface) descriptor).getSubclass()
- == UsbDescriptor.AUDIO_AUDIOCONTROL
- && ((UsbACInterface) descriptor).getSubtype()
- == subType) {
+ if (descriptor instanceof UsbACTerminal) {
+ if (((UsbACTerminal) descriptor).getSubclass() == UsbDescriptor.AUDIO_AUDIOCONTROL
+ && ((UsbACTerminal) descriptor).getSubtype() == subType
+ && ((UsbACTerminal) descriptor).getTerminalType() == terminalType) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true only if there is an interface whose subtype is the same as the given one and
+ * terminal type is different from the given one.
+ * @hide
+ */
+ public boolean hasAudioTerminalExcludeType(int subType, int excludedTerminalType) {
+ for (UsbDescriptor descriptor : mDescriptors) {
+ if (descriptor instanceof UsbACTerminal) {
+ if (((UsbACTerminal) descriptor).getSubclass() == UsbDescriptor.AUDIO_AUDIOCONTROL
+ && ((UsbACTerminal) descriptor).getSubtype() == subType
+ && ((UsbACTerminal) descriptor).getTerminalType() != excludedTerminalType) {
return true;
}
}
@@ -604,14 +623,21 @@ public final class UsbDescriptorParser {
* @hide
*/
public boolean hasAudioPlayback() {
- return hasAudioTerminal(UsbACInterface.ACI_OUTPUT_TERMINAL);
+ return hasAudioTerminalExcludeType(
+ UsbACInterface.ACI_OUTPUT_TERMINAL, UsbTerminalTypes.TERMINAL_USB_STREAMING)
+ && hasAudioTerminal(
+ UsbACInterface.ACI_INPUT_TERMINAL, UsbTerminalTypes.TERMINAL_USB_STREAMING);
}
/**
* @hide
*/
public boolean hasAudioCapture() {
- return hasAudioTerminal(UsbACInterface.ACI_INPUT_TERMINAL);
+ return hasAudioTerminalExcludeType(
+ UsbACInterface.ACI_INPUT_TERMINAL, UsbTerminalTypes.TERMINAL_USB_STREAMING)
+ && hasAudioTerminal(
+ UsbACInterface.ACI_OUTPUT_TERMINAL,
+ UsbTerminalTypes.TERMINAL_USB_STREAMING);
}
/**
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 9dd2a61671ec..26590c4704c3 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -744,10 +744,6 @@ public class TelecomManager {
* state of calls in the self-managed {@link ConnectionService}. An example use-case is
* exposing these calls to an automotive device via its companion app.
* <p>
- * This meta-data can only be set for an {@link InCallService} which also sets
- * {@link #METADATA_IN_CALL_SERVICE_UI}. Only the default phone/dialer app, or a car-mode
- * {@link InCallService} can see self-managed calls.
- * <p>
* See also {@link Connection#PROPERTY_SELF_MANAGED}.
*/
public static final String METADATA_INCLUDE_SELF_MANAGED_CALLS =
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 1ce85ba93d95..28ea5a681730 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1186,6 +1186,7 @@ public class ApnSetting implements Parcelable {
ApnSetting other = (ApnSetting) o;
return mEntryName.equals(other.mEntryName)
+ && Objects.equals(mId, other.mId)
&& Objects.equals(mOperatorNumeric, other.mOperatorNumeric)
&& Objects.equals(mApnName, other.mApnName)
&& Objects.equals(mProxyAddress, other.mProxyAddress)
@@ -1337,6 +1338,14 @@ public class ApnSetting implements Parcelable {
public ContentValues toContentValues() {
ContentValues apnValue = new ContentValues();
apnValue.put(Telephony.Carriers.NUMERIC, nullToEmpty(mOperatorNumeric));
+ // If the APN is editable, the user may be able to set an invalid numeric. The numeric must
+ // always be 5 or 6 characters (depending on the length of the MNC), so skip if it is
+ // potentially invalid.
+ if (!TextUtils.isEmpty(mOperatorNumeric)
+ && (mOperatorNumeric.length() == 5 || mOperatorNumeric.length() == 6)) {
+ apnValue.put(Telephony.Carriers.MCC, mOperatorNumeric.substring(0, 3));
+ apnValue.put(Telephony.Carriers.MNC, mOperatorNumeric.substring(3));
+ }
apnValue.put(Telephony.Carriers.NAME, nullToEmpty(mEntryName));
apnValue.put(Telephony.Carriers.APN, nullToEmpty(mApnName));
apnValue.put(Telephony.Carriers.PROXY, nullToEmpty(mProxyAddress));
@@ -1356,6 +1365,7 @@ public class ApnSetting implements Parcelable {
getProtocolStringFromInt(mRoamingProtocol));
apnValue.put(Telephony.Carriers.CARRIER_ENABLED, mCarrierEnabled);
apnValue.put(Telephony.Carriers.MVNO_TYPE, getMvnoTypeStringFromInt(mMvnoType));
+ apnValue.put(Telephony.Carriers.MVNO_MATCH_DATA, nullToEmpty(mMvnoMatchData));
apnValue.put(Telephony.Carriers.NETWORK_TYPE_BITMASK, mNetworkTypeBitmask);
apnValue.put(Telephony.Carriers.LINGERING_NETWORK_TYPE_BITMASK,
mLingeringNetworkTypeBitmask);
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
index 4e3ae0c0752a..efd9b004f8fd 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
@@ -18,7 +18,7 @@ package com.android.server.wm.flicker
import android.app.Instrumentation
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerBuilderProvider
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index f389e13a6884..1f120d47a1ac 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -19,9 +19,9 @@
package com.android.server.wm.flicker
import android.tools.common.PlatformConsts
-import android.tools.common.datatypes.component.ComponentNameMatcher
-import android.tools.common.datatypes.component.IComponentNameMatcher
import android.tools.common.flicker.subject.region.RegionSubject
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.common.traces.component.IComponentNameMatcher
import android.tools.common.traces.wm.WindowManagerTrace
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.helpers.WindowUtils
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt
index c3cbb84fd37f..863828881d36 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingSecondaryToSplitTest.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.activityembedding
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
index 5dc2dd7d93a8..10b71ff1efd7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
@@ -40,20 +40,27 @@ import org.junit.runners.Parameterized
* Launch an app [testApp] and wait animation to complete
* Press back button
* ```
+ *
* To run only the presubmit assertions add: `--
+ *
* ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Presubmit`
* ```
+ *
* To run only the postsubmit assertions add: `--
+ *
* ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Postsubmit`
* ```
+ *
* To run only the flaky assertions add: `--
+ *
* ```
* --module-arg FlickerTests:include-annotation:androidx.test.filters.FlakyTest`
* ```
+ *
* Notes:
* ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
index b042a14b30da..e5bd350019c8 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
@@ -40,20 +40,27 @@ import org.junit.runners.Parameterized
* Launch an app [testApp] and wait animation to complete
* Press home button
* ```
+ *
* To run only the presubmit assertions add: `--
+ *
* ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Presubmit`
* ```
+ *
* To run only the postsubmit assertions add: `--
+ *
* ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Postsubmit`
* ```
+ *
* To run only the flaky assertions add: `--
+ *
* ```
* --module-arg FlickerTests:include-annotation:androidx.test.filters.FlakyTest`
* ```
+ *
* Notes:
* ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
index c4628aaa90af..4570fa23dc43 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.close
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.LAUNCHER
+import android.tools.common.traces.component.ComponentNameMatcher.Companion.LAUNCHER
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
index e531bc06fb3d..6053f1dc9319 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.common.traces.wm.WindowManagerState.Companion.STATE_RESUMED
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt
index afb9fbf47350..94ac1a6e1e02 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/AppPairsHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
class AppPairsHelper(
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
index 47dd4e9fb32d..c6fa1bb89220 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
index d4f48fe8d50f..747cf3742bf7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.WindowManagerStateHelper
import android.tools.device.traces.parsers.toFlickerComponent
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
index 73effbde4515..d1722521bba8 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.traces.parsers.WindowManagerStateHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
index a6e57d5641d6..7a8d780c3d9f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.traces.parsers.WindowManagerStateHelper
import android.tools.device.traces.parsers.toFlickerComponent
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt
index d61a500e3293..83a41abbd4bd 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeShownOnAppStartHelper.kt
@@ -18,10 +18,10 @@ package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
-import android.tools.common.datatypes.component.IComponentMatcher
import android.tools.common.traces.Condition
import android.tools.common.traces.DeviceStateDump
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.common.traces.component.IComponentMatcher
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.helpers.IME_PACKAGE
import android.tools.device.traces.parsers.WindowManagerStateHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
index fb5e1d2da26b..b2aeb14aaf78 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
index 1ccac13c280f..a670d68cabd9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LetterboxAppHelper.kt
@@ -17,15 +17,15 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import androidx.test.uiautomator.By
-import androidx.test.uiautomator.Until
-import com.android.server.wm.flicker.testapp.ActivityOptions
-import android.tools.common.datatypes.component.ComponentNameMatcher
-import android.tools.device.traces.parsers.toFlickerComponent
-import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.helpers.SYSTEMUI_PACKAGE
+import android.tools.device.traces.parsers.WindowManagerStateHelper
+import android.tools.device.traces.parsers.toFlickerComponent
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.Until
+import com.android.server.wm.flicker.testapp.ActivityOptions
class LetterboxAppHelper
@JvmOverloads
@@ -37,13 +37,21 @@ constructor(
) : StandardAppHelper(instr, launcherName, component) {
fun clickRestart(wmHelper: WindowManagerStateHelper) {
- val restartButton = uiDevice.wait(Until.findObject(By.res(
- SYSTEMUI_PACKAGE, "size_compat_restart_button")), FIND_TIMEOUT)
+ val restartButton =
+ uiDevice.wait(
+ Until.findObject(By.res(SYSTEMUI_PACKAGE, "size_compat_restart_button")),
+ FIND_TIMEOUT
+ )
restartButton?.run { restartButton.click() } ?: error("Restart button not found")
// size compat mode restart confirmation dialog button
- val restartDialogButton = uiDevice.wait(Until.findObject(By.res(
- SYSTEMUI_PACKAGE, "letterbox_restart_dialog_restart_button")), FIND_TIMEOUT)
+ val restartDialogButton =
+ uiDevice.wait(
+ Until.findObject(
+ By.res(SYSTEMUI_PACKAGE, "letterbox_restart_dialog_restart_button")
+ ),
+ FIND_TIMEOUT
+ )
restartDialogButton?.run { restartDialogButton.click() }
?: error("Restart dialog button not found")
wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt
index ab916858858a..c98f1c4b4d29 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.traces.parsers.toFlickerComponent
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt
index e93e9c8e9bfb..65175ef33afb 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt
@@ -19,7 +19,7 @@ package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
import android.content.Context
import android.provider.Settings
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.util.Log
import com.android.compatibility.common.util.SystemUtil
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
index c547ad06fe6c..5b3d3083fe1c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.traces.parsers.WindowManagerStateHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
index 20ee3b9d236d..ee65004e9e78 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
index 78f8bcf70b60..7665690a3122 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.traces.parsers.WindowManagerStateHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
index c5a21a80d8d0..24e231c73a0f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
@@ -21,8 +21,8 @@ import android.media.session.MediaController
import android.media.session.MediaSessionManager
import android.tools.common.datatypes.Rect
import android.tools.common.datatypes.Region
-import android.tools.common.datatypes.component.IComponentMatcher
import android.tools.common.traces.ConditionsFactory
+import android.tools.common.traces.component.IComponentMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.helpers.SYSTEMUI_PACKAGE
@@ -250,7 +250,8 @@ open class PipAppHelper(instrumentation: Instrumentation) :
waitConditions = arrayOf(ConditionsFactory.hasPipWindow())
)
- wmHelper.StateSyncBuilder()
+ wmHelper
+ .StateSyncBuilder()
.withWindowSurfaceAppeared(this)
.withPipShown()
.waitForAndVerify()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
index 06e668ea07a1..cac3530399de 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
index 94c90dabd2c8..8366a7a1fe41 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
index 64af811d1c4f..89c6c35af47d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.traces.parsers.toFlickerComponent
import com.android.server.wm.flicker.testapp.ActivityOptions
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
index 316766a5c3f3..895725c1efef 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.helpers
import android.app.Instrumentation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.helpers.FIND_TIMEOUT
import android.tools.device.traces.parsers.WindowManagerStateHelper
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
index 34fa921f5777..7e0632d216ea 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnDismissPopupDialogTest.kt
@@ -18,8 +18,8 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
import android.tools.common.flicker.subject.region.RegionSubject
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
index 823328af57aa..7f496d828996 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeOnGoHomeTest.kt
@@ -19,7 +19,7 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
index df9d33bf2c8f..cbe03dcd932a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartOnGoHomeTest.kt
@@ -18,7 +18,7 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
index 7954dd13e906..82c390b77d59 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeShownOnAppStartToAppOnPressBackTest.kt
@@ -18,7 +18,7 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
index 10ce5eab4f29..c693ca759bdd 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeToAppOnPressBackTest.kt
@@ -18,7 +18,7 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
index 579c10f62f52..8e3371986056 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
@@ -18,7 +18,7 @@
package com.android.server.wm.flicker.ime
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.legacy.FlickerTest
fun FlickerTest.imeLayerBecomesVisible() {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
index 3f87aef16cdb..19bbf0cb92b0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToFixedPortraitAppTest.kt
@@ -18,8 +18,8 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
import android.tools.common.NavBar
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
import android.tools.common.flicker.subject.region.RegionSubject
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
index 6179fc2aef21..f64ad53bf2f7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromOverviewTest.kt
@@ -18,7 +18,7 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
index 690ed53df5f2..11bc7b9f29c0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppFromQuickSwitchTest.kt
@@ -19,7 +19,7 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
import android.tools.common.NavBar
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
index 866e858f3865..46967db55086 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeOnAppStartWhenLaunchingAppTest.kt
@@ -18,7 +18,7 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
index 6f225891f39c..277b91558416 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileDismissingThemedPopupDialogTest.kt
@@ -18,7 +18,7 @@ package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
index 231d0d74c2a1..9275d6a2f17f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ShowImeWhileEnteringOverviewTest.kt
@@ -17,8 +17,8 @@
package com.android.server.wm.flicker.ime
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
import android.tools.common.traces.ConditionsFactory
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
index 3c577ac2db35..e6594c969373 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTestCfArm.kt
index 3289bc601160..ac05c7687311 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTestCfArm.kt
@@ -41,4 +41,4 @@ class OpenAppAfterCameraTestCfArm(flicker: FlickerTest) : OpenAppAfterCameraTest
return FlickerTestFactory.nonRotationTests()
}
}
-} \ No newline at end of file
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
index d0dc42f29b9e..26f88d23cda0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
@@ -23,9 +23,9 @@ import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.helpers.setRotation
-import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -42,6 +42,7 @@ import org.junit.runners.Parameterized
* Make sure no apps are running on the device
* Launch an app [testApp] and wait animation to complete
* ```
+ *
* Notes:
* ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTestCfArm.kt
index f75d9eede25b..d9a99dadbd3d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTestCfArm.kt
@@ -49,4 +49,4 @@ class OpenAppColdTestCfArm(flicker: FlickerTest) : OpenAppColdTest(flicker) {
return FlickerTestFactory.nonRotationTests()
}
}
-} \ No newline at end of file
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
index 1a1d4036579f..3d5a8e309b10 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.legacy.FlickerTest
import com.android.server.wm.flicker.replacesLayer
import org.junit.Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
index b1a267ac27b4..b21777b30b21 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
@@ -78,9 +78,7 @@ open class OpenAppFromLockNotificationCold(flicker: FlickerTest) :
override fun taskBarLayerIsVisibleAtStartAndEnd() {}
/** {@inheritDoc} */
- @Test
- @Ignore("Display is off at the start")
- override fun taskBarWindowIsAlwaysVisible() {}
+ @Test @Ignore("Display is off at the start") override fun taskBarWindowIsAlwaysVisible() {}
/** {@inheritDoc} */
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
index e41432555ded..ec92ca65f80a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
@@ -20,7 +20,7 @@ import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
import android.platform.test.rule.SettingOverrideRule
import android.provider.Settings
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
index 0b09e248b221..009d61797fe0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
@@ -19,7 +19,7 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
@@ -113,9 +113,7 @@ class OpenAppFromLockNotificationWithLockOverlayApp(flicker: FlickerTest) :
@Test
override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
- @Presubmit
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
+ @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
@FlakyTest(bugId = 278227468)
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
index 730f78ff3bc2..eae9ca10c711 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
@@ -18,7 +18,7 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
import com.android.server.wm.flicker.navBarLayerPositionAtEnd
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
index 9c16b7938e73..7bcb91070ecf 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
@@ -18,7 +18,7 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdCfArm.kt
index 4aa78d4482fb..8b4a613305c0 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationColdCfArm.kt
@@ -44,4 +44,4 @@ class OpenAppFromNotificationColdCfArm(flicker: FlickerTest) :
return FlickerTestFactory.nonRotationTests()
}
}
-} \ No newline at end of file
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
index 23cb1d49619f..425e674dec3a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
@@ -18,7 +18,7 @@ package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
index 00d7544f7217..8e1b059b2bc7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
@@ -44,6 +44,7 @@ import org.junit.runners.Parameterized
* Relaunch an app [testApp] by selecting it in the overview screen, and wait animation to
* complete (only this action is traced)
* ```
+ *
* Notes:
* ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
index 17f5638a1a50..1383ae39f760 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
@@ -20,7 +20,7 @@ import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
import android.tools.common.NavBar
import android.tools.common.Rotation
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.annotation.FlickerServiceCompatible
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerTest
@@ -47,6 +47,7 @@ import org.junit.runners.Parameterized
* Lock the device.
* Launch an app on top of the lock screen [testApp] and wait animation to complete
* ```
+ *
* Notes:
* ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
@@ -161,9 +162,7 @@ open class OpenAppNonResizeableTest(flicker: FlickerTest) : OpenAppFromLockTrans
super.appWindowBecomesFirstAndOnlyTopWindow()
/** {@inheritDoc} */
- @Presubmit
- @Test
- override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
+ @Presubmit @Test override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
/** Checks the [ComponentNameMatcher.NAV_BAR] is visible at the end of the transition */
@Presubmit
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
index e0db96f3b5c6..87a14c69e3ac 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.launch
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
index cdd2d45769bb..3385830ee77f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
@@ -42,6 +42,7 @@ import org.junit.runners.Parameterized
* Press home
* Relaunch an app [testApp] and wait animation to complete (only this action is traced)
* ```
+ *
* Notes:
* ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTestCfArm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTestCfArm.kt
index 9679059e5069..d8b38b30cf13 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTestCfArm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTestCfArm.kt
@@ -43,4 +43,4 @@ class OpenAppWarmTestCfArm(flicker: FlickerTest) : OpenAppWarmTest(flicker) {
return FlickerTestFactory.nonRotationTests()
}
}
-} \ No newline at end of file
+}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
index b848e63c9c87..b48611edd738 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
@@ -20,20 +20,20 @@ import android.app.Instrumentation
import android.os.Bundle
import android.os.Handler
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
import android.tools.common.traces.ConditionsFactory
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerBuilderProvider
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
import android.tools.device.flicker.legacy.FlickerTestFactory
+import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
+import android.tools.device.helpers.wakeUpAndGoToHomeScreen
import androidx.test.filters.RequiresDevice
import androidx.test.platform.app.InstrumentationRegistry
import com.android.server.wm.flicker.R
-import com.android.server.wm.flicker.helpers.setRotation
-import android.tools.device.flicker.rules.RemoveAllTasksButHomeRule
-import android.tools.device.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.server.wm.flicker.helpers.setRotation
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
index be735477dc40..d0fd73207c42 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
@@ -21,11 +21,11 @@ import android.app.WallpaperManager
import android.content.res.Resources
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
-import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.SPLASH_SCREEN
-import android.tools.common.datatypes.component.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER
-import android.tools.common.datatypes.component.ComponentSplashScreenMatcher
-import android.tools.common.datatypes.component.IComponentMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher.Companion.SPLASH_SCREEN
+import android.tools.common.traces.component.ComponentNameMatcher.Companion.WALLPAPER_BBQ_WRAPPER
+import android.tools.common.traces.component.ComponentSplashScreenMatcher
+import android.tools.common.traces.component.IComponentMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
index eadeef5bf3e6..a8b80ad1d16c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
@@ -20,7 +20,7 @@ import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
import android.tools.common.NavBar
import android.tools.common.datatypes.Rect
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
index 136049533350..96cd8ffa3eff 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
@@ -20,7 +20,7 @@ import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
import android.tools.common.NavBar
import android.tools.common.datatypes.Rect
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
index d49f035fa84a..7e935f03aeb1 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
@@ -21,7 +21,7 @@ import android.platform.test.annotations.Presubmit
import android.tools.common.NavBar
import android.tools.common.Rotation
import android.tools.common.datatypes.Rect
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index fe789a7a7384..855ea3e38b3e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -18,7 +18,7 @@ package com.android.server.wm.flicker.rotation
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
index 3c0bbd6c4c1c..fe9da335a675 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
@@ -17,7 +17,7 @@
package com.android.server.wm.flicker.rotation
import android.platform.test.annotations.Presubmit
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.apphelpers.StandardAppHelper
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index 4d010f35d4eb..0cbbb83b48ee 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -19,7 +19,7 @@ package com.android.server.wm.flicker.rotation
import android.platform.test.annotations.IwTest
import android.platform.test.annotations.Presubmit
import android.tools.common.ScenarioBuilder
-import android.tools.common.datatypes.component.ComponentNameMatcher
+import android.tools.common.traces.component.ComponentNameMatcher
import android.tools.device.flicker.junit.FlickerParametersRunnerFactory
import android.tools.device.flicker.legacy.FlickerBuilder
import android.tools.device.flicker.legacy.FlickerTest