summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/IUidObserver.aidl3
-rw-r--r--core/java/android/app/UidObserver.java2
-rw-r--r--core/java/android/content/pm/PackageInstaller.java34
-rw-r--r--core/java/android/content/pm/parsing/ApkLiteParseUtils.java29
-rw-r--r--core/java/android/os/UserManager.java33
-rw-r--r--core/java/android/view/InsetsFrameProvider.java59
-rw-r--r--core/java/android/view/InsetsSource.java22
-rw-r--r--core/java/android/view/ViewRootImpl.java2
-rw-r--r--core/java/android/window/TransitionInfo.java6
-rw-r--r--core/proto/android/companion/telecom.proto29
-rw-r--r--core/res/res/values/dimens.xml8
-rw-r--r--core/tests/coretests/jni/NativeWorkSourceParcelTest.cpp15
-rw-r--r--core/tests/coretests/src/android/view/InsetsSourceTest.java20
-rw-r--r--data/etc/privapp-permissions-platform.xml2
-rw-r--r--graphics/java/android/graphics/MeshSpecification.java75
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java17
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java46
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt63
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java125
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/IDragAndDrop.aidl28
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/AndroidTest.xml3
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt52
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java6
-rw-r--r--libs/hwui/renderthread/CacheManager.cpp9
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp26
-rw-r--r--libs/hwui/renderthread/VulkanManager.h3
-rw-r--r--media/java/android/media/AudioSystem.java63
-rw-r--r--native/android/activity_manager.cpp4
-rw-r--r--packages/CredentialManager/res/values/strings.xml8
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt2
-rw-r--r--packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt12
-rw-r--r--packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java13
-rw-r--r--packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java107
-rw-r--r--packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java244
-rw-r--r--packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java81
-rw-r--r--packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java14
-rw-r--r--packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java17
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java6
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java50
-rw-r--r--packages/Shell/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/Android.bp1
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt39
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt14
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/AnimatableClockView.kt4
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt12
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt2
-rw-r--r--packages/SystemUI/log/.gitignore9
-rw-r--r--packages/SystemUI/log/Android.bp38
-rw-r--r--packages/SystemUI/log/AndroidManifest.xml22
-rw-r--r--packages/SystemUI/log/src/com/android/systemui/log/ConstantStringsLogger.kt (renamed from packages/SystemUI/plugin/src/com/android/systemui/plugins/log/ConstantStringsLogger.kt)2
-rw-r--r--packages/SystemUI/log/src/com/android/systemui/log/ConstantStringsLoggerImpl.kt (renamed from packages/SystemUI/plugin/src/com/android/systemui/plugins/log/ConstantStringsLoggerImpl.kt)2
-rw-r--r--packages/SystemUI/log/src/com/android/systemui/log/LogBuffer.kt (renamed from packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt)2
-rw-r--r--packages/SystemUI/log/src/com/android/systemui/log/LogLevel.kt (renamed from packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogLevel.kt)2
-rw-r--r--packages/SystemUI/log/src/com/android/systemui/log/LogMessage.kt (renamed from packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogMessage.kt)2
-rw-r--r--packages/SystemUI/log/src/com/android/systemui/log/LogMessageImpl.kt (renamed from packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogMessageImpl.kt)2
-rw-r--r--packages/SystemUI/log/src/com/android/systemui/log/LogcatEchoTracker.kt (renamed from packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTracker.kt)2
-rw-r--r--packages/SystemUI/log/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt (renamed from packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt)2
-rw-r--r--packages/SystemUI/log/src/com/android/systemui/log/LogcatEchoTrackerProd.kt (renamed from packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerProd.kt)2
-rw-r--r--packages/SystemUI/plugin/Android.bp2
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt2
-rw-r--r--packages/SystemUI/res-keyguard/layout/status_bar_mobile_signal_group_inner.xml21
-rw-r--r--packages/SystemUI/res/layout/combined_qs_header.xml3
-rw-r--r--packages/SystemUI/res/layout/smart_action_button.xml4
-rw-r--r--packages/SystemUI/res/layout/smart_reply_button.xml4
-rw-r--r--packages/SystemUI/res/layout/status_bar_wifi_group_inner.xml12
-rw-r--r--packages/SystemUI/res/layout/udfps_keyguard_view_internal.xml3
-rw-r--r--packages/SystemUI/res/values-sw720dp/dimens.xml2
-rw-r--r--packages/SystemUI/res/values/dimens.xml51
-rw-r--r--packages/SystemUI/res/values/ids.xml3
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/condition/CombinedCondition.kt172
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java58
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/condition/ConditionExtensions.kt32
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt36
-rw-r--r--packages/SystemUI/src/com/android/keyguard/ClockEventController.kt4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java22
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java21
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java14
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java2
-rw-r--r--packages/SystemUI/src/com/android/keyguard/logging/BiometricMessageDeferralLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/logging/BiometricUnlockLogger.kt8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt14
-rw-r--r--packages/SystemUI/src/com/android/keyguard/logging/TrustRepositoryLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsLogger.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/bluetooth/BluetoothLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/BiometricLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/BroadcastDispatcherLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/DozeLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardClockLog.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/LSShadeTransitionLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/MediaBrowserLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/MediaCarouselControllerLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/MediaMuteAwaitLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/MediaTimeoutListenerLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/MediaViewLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/NearbyMediaDevicesLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/NotifInteractionLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/NotificationHeadsUpLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/NotificationInterruptLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/NotificationRenderLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/NotificationSectionLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/PrivacyLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/QSConfigLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/QSFragmentDisableLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/QSLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/ShadeLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/ShadeWindowLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/StatusBarNetworkControllerLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/SwipeUpLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/ToastLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/dagger/UnseenNotificationLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselControllerLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtils.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLogBuffer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLogger.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogBuffer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSPipelineModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/RemoteInputControllerLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationRoundnessLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLogger.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/VerboseMobileViewLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarLogger.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/temporarydisplay/dagger/TemporaryDisplayModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLockLog.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLockLogger.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt (renamed from packages/SystemUI/plugin/tests/log/LogBufferTest.kt)1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/log/table/TableLogBufferTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtilsTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLoggerTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLoggerTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/process/condition/SystemProcessConditionTest.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentDisableFlagsLoggerTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt450
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt24
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java174
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/condition/FakeCondition.java19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt82
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java18
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt4
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java20
-rw-r--r--services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncConnectionService.java49
-rw-r--r--services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncData.java16
-rw-r--r--services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncInCallService.java27
-rw-r--r--services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceCall.java35
-rw-r--r--services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceSyncController.java4
-rw-r--r--services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java54
-rw-r--r--services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java21
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java4
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueueImpl.java4
-rw-r--r--services/core/java/com/android/server/am/CachedAppOptimizer.java19
-rw-r--r--services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java18
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java5
-rw-r--r--services/core/java/com/android/server/am/UidObserverController.java7
-rw-r--r--services/core/java/com/android/server/am/UidRecord.java20
-rw-r--r--services/core/java/com/android/server/am/UserController.java327
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java86
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java811
-rw-r--r--services/core/java/com/android/server/audio/AudioSystemAdapter.java15
-rw-r--r--services/core/java/com/android/server/audio/BtHelper.java93
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java55
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java22
-rw-r--r--services/core/java/com/android/server/pm/UserJourneyLogger.java552
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java222
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java10
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java108
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java17
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java10
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java8
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java7
-rw-r--r--services/core/java/com/android/server/wm/KeyguardController.java2
-rw-r--r--services/core/java/com/android/server/wm/Transition.java42
-rw-r--r--services/core/java/com/android/server/wm/TransitionController.java9
-rw-r--r--services/core/java/com/android/server/wm/WallpaperController.java128
-rw-r--r--services/core/java/com/android/server/wm/WallpaperWindowToken.java20
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java6
-rw-r--r--services/core/jni/com_android_server_am_CachedAppOptimizer.cpp12
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java32
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java141
-rw-r--r--services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java23
-rw-r--r--services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java11
-rw-r--r--services/tests/servicestests/src/com/android/server/am/UserControllerTest.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncDataTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncInCallServiceTest.java12
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CrossDeviceCallTest.java46
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CrossDeviceSyncControllerTest.java18
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java13
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserJourneyLoggerTest.java580
-rw-r--r--services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java17
-rw-r--r--services/tests/voiceinteractiontests/src/com/android/server/soundtrigger/DeviceStateHandlerTest.java261
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java18
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java9
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/DeviceStateHandler.java279
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/PhoneCallStateHandler.java158
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java211
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java59
-rw-r--r--tests/FlickerTests/AndroidTest.xml3
314 files changed, 6121 insertions, 2263 deletions
diff --git a/core/java/android/app/IUidObserver.aidl b/core/java/android/app/IUidObserver.aidl
index 0c920f1359f3..60c2eeddac63 100644
--- a/core/java/android/app/IUidObserver.aidl
+++ b/core/java/android/app/IUidObserver.aidl
@@ -58,8 +58,9 @@ oneway interface IUidObserver {
* Report a proc oom adj change associated with a uid.
*
* @param uid The uid for which the state change is being reported.
+ * @param adj The minimum OOM adj among all processes with this uid.
*/
- void onUidProcAdjChanged(int uid);
+ void onUidProcAdjChanged(int uid, int adj);
// =============== End of transactions used on native side as well ============================
diff --git a/core/java/android/app/UidObserver.java b/core/java/android/app/UidObserver.java
index 9e928073ac5c..519662448e91 100644
--- a/core/java/android/app/UidObserver.java
+++ b/core/java/android/app/UidObserver.java
@@ -41,7 +41,7 @@ public class UidObserver extends IUidObserver.Stub {
}
@Override
- public void onUidProcAdjChanged(int uid) {
+ public void onUidProcAdjChanged(int uid, int adj) {
}
@Override
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index de66f050c007..56f6f8206d30 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -2072,6 +2072,25 @@ public class PackageInstaller {
return new InstallInfo(result);
}
+ /**
+ * Parse a single APK file passed as an FD to get install relevant information about
+ * the package wrapped in {@link InstallInfo}.
+ * @throws PackageParsingException if the package source file(s) provided is(are) not valid,
+ * or the parser isn't able to parse the supplied source(s).
+ * @hide
+ */
+ @NonNull
+ public InstallInfo readInstallInfo(@NonNull ParcelFileDescriptor pfd,
+ @Nullable String debugPathName, int flags) throws PackageParsingException {
+ final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
+ final ParseResult<PackageLite> result = ApkLiteParseUtils.parseMonolithicPackageLite(input,
+ pfd.getFileDescriptor(), debugPathName, flags);
+ if (result.isError()) {
+ throw new PackageParsingException(result.getErrorCode(), result.getErrorMessage());
+ }
+ return new InstallInfo(result);
+ }
+
// (b/239722738) This class serves as a bridge between the PackageLite class, which
// is a hidden class, and the consumers of this class. (e.g. InstallInstalling.java)
// This is a part of an effort to remove dependency on hidden APIs and use SystemAPIs or
@@ -2125,6 +2144,21 @@ public class PackageInstaller {
public long calculateInstalledSize(@NonNull SessionParams params) throws IOException {
return InstallLocationUtils.calculateInstalledSize(mPkg, params.abiOverride);
}
+
+ /**
+ * @param params {@link SessionParams} of the installation
+ * @param pfd of an APK opened for read
+ * @return Total disk space occupied by an application after installation.
+ * Includes the size of the raw APKs, possibly unpacked resources, raw dex metadata files,
+ * and all relevant native code.
+ * @throws IOException when size of native binaries cannot be calculated.
+ * @hide
+ */
+ public long calculateInstalledSize(@NonNull SessionParams params,
+ @NonNull ParcelFileDescriptor pfd) throws IOException {
+ return InstallLocationUtils.calculateInstalledSize(mPkg, params.abiOverride,
+ pfd.getFileDescriptor());
+ }
}
/**
diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
index a4339d41dfd2..d209b35ac810 100644
--- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
@@ -109,7 +109,7 @@ public class ApkLiteParseUtils {
}
/**
- * Parse lightweight details about a single APK files.
+ * Parse lightweight details about a single APK file.
*/
public static ParseResult<PackageLite> parseMonolithicPackageLite(ParseInput input,
File packageFile, int flags) {
@@ -135,6 +135,33 @@ public class ApkLiteParseUtils {
}
/**
+ * Parse lightweight details about a single APK file passed as an FD.
+ */
+ public static ParseResult<PackageLite> parseMonolithicPackageLite(ParseInput input,
+ FileDescriptor packageFd, String debugPathName, int flags) {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parseApkLite");
+ try {
+ final ParseResult<ApkLite> result = parseApkLite(input, packageFd, debugPathName,
+ flags);
+ if (result.isError()) {
+ return input.error(result);
+ }
+
+ final ApkLite baseApk = result.getResult();
+ final String packagePath = debugPathName;
+ return input.success(
+ new PackageLite(packagePath, baseApk.getPath(), baseApk, null /* splitNames */,
+ null /* isFeatureSplits */, null /* usesSplitNames */,
+ null /* configForSplit */, null /* splitApkPaths */,
+ null /* splitRevisionCodes */, baseApk.getTargetSdkVersion(),
+ null /* requiredSplitTypes */, null, /* splitTypes */
+ baseApk.isAllowUpdateOwnership()));
+ } finally {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+ }
+
+ /**
* Parse lightweight details about a directory of APKs.
*
* @param packageDir is the folder that contains split apks for a regular app
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 24e28e95cd98..5bcbaa10e95b 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -65,7 +65,6 @@ import android.util.Log;
import android.view.WindowManager.LayoutParams;
import com.android.internal.R;
-import com.android.internal.util.FrameworkStatsLog;
import java.io.IOException;
import java.lang.annotation.Retention;
@@ -2533,38 +2532,6 @@ public class UserManager {
}
/**
- * Returns the enum defined in the statsd UserLifecycleJourneyReported atom corresponding to the
- * user type.
- * @hide
- */
- public static int getUserTypeForStatsd(@NonNull String userType) {
- switch (userType) {
- case USER_TYPE_FULL_SYSTEM:
- return FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SYSTEM;
- case USER_TYPE_FULL_SECONDARY:
- return FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY;
- case USER_TYPE_FULL_GUEST:
- return FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_GUEST;
- case USER_TYPE_FULL_DEMO:
- return FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_DEMO;
- case USER_TYPE_FULL_RESTRICTED:
- return FrameworkStatsLog
- .USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_RESTRICTED;
- case USER_TYPE_PROFILE_MANAGED:
- return FrameworkStatsLog
- .USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__PROFILE_MANAGED;
- case USER_TYPE_SYSTEM_HEADLESS:
- return FrameworkStatsLog
- .USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__SYSTEM_HEADLESS;
- case USER_TYPE_PROFILE_CLONE:
- return FrameworkStatsLog
- .USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__PROFILE_CLONE;
- default:
- return FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__TYPE_UNKNOWN;
- }
- }
-
- /**
* @hide
* @deprecated Use {@link #isRestrictedProfile()}
*/
diff --git a/core/java/android/view/InsetsFrameProvider.java b/core/java/android/view/InsetsFrameProvider.java
index a69af24756a0..470c2801d838 100644
--- a/core/java/android/view/InsetsFrameProvider.java
+++ b/core/java/android/view/InsetsFrameProvider.java
@@ -62,9 +62,7 @@ public class InsetsFrameProvider implements Parcelable {
*/
public static final int SOURCE_ARBITRARY_RECTANGLE = 3;
- private final IBinder mOwner;
- private final int mIndex;
- private final @InsetsType int mType;
+ private final int mId;
/**
* The selection of the starting rectangle to be converted into source frame.
@@ -122,30 +120,30 @@ public class InsetsFrameProvider implements Parcelable {
* @param type the {@link InsetsType}.
* @see InsetsSource#createId(Object, int, int)
*/
- public InsetsFrameProvider(IBinder owner, @IntRange(from = 0, to = 2047) int index,
+ public InsetsFrameProvider(Object owner, @IntRange(from = 0, to = 2047) int index,
@InsetsType int type) {
- if (index < 0 || index >= 2048) {
- throw new IllegalArgumentException();
- }
-
- // This throws IllegalArgumentException if the type is not valid.
- WindowInsets.Type.indexOf(type);
-
- mOwner = owner;
- mIndex = index;
- mType = type;
+ mId = InsetsSource.createId(owner, index, type);
}
- public IBinder getOwner() {
- return mOwner;
+ /**
+ * Returns an unique integer which identifies the insets source.
+ */
+ public int getId() {
+ return mId;
}
+ /**
+ * Returns the index specified in {@link #InsetsFrameProvider(IBinder, int, int)}.
+ */
public int getIndex() {
- return mIndex;
+ return InsetsSource.getIndex(mId);
}
+ /**
+ * Returns the {@link InsetsType} specified in {@link #InsetsFrameProvider(IBinder, int, int)}.
+ */
public int getType() {
- return mType;
+ return InsetsSource.getType(mId);
}
public InsetsFrameProvider setSource(int source) {
@@ -211,9 +209,9 @@ public class InsetsFrameProvider implements Parcelable {
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("InsetsFrameProvider: {");
- sb.append("owner=").append(mOwner);
- sb.append(", index=").append(mIndex);
- sb.append(", type=").append(WindowInsets.Type.toString(mType));
+ sb.append("id=#").append(Integer.toHexString(mId));
+ sb.append(", index=").append(getIndex());
+ sb.append(", type=").append(WindowInsets.Type.toString(getType()));
sb.append(", source=").append(sourceToString(mSource));
sb.append(", flags=[").append(InsetsSource.flagsToString(mFlags)).append("]");
if (mInsetsSize != null) {
@@ -244,9 +242,7 @@ public class InsetsFrameProvider implements Parcelable {
}
public InsetsFrameProvider(Parcel in) {
- mOwner = in.readStrongBinder();
- mIndex = in.readInt();
- mType = in.readInt();
+ mId = in.readInt();
mSource = in.readInt();
mFlags = in.readInt();
mInsetsSize = in.readTypedObject(Insets.CREATOR);
@@ -256,9 +252,7 @@ public class InsetsFrameProvider implements Parcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
- out.writeStrongBinder(mOwner);
- out.writeInt(mIndex);
- out.writeInt(mType);
+ out.writeInt(mId);
out.writeInt(mSource);
out.writeInt(mFlags);
out.writeTypedObject(mInsetsSize, flags);
@@ -267,7 +261,7 @@ public class InsetsFrameProvider implements Parcelable {
}
public boolean idEquals(InsetsFrameProvider o) {
- return Objects.equals(mOwner, o.mOwner) && mIndex == o.mIndex && mType == o.mType;
+ return mId == o.mId;
}
@Override
@@ -279,8 +273,7 @@ public class InsetsFrameProvider implements Parcelable {
return false;
}
final InsetsFrameProvider other = (InsetsFrameProvider) o;
- return Objects.equals(mOwner, other.mOwner) && mIndex == other.mIndex
- && mType == other.mType && mSource == other.mSource && mFlags == other.mFlags
+ return mId == other.mId && mSource == other.mSource && mFlags == other.mFlags
&& Objects.equals(mInsetsSize, other.mInsetsSize)
&& Arrays.equals(mInsetsSizeOverrides, other.mInsetsSizeOverrides)
&& Objects.equals(mArbitraryRectangle, other.mArbitraryRectangle);
@@ -288,7 +281,7 @@ public class InsetsFrameProvider implements Parcelable {
@Override
public int hashCode() {
- return Objects.hash(mOwner, mIndex, mType, mSource, mFlags, mInsetsSize,
+ return Objects.hash(mId, mSource, mFlags, mInsetsSize,
Arrays.hashCode(mInsetsSizeOverrides), mArbitraryRectangle);
}
@@ -319,7 +312,7 @@ public class InsetsFrameProvider implements Parcelable {
protected InsetsSizeOverride(Parcel in) {
mWindowType = in.readInt();
- mInsetsSize = in.readParcelable(null, Insets.class);
+ mInsetsSize = in.readTypedObject(Insets.CREATOR);
}
public InsetsSizeOverride(int windowType, Insets insetsSize) {
@@ -354,7 +347,7 @@ public class InsetsFrameProvider implements Parcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(mWindowType);
- out.writeParcelable(mInsetsSize, flags);
+ out.writeTypedObject(mInsetsSize, flags);
}
@Override
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index bd48771ec4b3..114f4ed04ee6 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -271,7 +271,7 @@ public class InsetsSource implements Parcelable {
* @param index An owner may have multiple sources with the same type. For example, the system
* server might have multiple display cutout sources. This is used to identify
* which one is which. The value must be in a range of [0, 2047].
- * @param type The {@link WindowInsets.Type.InsetsType type} of the source.
+ * @param type The {@link InsetsType type} of the source.
* @return a unique integer as the identifier.
*/
public static int createId(Object owner, @IntRange(from = 0, to = 2047) int index,
@@ -282,11 +282,29 @@ public class InsetsSource implements Parcelable {
// owner takes top 16 bits;
// index takes 11 bits since the 6th bit;
// type takes bottom 5 bits.
- return (((owner != null ? owner.hashCode() : 1) % (1 << 16)) << 16)
+ return ((System.identityHashCode(owner) % (1 << 16)) << 16)
+ (index << 5)
+ WindowInsets.Type.indexOf(type);
}
+ /**
+ * Gets the index from the ID.
+ *
+ * @see #createId(Object, int, int)
+ */
+ public static int getIndex(int id) {
+ return (id % (1 << 16)) >> 5;
+ }
+
+ /**
+ * Gets the {@link InsetsType} from the ID.
+ *
+ * @see #createId(Object, int, int)
+ */
+ public static int getType(int id) {
+ return 1 << (id % 32);
+ }
+
public static String flagsToString(@Flags int flags) {
final StringJoiner joiner = new StringJoiner(" ");
if ((flags & FLAG_SUPPRESS_SCRIM) != 0) {
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 8f20e2d044ac..153bfde07758 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -11325,7 +11325,7 @@ public final class ViewRootImpl implements ViewParent,
// to sync the same frame in the same BBQ. That shouldn't be possible, but
// if it did happen, invoke markSyncReady so the active SSG doesn't get
// stuck.
- Log.e(mTag, "Unable to syncNextTransaction. Possibly something else is"
+ Log.w(mTag, "Unable to syncNextTransaction. Possibly something else is"
+ " trying to sync?");
surfaceSyncGroup.markSyncReady();
}
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index 628fc3140ee8..c0370cc5517d 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -21,6 +21,7 @@ import static android.app.ActivityOptions.ANIM_CUSTOM;
import static android.app.ActivityOptions.ANIM_FROM_STYLE;
import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
import static android.app.ActivityOptions.ANIM_SCALE_UP;
+import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
@@ -1067,6 +1068,11 @@ public final class TransitionInfo implements Parcelable {
return options;
}
+ public static AnimationOptions makeSceneTransitionAnimOptions() {
+ AnimationOptions options = new AnimationOptions(ANIM_SCENE_TRANSITION);
+ return options;
+ }
+
public int getType() {
return mType;
}
diff --git a/core/proto/android/companion/telecom.proto b/core/proto/android/companion/telecom.proto
index 3a9e5eeb4877..02ba7c5e39ff 100644
--- a/core/proto/android/companion/telecom.proto
+++ b/core/proto/android/companion/telecom.proto
@@ -25,7 +25,7 @@ message Telecom {
// Next index: 6
message Call {
// UUID representing this call
- int64 id = 1;
+ string id = 1;
message Origin {
// Caller's name and/or phone number; what a user would see displayed when receiving an
@@ -48,22 +48,23 @@ message Telecom {
}
Status status = 3;
- enum Control {
- UNKNOWN_CONTROL = 0;
- ACCEPT = 1;
- REJECT = 2;
- SILENCE = 3;
- MUTE = 4;
- UNMUTE = 5;
- END = 6;
- PUT_ON_HOLD = 7;
- TAKE_OFF_HOLD = 8;
- REJECT_AND_BLOCK = 9;
- IGNORE = 10;
- }
repeated Control controls = 4;
}
+ enum Control {
+ UNKNOWN_CONTROL = 0;
+ ACCEPT = 1;
+ REJECT = 2;
+ SILENCE = 3;
+ MUTE = 4;
+ UNMUTE = 5;
+ END = 6;
+ PUT_ON_HOLD = 7;
+ TAKE_OFF_HOLD = 8;
+ REJECT_AND_BLOCK = 9;
+ IGNORE = 10;
+ }
+
// The list of active calls.
repeated Call calls = 1;
// The list of requested calls or call changes.
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index ad864b13b16d..bc0af12e9569 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -96,12 +96,12 @@
<!-- Width of the navigation bar when it is placed vertically on the screen in car mode -->
<dimen name="navigation_bar_width_car_mode">96dp</dimen>
<!-- Height of notification icons in the status bar -->
- <dimen name="status_bar_icon_size">18sp</dimen>
+ <dimen name="status_bar_icon_size">22dip</dimen>
<!-- Desired size of system icons in status bar. -->
- <dimen name="status_bar_system_icon_size">15sp</dimen>
+ <dimen name="status_bar_system_icon_size">15dp</dimen>
<!-- Intrinsic size of most system icons in status bar. This is the default value that
is used if a Drawable reports an intrinsic size of 0. -->
- <dimen name="status_bar_system_icon_intrinsic_size">17sp</dimen>
+ <dimen name="status_bar_system_icon_intrinsic_size">17dp</dimen>
<!-- Size of the giant number (unread count) in the notifications -->
<dimen name="status_bar_content_number_size">48sp</dimen>
<!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
@@ -330,7 +330,7 @@
<dimen name="notification_icon_circle_start">16dp</dimen>
<!-- size (width and height) of the icon in the notification header -->
- <dimen name="notification_header_icon_size_ambient">18sp</dimen>
+ <dimen name="notification_header_icon_size_ambient">18dp</dimen>
<!-- The margin before the start of the app name in the header. -->
<dimen name="notification_header_app_name_margin_start">3dp</dimen>
diff --git a/core/tests/coretests/jni/NativeWorkSourceParcelTest.cpp b/core/tests/coretests/jni/NativeWorkSourceParcelTest.cpp
index db1f7bde4b4f..187e2c137f85 100644
--- a/core/tests/coretests/jni/NativeWorkSourceParcelTest.cpp
+++ b/core/tests/coretests/jni/NativeWorkSourceParcelTest.cpp
@@ -77,15 +77,18 @@ static void nativeUnparcelAndVerifyWorkSource(JNIEnv* env, jobject /* obj */, jo
Parcel* parcel = nativeGetParcelData(env, wsParcel);
int32_t endMarker;
- // read WorkSource and if no error read end marker
- status_t err = ws.readFromParcel(parcel) ?: parcel->readInt32(&endMarker);
- int32_t dataAvailable = parcel->dataAvail();
-
+ status_t err = ws.readFromParcel(parcel);
if (err != OK) {
- ALOGE("WorkSource readFromParcel failed %d", err);
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ StringPrintf("WorkSource readFromParcel failed: %d", err).c_str());
+ }
+ err = parcel->readInt32(&endMarker);
+ if (err != OK) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ StringPrintf("Failed to read endMarker: %d", err).c_str());
}
-
// Now we have a native WorkSource object, verify it.
+ int32_t dataAvailable = parcel->dataAvail();
if (dataAvailable > 0) { // not all data read from the parcel
jniThrowException(env, "java/lang/IllegalArgumentException",
StringPrintf("WorkSource contains more data than native read (%d)",
diff --git a/core/tests/coretests/src/android/view/InsetsSourceTest.java b/core/tests/coretests/src/android/view/InsetsSourceTest.java
index 6fa8f1117343..55680abb159d 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceTest.java
@@ -227,5 +227,25 @@ public class InsetsSourceTest {
assertEquals(numTotalSources, sources.size());
}
+ @Test
+ public void testGetIndex() {
+ for (int index = 0; index < 2048; index++) {
+ for (int type = FIRST; type <= LAST; type = type << 1) {
+ final int id = InsetsSource.createId(null, index, type);
+ assertEquals(index, InsetsSource.getIndex(id));
+ }
+ }
+ }
+
+ @Test
+ public void testGetType() {
+ for (int index = 0; index < 2048; index++) {
+ for (int type = FIRST; type <= LAST; type = type << 1) {
+ final int id = InsetsSource.createId(null, index, type);
+ assertEquals(type, InsetsSource.getType(id));
+ }
+ }
+ }
+
// Parcel and equals already tested via InsetsStateTest
}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 40cb7f2194e9..20a43fc1beb0 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -520,6 +520,8 @@ applications that come with the platform
<permission name="android.permission.SOUND_TRIGGER_RUN_IN_BATTERY_SAVER"/>
<!-- Permission required for CTS test - SatelliteManagerTest -->
<permission name="android.permission.SATELLITE_COMMUNICATION"/>
+ <!-- Permission required for GTS test - GtsAttestationVerificationDeviceSideTestCases -->
+ <permission name="android.permission.USE_ATTESTATION_VERIFICATION_SERVICE" />
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/graphics/java/android/graphics/MeshSpecification.java b/graphics/java/android/graphics/MeshSpecification.java
index 70311fdb2d1f..b1aae7f37c31 100644
--- a/graphics/java/android/graphics/MeshSpecification.java
+++ b/graphics/java/android/graphics/MeshSpecification.java
@@ -28,11 +28,40 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
- * Class responsible for holding specifications for {@link Mesh} creations. This class
- * generates a {@link MeshSpecification} via the Make method, where multiple parameters to set up
- * the mesh are supplied, including attributes, vertex stride, varyings, and
- * vertex/fragment shaders. There are also additional methods to provide an optional
- * {@link ColorSpace} as well as an alpha type.
+ * Class responsible for holding specifications for {@link Mesh} creations. This class generates a
+ * {@link MeshSpecification} via the
+ * {@link MeshSpecification#make(Attribute[], int, Varying[], String, String)} method,
+ * where multiple parameters to set up the mesh are supplied, including attributes, vertex stride,
+ * {@link Varying}, and vertex/fragment shaders. There are also additional methods to provide an
+ * optional {@link ColorSpace} as well as an alpha type.
+ *
+ * For example a vertex shader that leverages a {@link Varying} may look like the following:
+ *
+ * <pre>
+ * Varyings main(const Attributes attributes) {
+ * Varyings varyings;
+ * varyings.position = attributes.position;
+ * return varyings;
+ * }
+ * </pre>
+ *
+ * The corresponding fragment shader that may consume the varying look like the following:
+ *
+ * <pre>
+ * float2 main(const Varyings varyings, out float4 color) {
+ * color = vec4(1.0, 0.0, 0.0, 1.0);
+ * return varyings.position;
+ * }
+ * </pre>
+ *
+ * The color returned from this fragment shader is blended with the other parameters that are
+ * configured on the Paint object (ex. {@link Paint#setBlendMode(BlendMode)} used to draw the mesh.
+ *
+ * The position returned in the fragment shader can be consumed by any following fragment shaders in
+ * the shader chain.
+ *
+ * See https://developer.android.com/develop/ui/views/graphics/agsl for more information
+ * regarding Android Graphics Shader Language.
*
* Note that there are several limitations on various mesh specifications:
* 1. The max amount of attributes allowed is 8.
@@ -118,7 +147,11 @@ public class MeshSpecification {
public static final int TYPE_UBYTE4 = 4;
/**
- * Data class to represent a single attribute in a shader.
+ * Data class to represent a single attribute in a shader. An attribute is a variable that
+ * accompanies a vertex, this can be a color or texture coordinates.
+ *
+ * See https://developer.android.com/develop/ui/views/graphics/agsl for more information
+ * regarding Android Graphics Shader Language.
*
* Note that offset is the offset in number of bytes. For example, if we had two attributes
*
@@ -128,6 +161,10 @@ public class MeshSpecification {
* </pre>
*
* att1 would have an offset of 0, while att2 would have an offset of 12 bytes.
+ *
+ * This is consumed as part of
+ * {@link MeshSpecification#make(Attribute[], int, Varying[], String, String, ColorSpace, int)}
+ * to create a {@link MeshSpecification} instance.
*/
public static class Attribute {
@Type
@@ -175,7 +212,15 @@ public class MeshSpecification {
}
/**
- * Data class to represent a single varying variable.
+ * Data class to represent a single varying variable. A Varying variable can be altered by the
+ * vertex shader defined on the mesh but not by the fragment shader defined by AGSL.
+ *
+ * See https://developer.android.com/develop/ui/views/graphics/agsl for more information
+ * regarding Android Graphics Shader Language.
+ *
+ * This is consumed as part of
+ * {@link MeshSpecification#make(Attribute[], int, Varying[], String, String, ColorSpace, int)}
+ * to create a {@link MeshSpecification} instance.
*/
public static class Varying {
@Type
@@ -220,7 +265,7 @@ public class MeshSpecification {
/**
* Creates a {@link MeshSpecification} object for use within {@link Mesh}. This uses a default
- * color space of {@link ColorSpace.Named#SRGB} and {@link AlphaType} of
+ * color space of {@link ColorSpace.Named#SRGB} and alphaType of
* {@link #ALPHA_TYPE_PREMULTIPLIED}.
*
* @param attributes list of attributes represented by {@link Attribute}. Can hold a max of
@@ -233,7 +278,11 @@ public class MeshSpecification {
* the 6 varyings allowed.
* @param vertexShader vertex shader to be supplied to the mesh. Ensure that the position
* varying is set within the shader to get proper results.
+ * See {@link MeshSpecification} for an example vertex shader
+ * implementation
* @param fragmentShader fragment shader to be supplied to the mesh.
+ * See {@link MeshSpecification} for an example fragment shader
+ * implementation
* @return {@link MeshSpecification} object for use when creating {@link Mesh}
*/
@NonNull
@@ -253,7 +302,7 @@ public class MeshSpecification {
}
/**
- * Creates a {@link MeshSpecification} object. This uses a default {@link AlphaType} of
+ * Creates a {@link MeshSpecification} object. This uses a default alphaType of
* {@link #ALPHA_TYPE_PREMULTIPLIED}.
*
* @param attributes list of attributes represented by {@link Attribute}. Can hold a max of
@@ -266,7 +315,11 @@ public class MeshSpecification {
* the 6 varyings allowed.
* @param vertexShader vertex shader to be supplied to the mesh. Ensure that the position
* varying is set within the shader to get proper results.
+ * See {@link MeshSpecification} for an example vertex shader
+ * implementation
* @param fragmentShader fragment shader to be supplied to the mesh.
+ * See {@link MeshSpecification} for an example fragment shader
+ * implementation
* @param colorSpace {@link ColorSpace} to tell what color space to work in.
* @return {@link MeshSpecification} object for use when creating {@link Mesh}
*/
@@ -301,7 +354,11 @@ public class MeshSpecification {
* the 6 varyings allowed.
* @param vertexShader vertex shader to be supplied to the mesh. Ensure that the position
* varying is set within the shader to get proper results.
+ * See {@link MeshSpecification} for an example vertex shader
+ * implementation
* @param fragmentShader fragment shader to be supplied to the mesh.
+ * See {@link MeshSpecification} for an example fragment shader
+ * implementation
* @param colorSpace {@link ColorSpace} to tell what color space to work in.
* @param alphaType Describes how to interpret the alpha component for a pixel. Must be
* one of
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
index 544d75739547..410ae78dba1b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/RootTaskDisplayAreaOrganizer.java
@@ -181,6 +181,17 @@ public class RootTaskDisplayAreaOrganizer extends DisplayAreaOrganizer {
}
/**
+ * Returns the list of display ids that are tracked by a {@link DisplayAreaInfo}
+ */
+ public int[] getDisplayIds() {
+ int[] displayIds = new int[mDisplayAreasInfo.size()];
+ for (int i = 0; i < mDisplayAreasInfo.size(); i++) {
+ displayIds[i] = mDisplayAreasInfo.keyAt(i);
+ }
+ return displayIds;
+ }
+
+ /**
* Returns the {@link DisplayAreaInfo} of the {@link DisplayAreaInfo#displayId}.
*/
@Nullable
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java
index c767376d4f29..18615f7e353a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java
@@ -19,6 +19,8 @@ package com.android.wm.shell.activityembedding;
import static android.graphics.Matrix.MTRANS_X;
import static android.graphics.Matrix.MTRANS_Y;
+import static com.android.wm.shell.activityembedding.ActivityEmbeddingAnimationRunner.shouldUseSnapshotAnimationForClosingChange;
+
import android.annotation.CallSuper;
import android.graphics.Point;
import android.graphics.Rect;
@@ -97,10 +99,17 @@ class ActivityEmbeddingAnimationAdapter {
final Rect startBounds = change.getStartAbsBounds();
final Rect endBounds = change.getEndAbsBounds();
mContentBounds.set(startBounds);
- mContentRelOffset.set(change.getEndRelOffset());
- mContentRelOffset.offset(
- startBounds.left - endBounds.left,
- startBounds.top - endBounds.top);
+ // Put the transition to the top left for snapshot animation.
+ if (shouldUseSnapshotAnimationForClosingChange(mChange)) {
+ // TODO(b/275034335): Fix an issue that black hole when closing the right container
+ // in bounds change transition.
+ mContentRelOffset.set(0, 0);
+ } else {
+ mContentRelOffset.set(change.getEndRelOffset());
+ mContentRelOffset.offset(
+ startBounds.left - endBounds.left,
+ startBounds.top - endBounds.top);
+ }
} else {
mContentBounds.set(change.getEndAbsBounds());
mContentRelOffset.set(change.getEndRelOffset());
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
index 1df6ecda78c3..ab7c7d8ae6c8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java
@@ -21,6 +21,7 @@ import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET;
import static android.window.TransitionInfo.FLAG_IS_BEHIND_STARTING_WINDOW;
+import static com.android.wm.shell.activityembedding.ActivityEmbeddingAnimationSpec.createShowSnapshotForClosingAnimation;
import static com.android.wm.shell.transition.TransitionAnimationHelper.addBackgroundToTransition;
import static com.android.wm.shell.transition.TransitionAnimationHelper.edgeExtendWindow;
import static com.android.wm.shell.transition.TransitionAnimationHelper.getTransitionBackgroundColorIfSet;
@@ -42,6 +43,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.wm.shell.activityembedding.ActivityEmbeddingAnimationAdapter.SnapshotAdapter;
import com.android.wm.shell.common.ScreenshotUtils;
import com.android.wm.shell.util.TransitionUtil;
@@ -185,23 +187,23 @@ class ActivityEmbeddingAnimationRunner {
return createChangeAnimationAdapters(info, startTransaction);
}
if (TransitionUtil.isClosingType(info.getType())) {
- return createCloseAnimationAdapters(info);
+ return createCloseAnimationAdapters(info, startTransaction);
}
- return createOpenAnimationAdapters(info);
+ return createOpenAnimationAdapters(info, startTransaction);
}
@NonNull
private List<ActivityEmbeddingAnimationAdapter> createOpenAnimationAdapters(
- @NonNull TransitionInfo info) {
+ @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction) {
return createOpenCloseAnimationAdapters(info, true /* isOpening */,
- mAnimationSpec::loadOpenAnimation);
+ mAnimationSpec::loadOpenAnimation, startTransaction);
}
@NonNull
private List<ActivityEmbeddingAnimationAdapter> createCloseAnimationAdapters(
- @NonNull TransitionInfo info) {
+ @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction) {
return createOpenCloseAnimationAdapters(info, false /* isOpening */,
- mAnimationSpec::loadCloseAnimation);
+ mAnimationSpec::loadCloseAnimation, startTransaction);
}
/**
@@ -211,7 +213,8 @@ class ActivityEmbeddingAnimationRunner {
@NonNull
private List<ActivityEmbeddingAnimationAdapter> createOpenCloseAnimationAdapters(
@NonNull TransitionInfo info, boolean isOpening,
- @NonNull AnimationProvider animationProvider) {
+ @NonNull AnimationProvider animationProvider,
+ @NonNull SurfaceControl.Transaction startTransaction) {
// We need to know if the change window is only a partial of the whole animation screen.
// If so, we will need to adjust it to make the whole animation screen looks like one.
final List<TransitionInfo.Change> openingChanges = new ArrayList<>();
@@ -224,6 +227,8 @@ class ActivityEmbeddingAnimationRunner {
openingWholeScreenBounds.union(change.getEndAbsBounds());
} else {
closingChanges.add(change);
+ // Also union with the start bounds because the closing transition may be shrunk.
+ closingWholeScreenBounds.union(change.getStartAbsBounds());
closingWholeScreenBounds.union(change.getEndAbsBounds());
}
}
@@ -241,6 +246,17 @@ class ActivityEmbeddingAnimationRunner {
adapters.add(adapter);
}
for (TransitionInfo.Change change : closingChanges) {
+ if (shouldUseSnapshotAnimationForClosingChange(change)) {
+ SurfaceControl screenshot = getOrCreateScreenshot(change, change, startTransaction);
+ if (screenshot != null) {
+ final SnapshotAdapter snapshotAdapter = new SnapshotAdapter(
+ createShowSnapshotForClosingAnimation(), change, screenshot);
+ if (!isOpening) {
+ snapshotAdapter.overrideLayer(offsetLayer++);
+ }
+ adapters.add(snapshotAdapter);
+ }
+ }
final ActivityEmbeddingAnimationAdapter adapter = createOpenCloseAnimationAdapter(
info, change, animationProvider, closingWholeScreenBounds);
if (!isOpening) {
@@ -251,6 +267,22 @@ class ActivityEmbeddingAnimationRunner {
return adapters;
}
+ /**
+ * Returns whether we should use snapshot animation for the closing change.
+ * It's usually because the end bounds of the closing change are shrunk, which leaves a black
+ * area in the transition.
+ */
+ static boolean shouldUseSnapshotAnimationForClosingChange(
+ @NonNull TransitionInfo.Change closingChange) {
+ // Only check closing type because we only take screenshot for closing bounds-changing
+ // changes.
+ if (!TransitionUtil.isClosingType(closingChange.getMode())) {
+ return false;
+ }
+ // Don't need to take screenshot if there's no bounds change.
+ return !closingChange.getStartAbsBounds().equals(closingChange.getEndAbsBounds());
+ }
+
/** Sets the first frame to the {@code startTransaction} to avoid any flicker on start. */
private void prepareForFirstFrame(@NonNull SurfaceControl.Transaction startTransaction,
@NonNull List<ActivityEmbeddingAnimationAdapter> adapters) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
index cb8342a10a6a..19eff0e43169 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java
@@ -77,6 +77,15 @@ class ActivityEmbeddingAnimationSpec {
return new AlphaAnimation(alpha, alpha);
}
+ /**
+ * Animation that intended to show snapshot for closing animation because the closing end bounds
+ * are changed.
+ */
+ @NonNull
+ static Animation createShowSnapshotForClosingAnimation() {
+ return new AlphaAnimation(1f, 1f);
+ }
+
/** Animation for window that is opening in a change transition. */
@NonNull
Animation createChangeBoundsOpenAnimation(@NonNull TransitionInfo.Change change,
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 b9ff5f0e820a..f3efaade945f 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
@@ -2884,6 +2884,7 @@ public class BubbleStackView extends FrameLayout
/** Hide or show the manage menu for the currently expanded bubble. */
@VisibleForTesting
public void showManageMenu(boolean show) {
+ if ((mManageMenu.getVisibility() == VISIBLE) == show) return;
mShowingManage = show;
// This should not happen, since the manage menu is only visible when there's an expanded
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 80e920fefe5f..28368ef37061 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -189,12 +189,13 @@ public abstract class WMShellBaseModule {
static Optional<DragAndDropController> provideDragAndDropController(Context context,
ShellInit shellInit,
ShellController shellController,
+ ShellCommandHandler shellCommandHandler,
DisplayController displayController,
UiEventLogger uiEventLogger,
IconProvider iconProvider,
@ShellMainThread ShellExecutor mainExecutor) {
return Optional.ofNullable(DragAndDropController.create(context, shellInit, shellController,
- displayController, uiEventLogger, iconProvider, mainExecutor));
+ shellCommandHandler, displayController, uiEventLogger, iconProvider, mainExecutor));
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
index d1760ed75547..76ca68bbfa75 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
@@ -49,6 +49,12 @@ public class DesktopModeStatus {
"persist.wm.debug.desktop_veiled_resizing", true);
/**
+ * Flag to indicate is moving task to another display is enabled.
+ */
+ public static final boolean IS_DISPLAY_CHANGE_ENABLED = SystemProperties.getBoolean(
+ "persist.wm.debug.desktop_change_display", false);
+
+ /**
* Return {@code true} if desktop mode support is enabled
*/
public static boolean isProto1Enabled() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
index c814fe575e81..73a0e362a744 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt
@@ -235,6 +235,69 @@ class DesktopTasksController(
}
/**
+ * Move task to the next display.
+ *
+ * Queries all current known display ids and sorts them in ascending order. Then iterates
+ * through the list and looks for the display id that is larger than the display id for
+ * the passed in task. If a display with a higher id is not found, iterates through the list and
+ * finds the first display id that is not the display id for the passed in task.
+ *
+ * If a display matching the above criteria is found, re-parents the task to that display.
+ * No-op if no such display is found.
+ */
+ fun moveToNextDisplay(taskId: Int) {
+ val task = shellTaskOrganizer.getRunningTaskInfo(taskId)
+ if (task == null) {
+ ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: taskId=%d not found", taskId)
+ return
+ }
+ ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: taskId=%d taskDisplayId=%d",
+ taskId, task.displayId)
+
+ val displayIds = rootTaskDisplayAreaOrganizer.displayIds.sorted()
+ // Get the first display id that is higher than current task display id
+ var newDisplayId = displayIds.firstOrNull { displayId -> displayId > task.displayId }
+ if (newDisplayId == null) {
+ // No display with a higher id, get the first display id that is not the task display id
+ newDisplayId = displayIds.firstOrNull { displayId -> displayId < task.displayId }
+ }
+ if (newDisplayId == null) {
+ ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToNextDisplay: next display not found")
+ return
+ }
+ moveToDisplay(task, newDisplayId)
+ }
+
+ /**
+ * Move [task] to display with [displayId].
+ *
+ * No-op if task is already on that display per [RunningTaskInfo.displayId].
+ */
+ private fun moveToDisplay(task: RunningTaskInfo, displayId: Int) {
+ ProtoLog.v(WM_SHELL_DESKTOP_MODE, "moveToDisplay: taskId=%d displayId=%d",
+ task.taskId, displayId)
+
+ if (task.displayId == displayId) {
+ ProtoLog.d(WM_SHELL_DESKTOP_MODE, "moveToDisplay: task already on display")
+ return
+ }
+
+ val displayAreaInfo = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(displayId)
+ if (displayAreaInfo == null) {
+ ProtoLog.w(WM_SHELL_DESKTOP_MODE, "moveToDisplay: display not found")
+ return
+ }
+
+ val wct = WindowContainerTransaction()
+ wct.reparent(task.token, displayAreaInfo.token, true /* onTop */)
+ if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+ transitions.startTransition(TRANSIT_CHANGE, wct, null /* handler */)
+ } else {
+ shellTaskOrganizer.applyTransaction(wct)
+ }
+ }
+
+ /**
* Get windowing move for a given `taskId`
*
* @return [WindowingMode] for the task or [WINDOWING_MODE_UNDEFINED] if task is not found
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index 091de3a86461..be2489da3628 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -35,10 +35,14 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMA
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
+import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DRAG_AND_DROP;
+
import android.content.ClipDescription;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.res.Configuration;
+import android.graphics.HardwareRenderer;
import android.graphics.PixelFormat;
import android.util.Slog;
import android.util.SparseArray;
@@ -50,6 +54,8 @@ import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
+import androidx.annotation.BinderThread;
+import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.InstanceId;
@@ -58,25 +64,31 @@ import com.android.internal.protolog.common.ProtoLog;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.ExternalInterfaceBinder;
+import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.annotations.ExternalMainThread;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.splitscreen.SplitScreenController;
+import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
+import java.io.PrintWriter;
import java.util.ArrayList;
/**
* Handles the global drag and drop handling for the Shell.
*/
-public class DragAndDropController implements DisplayController.OnDisplaysChangedListener,
+public class DragAndDropController implements RemoteCallable<DragAndDropController>,
+ DisplayController.OnDisplaysChangedListener,
View.OnDragListener, ComponentCallbacks2 {
private static final String TAG = DragAndDropController.class.getSimpleName();
private final Context mContext;
private final ShellController mShellController;
+ private final ShellCommandHandler mShellCommandHandler;
private final DisplayController mDisplayController;
private final DragAndDropEventLogger mLogger;
private final IconProvider mIconProvider;
@@ -100,6 +112,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
public static DragAndDropController create(Context context,
ShellInit shellInit,
ShellController shellController,
+ ShellCommandHandler shellCommandHandler,
DisplayController displayController,
UiEventLogger uiEventLogger,
IconProvider iconProvider,
@@ -107,19 +120,21 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
if (!context.getResources().getBoolean(R.bool.config_enableShellDragDrop)) {
return null;
}
- return new DragAndDropController(context, shellInit, shellController, displayController,
- uiEventLogger, iconProvider, mainExecutor);
+ return new DragAndDropController(context, shellInit, shellController, shellCommandHandler,
+ displayController, uiEventLogger, iconProvider, mainExecutor);
}
DragAndDropController(Context context,
ShellInit shellInit,
ShellController shellController,
+ ShellCommandHandler shellCommandHandler,
DisplayController displayController,
UiEventLogger uiEventLogger,
IconProvider iconProvider,
ShellExecutor mainExecutor) {
mContext = context;
mShellController = shellController;
+ mShellCommandHandler = shellCommandHandler;
mDisplayController = displayController;
mLogger = new DragAndDropEventLogger(uiEventLogger);
mIconProvider = iconProvider;
@@ -137,6 +152,23 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
mMainExecutor.executeDelayed(() -> {
mDisplayController.addDisplayWindowListener(this);
}, 0);
+ mShellController.addExternalInterface(KEY_EXTRA_SHELL_DRAG_AND_DROP,
+ this::createExternalInterface, this);
+ mShellCommandHandler.addDumpCallback(this::dump, this);
+ }
+
+ private ExternalInterfaceBinder createExternalInterface() {
+ return new IDragAndDropImpl(this);
+ }
+
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ public ShellExecutor getRemoteCallExecutor() {
+ return mMainExecutor;
}
/**
@@ -156,7 +188,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
mListeners.remove(listener);
}
- private void notifyListeners() {
+ private void notifyDragStarted() {
for (int i = 0; i < mListeners.size(); i++) {
mListeners.get(i).onDragStarted();
}
@@ -273,7 +305,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
pd.dragLayout.prepare(mDisplayController.getDisplayLayout(displayId),
event.getClipData(), loggerSessionId);
setDropTargetWindowVisibility(pd, View.VISIBLE);
- notifyListeners();
+ notifyDragStarted();
break;
case ACTION_DRAG_ENTERED:
pd.dragLayout.show();
@@ -327,13 +359,7 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
}
private void setDropTargetWindowVisibility(PerDisplay pd, int visibility) {
- ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP,
- "Set drop target window visibility: displayId=%d visibility=%d",
- pd.displayId, visibility);
- pd.rootView.setVisibility(visibility);
- if (visibility == View.VISIBLE) {
- pd.rootView.requestApplyInsets();
- }
+ pd.setWindowVisibility(visibility);
}
private String getMimeTypes(ClipDescription description) {
@@ -347,6 +373,18 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
return mimeTypes;
}
+ /**
+ * Returns if any displays are currently ready to handle a drag/drop.
+ */
+ private boolean isReadyToHandleDrag() {
+ for (int i = 0; i < mDisplayDropTargets.size(); i++) {
+ if (mDisplayDropTargets.valueAt(i).mHasDrawn) {
+ return true;
+ }
+ }
+ return false;
+ }
+
// Note: Component callbacks are always called on the main thread of the process
@ExternalMainThread
@Override
@@ -372,12 +410,53 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
// Do nothing
}
- private static class PerDisplay {
+ /**
+ * Dumps information about this controller.
+ */
+ public void dump(@NonNull PrintWriter pw, String prefix) {
+ pw.println(prefix + TAG);
+ pw.println(prefix + " listeners=" + mListeners.size());
+ }
+
+ /**
+ * The interface for calls from outside the host process.
+ */
+ @BinderThread
+ private static class IDragAndDropImpl extends IDragAndDrop.Stub
+ implements ExternalInterfaceBinder {
+ private DragAndDropController mController;
+
+ public IDragAndDropImpl(DragAndDropController controller) {
+ mController = controller;
+ }
+
+ /**
+ * Invalidates this instance, preventing future calls from updating the controller.
+ */
+ @Override
+ public void invalidate() {
+ mController = null;
+ }
+
+ @Override
+ public boolean isReadyToHandleDrag() {
+ boolean[] result = new boolean[1];
+ executeRemoteCallWithTaskPermission(mController, "isReadyToHandleDrag",
+ controller -> result[0] = controller.isReadyToHandleDrag(),
+ true /* blocking */
+ );
+ return result[0];
+ }
+ }
+
+ private static class PerDisplay implements HardwareRenderer.FrameDrawingCallback {
final int displayId;
final Context context;
final WindowManager wm;
final FrameLayout rootView;
final DragLayout dragLayout;
+ // Tracks whether the window has fully drawn since it was last made visible
+ boolean mHasDrawn;
boolean isHandlingDrag;
// A count of the number of active drags in progress to ensure that we only hide the window
@@ -391,5 +470,25 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange
rootView = rv;
dragLayout = dl;
}
+
+ private void setWindowVisibility(int visibility) {
+ ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP,
+ "Set drop target window visibility: displayId=%d visibility=%d",
+ displayId, visibility);
+ rootView.setVisibility(visibility);
+ if (visibility == View.VISIBLE) {
+ rootView.requestApplyInsets();
+ if (!mHasDrawn && rootView.getViewRootImpl() != null) {
+ rootView.getViewRootImpl().registerRtFrameCallback(this);
+ }
+ } else {
+ mHasDrawn = false;
+ }
+ }
+
+ @Override
+ public void onFrameDraw(long frame) {
+ mHasDrawn = true;
+ }
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/IDragAndDrop.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/IDragAndDrop.aidl
new file mode 100644
index 000000000000..aeb0c63fa4c5
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/IDragAndDrop.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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.wm.shell.draganddrop;
+
+/**
+ * Interface that is exposed to remote callers to manipulate drag and drop.
+ */
+interface IDragAndDrop {
+ /**
+ * Returns whether the shell drop target is showing and will handle a drag/drop.
+ */
+ boolean isReadyToHandleDrag() = 1;
+}
+// Last id = 1 \ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java
index bfa63909cd47..5f54f58557d1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellSharedConstants.java
@@ -42,4 +42,6 @@ public class ShellSharedConstants {
public static final String KEY_EXTRA_SHELL_FLOATING_TASKS = "extra_shell_floating_tasks";
// See IDesktopMode.aidl
public static final String KEY_EXTRA_SHELL_DESKTOP_MODE = "extra_shell_desktop_mode";
+ // See IDragAndDrop.aidl
+ public static final String KEY_EXTRA_SHELL_DRAG_AND_DROP = "extra_shell_drag_and_drop";
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index 6e9ecdaf55e7..1ee52ae00645 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -21,6 +21,7 @@ import static android.app.ActivityOptions.ANIM_CUSTOM;
import static android.app.ActivityOptions.ANIM_NONE;
import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
import static android.app.ActivityOptions.ANIM_SCALE_UP;
+import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
@@ -625,6 +626,9 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler {
} else if ((changeFlags & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0 && isOpeningType) {
// This received a transferred starting window, so don't animate
return null;
+ } else if (overrideType == ANIM_SCENE_TRANSITION) {
+ // If there's a scene-transition, then jump-cut.
+ return null;
} else {
a = loadAttributeAnimation(info, change, wallpaperTransit, mTransitionAnimation);
}
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 f79f1f7a27b1..a73ab776486b 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
@@ -533,8 +533,12 @@ public class Transitions implements RemoteCallable<Transitions>,
final int layer;
// Put all the OPEN/SHOW on top
if ((change.getFlags() & FLAG_IS_WALLPAPER) != 0) {
- // Wallpaper is always at the bottom.
- layer = -zSplitLine;
+ // Wallpaper is always at the bottom, opening wallpaper on top of closing one.
+ if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT) {
+ layer = -zSplitLine + numChanges - i;
+ } else {
+ layer = -zSplitLine - i;
+ }
} else if (mode == TRANSIT_OPEN || mode == TRANSIT_TO_FRONT) {
if (isOpening) {
// put on top
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 4cda5715ac1f..12edc3548642 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -326,6 +326,13 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
decoration.closeHandleMenu();
} else if (id == R.id.collapse_menu_button) {
decoration.closeHandleMenu();
+ } else if (id == R.id.select_button) {
+ if (DesktopModeStatus.IS_DISPLAY_CHANGE_ENABLED) {
+ // TODO(b/278084491): dev option to enable display switching
+ // remove when select is implemented
+ mDesktopTasksController.ifPresent(c -> c.moveToNextDisplay(mTaskId));
+ decoration.closeHandleMenu();
+ }
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
index ed3cca078084..ac4a597c15d1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.java
@@ -187,6 +187,8 @@ class HandleMenu {
final View moreActionsPillView = mMoreActionsPill.mWindowViewHost.getView();
final Button closeBtn = moreActionsPillView.findViewById(R.id.close_button);
closeBtn.setOnClickListener(mOnClickListener);
+ final Button selectBtn = moreActionsPillView.findViewById(R.id.select_button);
+ selectBtn.setOnClickListener(mOnClickListener);
}
/**
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
index b6d92814ad43..b5937ae80f0a 100644
--- a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
@@ -21,6 +21,9 @@
<option name="run-command" value="setprop ro.test_harness 1 ; am force-stop com.google.android.apps.nexuslauncher" />
<!-- Ensure output directory is empty at the start -->
<option name="run-command" value="rm -rf /sdcard/flicker" />
+ <!-- Increase trace size: 20mb for WM and 80mb for SF -->
+ <option name="run-command" value="cmd window tracing size 20480" />
+ <option name="run-command" value="su root service call SurfaceFlinger 1029 i32 81920" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<option name="run-command" value="settings put secure show_ime_with_hard_keyboard 1" />
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
index f506969f51df..1335ebf105a6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt
@@ -31,6 +31,7 @@ import android.view.WindowManager.TRANSIT_CHANGE
import android.view.WindowManager.TRANSIT_NONE
import android.view.WindowManager.TRANSIT_OPEN
import android.view.WindowManager.TRANSIT_TO_FRONT
+import android.window.DisplayAreaInfo
import android.window.TransitionRequestInfo
import android.window.WindowContainerTransaction
import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER
@@ -344,6 +345,57 @@ class DesktopTasksControllerTest : ShellTestCase() {
}
@Test
+ fun moveToNextDisplay_noOtherDisplays() {
+ whenever(rootTaskDisplayAreaOrganizer.displayIds).thenReturn(intArrayOf(DEFAULT_DISPLAY))
+ val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
+ controller.moveToNextDisplay(task.taskId)
+ verifyWCTNotExecuted()
+ }
+
+ @Test
+ fun moveToNextDisplay_moveFromFirstToSecondDisplay() {
+ // Set up two display ids
+ whenever(rootTaskDisplayAreaOrganizer.displayIds)
+ .thenReturn(intArrayOf(DEFAULT_DISPLAY, SECOND_DISPLAY))
+ // Create a mock for the target display area: second display
+ val secondDisplayArea = DisplayAreaInfo(MockToken().token(), SECOND_DISPLAY, 0)
+ whenever(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(SECOND_DISPLAY))
+ .thenReturn(secondDisplayArea)
+
+ val task = setUpFreeformTask(displayId = DEFAULT_DISPLAY)
+ controller.moveToNextDisplay(task.taskId)
+ with(getLatestWct(expectTransition = TRANSIT_CHANGE)) {
+ assertThat(hierarchyOps).hasSize(1)
+ assertThat(hierarchyOps[0].container).isEqualTo(task.token.asBinder())
+ assertThat(hierarchyOps[0].isReparent).isTrue()
+ assertThat(hierarchyOps[0].newParent).isEqualTo(secondDisplayArea.token.asBinder())
+ assertThat(hierarchyOps[0].toTop).isTrue()
+ }
+ }
+
+ @Test
+ fun moveToNextDisplay_moveFromSecondToFirstDisplay() {
+ // Set up two display ids
+ whenever(rootTaskDisplayAreaOrganizer.displayIds)
+ .thenReturn(intArrayOf(DEFAULT_DISPLAY, SECOND_DISPLAY))
+ // Create a mock for the target display area: default display
+ val defaultDisplayArea = DisplayAreaInfo(MockToken().token(), DEFAULT_DISPLAY, 0)
+ whenever(rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY))
+ .thenReturn(defaultDisplayArea)
+
+ val task = setUpFreeformTask(displayId = SECOND_DISPLAY)
+ controller.moveToNextDisplay(task.taskId)
+
+ with(getLatestWct(expectTransition = TRANSIT_CHANGE)) {
+ assertThat(hierarchyOps).hasSize(1)
+ assertThat(hierarchyOps[0].container).isEqualTo(task.token.asBinder())
+ assertThat(hierarchyOps[0].isReparent).isTrue()
+ assertThat(hierarchyOps[0].newParent).isEqualTo(defaultDisplayArea.token.asBinder())
+ assertThat(hierarchyOps[0].toTop).isTrue()
+ }
+ }
+
+ @Test
fun getTaskWindowingMode() {
val fullscreenTask = setUpFullscreenTask()
val freeformTask = setUpFreeformTask()
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
index 523cb6629d9a..54f36f61859d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
@@ -48,6 +48,7 @@ import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
@@ -71,6 +72,8 @@ public class DragAndDropControllerTest extends ShellTestCase {
@Mock
private ShellController mShellController;
@Mock
+ private ShellCommandHandler mShellCommandHandler;
+ @Mock
private DisplayController mDisplayController;
@Mock
private UiEventLogger mUiEventLogger;
@@ -89,7 +92,8 @@ public class DragAndDropControllerTest extends ShellTestCase {
public void setUp() throws RemoteException {
MockitoAnnotations.initMocks(this);
mController = new DragAndDropController(mContext, mShellInit, mShellController,
- mDisplayController, mUiEventLogger, mIconProvider, mMainExecutor);
+ mShellCommandHandler, mDisplayController, mUiEventLogger, mIconProvider,
+ mMainExecutor);
mController.onInit();
}
diff --git a/libs/hwui/renderthread/CacheManager.cpp b/libs/hwui/renderthread/CacheManager.cpp
index 7e9d44fbdbd1..c00a2707e0a2 100644
--- a/libs/hwui/renderthread/CacheManager.cpp
+++ b/libs/hwui/renderthread/CacheManager.cpp
@@ -29,6 +29,7 @@
#include "Layer.h"
#include "Properties.h"
#include "RenderThread.h"
+#include "VulkanManager.h"
#include "pipeline/skia/ATraceMemoryDump.h"
#include "pipeline/skia/ShaderCache.h"
#include "pipeline/skia/SkiaMemoryTracer.h"
@@ -182,8 +183,14 @@ void CacheManager::dumpMemoryUsage(String8& log, const RenderState* renderState)
}
log.appendFormat("Contexts: %zu (stopped = %zu)\n", mCanvasContexts.size(), stoppedContexts);
+ auto vkInstance = VulkanManager::peekInstance();
if (!mGrContext) {
- log.appendFormat("No GPU context.\n");
+ if (!vkInstance) {
+ log.appendFormat("No GPU context.\n");
+ } else {
+ log.appendFormat("No GrContext; however %d remaining Vulkan refs",
+ vkInstance->getStrongCount() - 1);
+ }
return;
}
std::vector<skiapipeline::ResourcePair> cpuResourceMap = {
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index f198bca9060c..4cffc6c2efe3 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -107,11 +107,11 @@ GrVkGetProc VulkanManager::sSkiaGetProp = [](const char* proc_name, VkInstance i
#define GET_INST_PROC(F) m##F = (PFN_vk##F)vkGetInstanceProcAddr(mInstance, "vk" #F)
#define GET_DEV_PROC(F) m##F = (PFN_vk##F)vkGetDeviceProcAddr(mDevice, "vk" #F)
-sp<VulkanManager> VulkanManager::getInstance() {
- // cache a weakptr to the context to enable a second thread to share the same vulkan state
- static wp<VulkanManager> sWeakInstance = nullptr;
- static std::mutex sLock;
+// cache a weakptr to the context to enable a second thread to share the same vulkan state
+static wp<VulkanManager> sWeakInstance = nullptr;
+static std::mutex sLock;
+sp<VulkanManager> VulkanManager::getInstance() {
std::lock_guard _lock{sLock};
sp<VulkanManager> vulkanManager = sWeakInstance.promote();
if (!vulkanManager.get()) {
@@ -122,6 +122,11 @@ sp<VulkanManager> VulkanManager::getInstance() {
return vulkanManager;
}
+sp<VulkanManager> VulkanManager::peekInstance() {
+ std::lock_guard _lock{sLock};
+ return sWeakInstance.promote();
+}
+
VulkanManager::~VulkanManager() {
if (mDevice != VK_NULL_HANDLE) {
mDeviceWaitIdle(mDevice);
@@ -404,9 +409,13 @@ void VulkanManager::initialize() {
}
}
-sk_sp<GrDirectContext> VulkanManager::createContext(const GrContextOptions& options,
- ContextType contextType) {
+static void onGrContextReleased(void* context) {
+ VulkanManager* manager = (VulkanManager*)context;
+ manager->decStrong((void*)onGrContextReleased);
+}
+sk_sp<GrDirectContext> VulkanManager::createContext(GrContextOptions& options,
+ ContextType contextType) {
GrVkBackendContext backendContext;
backendContext.fInstance = mInstance;
backendContext.fPhysicalDevice = mPhysicalDevice;
@@ -418,6 +427,11 @@ sk_sp<GrDirectContext> VulkanManager::createContext(const GrContextOptions& opti
backendContext.fDeviceFeatures2 = &mPhysicalDeviceFeatures2;
backendContext.fGetProc = sSkiaGetProp;
+ LOG_ALWAYS_FATAL_IF(options.fContextDeleteProc != nullptr, "Conflicting fContextDeleteProcs!");
+ this->incStrong((void*)onGrContextReleased);
+ options.fContextDeleteContext = this;
+ options.fContextDeleteProc = onGrContextReleased;
+
return GrDirectContext::MakeVulkan(backendContext, options);
}
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index c5196eeccea3..00a40c0c85c3 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -66,6 +66,7 @@ class RenderThread;
class VulkanManager final : public RefBase {
public:
static sp<VulkanManager> getInstance();
+ static sp<VulkanManager> peekInstance();
// Sets up the vulkan context that is shared amonst all clients of the VulkanManager. This must
// be call once before use of the VulkanManager. Multiple calls after the first will simiply
@@ -109,7 +110,7 @@ public:
};
// returns a Skia graphic context used to draw content on the specified thread
- sk_sp<GrDirectContext> createContext(const GrContextOptions& options,
+ sk_sp<GrDirectContext> createContext(GrContextOptions& options,
ContextType contextType = ContextType::kRenderThread);
uint32_t getDriverVersion() const { return mDriverVersion; }
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index e73cf87ba9f3..3123ee6dd4d7 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -1237,6 +1237,9 @@ public class AudioSystem
public static final Set<Integer> DEVICE_IN_ALL_SCO_SET;
/** @hide */
public static final Set<Integer> DEVICE_IN_ALL_USB_SET;
+ /** @hide */
+ public static final Set<Integer> DEVICE_IN_ALL_BLE_SET;
+
static {
DEVICE_IN_ALL_SET = new HashSet<>();
DEVICE_IN_ALL_SET.add(DEVICE_IN_COMMUNICATION);
@@ -1276,6 +1279,66 @@ public class AudioSystem
DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_ACCESSORY);
DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_DEVICE);
DEVICE_IN_ALL_USB_SET.add(DEVICE_IN_USB_HEADSET);
+
+ DEVICE_IN_ALL_BLE_SET = new HashSet<>();
+ DEVICE_IN_ALL_BLE_SET.add(DEVICE_IN_BLE_HEADSET);
+ }
+
+ /** @hide */
+ public static boolean isBluetoothDevice(int deviceType) {
+ return isBluetoothA2dpOutDevice(deviceType)
+ || isBluetoothScoDevice(deviceType)
+ || isBluetoothLeDevice(deviceType);
+ }
+
+ /** @hide */
+ public static boolean isBluetoothOutDevice(int deviceType) {
+ return isBluetoothA2dpOutDevice(deviceType)
+ || isBluetoothScoOutDevice(deviceType)
+ || isBluetoothLeOutDevice(deviceType);
+ }
+
+ /** @hide */
+ public static boolean isBluetoothInDevice(int deviceType) {
+ return isBluetoothScoInDevice(deviceType)
+ || isBluetoothLeInDevice(deviceType);
+ }
+
+ /** @hide */
+ public static boolean isBluetoothA2dpOutDevice(int deviceType) {
+ return DEVICE_OUT_ALL_A2DP_SET.contains(deviceType);
+ }
+
+ /** @hide */
+ public static boolean isBluetoothScoOutDevice(int deviceType) {
+ return DEVICE_OUT_ALL_SCO_SET.contains(deviceType);
+ }
+
+ /** @hide */
+ public static boolean isBluetoothScoInDevice(int deviceType) {
+ return DEVICE_IN_ALL_SCO_SET.contains(deviceType);
+ }
+
+ /** @hide */
+ public static boolean isBluetoothScoDevice(int deviceType) {
+ return isBluetoothScoOutDevice(deviceType)
+ || isBluetoothScoInDevice(deviceType);
+ }
+
+ /** @hide */
+ public static boolean isBluetoothLeOutDevice(int deviceType) {
+ return DEVICE_OUT_ALL_BLE_SET.contains(deviceType);
+ }
+
+ /** @hide */
+ public static boolean isBluetoothLeInDevice(int deviceType) {
+ return DEVICE_IN_ALL_BLE_SET.contains(deviceType);
+ }
+
+ /** @hide */
+ public static boolean isBluetoothLeDevice(int deviceType) {
+ return isBluetoothLeOutDevice(deviceType)
+ || isBluetoothLeInDevice(deviceType);
}
/** @hide */
diff --git a/native/android/activity_manager.cpp b/native/android/activity_manager.cpp
index 155a355241c8..bc6a84f01517 100644
--- a/native/android/activity_manager.cpp
+++ b/native/android/activity_manager.cpp
@@ -45,7 +45,7 @@ struct UidObserver : public BnUidObserver, public virtual IBinder::DeathRecipien
void onUidIdle(uid_t uid, bool disabled) override;
void onUidStateChanged(uid_t uid, int32_t procState, int64_t procStateSeq,
int32_t capability) override;
- void onUidProcAdjChanged(uid_t uid) override;
+ void onUidProcAdjChanged(uid_t uid, int32_t adj) override;
// IBinder::DeathRecipient implementation
void binderDied(const wp<IBinder>& who) override;
@@ -121,7 +121,7 @@ void UidObserver::onUidActive(uid_t uid __unused) {}
void UidObserver::onUidIdle(uid_t uid __unused, bool disabled __unused) {}
-void UidObserver::onUidProcAdjChanged(uid_t uid __unused) {}
+void UidObserver::onUidProcAdjChanged(uid_t uid __unused, int32_t adj __unused) {}
void UidObserver::onUidStateChanged(uid_t uid, int32_t procState,
int64_t procStateSeq __unused,
diff --git a/packages/CredentialManager/res/values/strings.xml b/packages/CredentialManager/res/values/strings.xml
index 340285760cda..7d71bd5c91ab 100644
--- a/packages/CredentialManager/res/values/strings.xml
+++ b/packages/CredentialManager/res/values/strings.xml
@@ -78,8 +78,12 @@
<!-- This text is followed by a list of one or more options. [CHAR LIMIT=200] -->
<string name="save_credential_to_title">Save <xliff:g id="credentialTypes" example="passkey">%1$s</xliff:g> to</string>
- <!-- This appears as the title of the modal bottom sheet for users to choose to create a passkey on another device. [CHAR LIMIT=200] -->
- <string name="create_passkey_in_other_device_title">Create passkey in another device?</string>
+ <!-- This appears as the title of the modal bottom sheet for users to confirm to create a passkey on another device. [CHAR LIMIT=200] -->
+ <string name="create_passkey_in_other_device_title">Create passkey on another device?</string>
+ <!-- This appears as the title of the modal bottom sheet for users to confirm to save a password on another device. [CHAR LIMIT=200] -->
+ <string name="save_password_on_other_device_title">Save password on another device?</string>
+ <!-- This appears as the title of the modal bottom sheet for users to confirm to save a sign-in credential on another device. [CHAR LIMIT=200] -->
+ <string name="save_sign_in_on_other_device_title">Save sign-in on another device?</string>
<!-- This appears as the title of the modal bottom sheet for users to confirm whether they should use the selected provider as default or not. [CHAR LIMIT=200] -->
<string name="use_provider_for_all_title">Use <xliff:g id="providerInfoDisplayName" example="Google Password Manager">%1$s</xliff:g> for all your sign-ins?</string>
<!-- This appears as the description body of the modal bottom sheet for users to confirm whether they should use the selected provider as default or not. [CHAR LIMIT=300] -->
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
index 6549b2d0187c..1fb5e3f853b2 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialSelectorActivity.kt
@@ -50,6 +50,8 @@ class CredentialSelectorActivity : ComponentActivity() {
super.onCreate(savedInstanceState)
overrideActivityTransition(Activity.OVERRIDE_TRANSITION_OPEN,
0, 0)
+ overrideActivityTransition(Activity.OVERRIDE_TRANSITION_CLOSE,
+ 0, 0)
Log.d(Constants.LOG_TAG, "Creating new CredentialSelectorActivity")
try {
val (isCancellationRequest, shouldShowCancellationUi, _) =
diff --git a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
index dfa517b118b3..d16120fee452 100644
--- a/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
+++ b/packages/CredentialManager/src/com/android/credentialmanager/createflow/CreateCredentialComponents.kt
@@ -465,7 +465,17 @@ fun ExternalOnlySelectionCard(
SheetContainerCard {
item { HeadlineIcon(imageVector = Icons.Outlined.QrCodeScanner) }
item { Divider(thickness = 16.dp, color = Color.Transparent) }
- item { HeadlineText(text = stringResource(R.string.create_passkey_in_other_device_title)) }
+ item {
+ HeadlineText(
+ text = stringResource(
+ when (requestDisplayInfo.type) {
+ CredentialType.PASSKEY -> R.string.create_passkey_in_other_device_title
+ CredentialType.PASSWORD -> R.string.save_password_on_other_device_title
+ else -> R.string.save_sign_in_on_other_device_title
+ }
+ )
+ )
+ }
item { Divider(thickness = 24.dp, color = Color.Transparent) }
item {
CredentialContainerCard {
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java b/packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java
index 4c5875b1f2d9..7b17cbdd3a1e 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/DeleteStagedFileOnResult.java
@@ -16,14 +16,14 @@
package com.android.packageinstaller;
+import static com.android.packageinstaller.PackageInstallerActivity.EXTRA_STAGED_SESSION_ID;
+
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.Nullable;
-import java.io.File;
-
/**
* Trampoline activity. Calls PackageInstallerActivity and deletes staged install file onResult.
*/
@@ -52,8 +52,13 @@ public class DeleteStagedFileOnResult extends Activity {
super.onDestroy();
if (isFinishing()) {
- File sourceFile = new File(getIntent().getData().getPath());
- new Thread(sourceFile::delete).start();
+ // While we expect PIA/InstallStaging to abandon/commit the session, still there
+ // might be cases when the session becomes orphan.
+ int sessionId = getIntent().getIntExtra(EXTRA_STAGED_SESSION_ID, 0);
+ try {
+ getPackageManager().getPackageInstaller().abandonSession(sessionId);
+ } catch (SecurityException ignored) {
+ }
}
}
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
index c6217ece800d..7bea33971259 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallInstalling.java
@@ -16,17 +16,17 @@
package com.android.packageinstaller;
+import static com.android.packageinstaller.PackageInstallerActivity.EXTRA_STAGED_SESSION_ID;
+
import android.app.PendingIntent;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInstaller;
-import android.content.pm.PackageInstaller.InstallInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
-import android.os.Process;
import android.util.Log;
import android.view.View;
import android.widget.Button;
@@ -34,10 +34,7 @@ import android.widget.Button;
import androidx.annotation.Nullable;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
/**
* Send package to the package manager and handle results from package manager. Once the
@@ -77,7 +74,7 @@ public class InstallInstalling extends AlertActivity {
.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
mPackageURI = getIntent().getData();
- if ("package".equals(mPackageURI.getScheme())) {
+ if (PackageInstallerActivity.SCHEME_PACKAGE.equals(mPackageURI.getScheme())) {
try {
getPackageManager().installExistingPackage(appInfo.packageName);
launchSuccess();
@@ -86,6 +83,8 @@ public class InstallInstalling extends AlertActivity {
PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
} else {
+ // ContentResolver.SCHEME_FILE
+ // STAGED_SESSION_ID extra contains an ID of a previously staged install session.
final File sourceFile = new File(mPackageURI.getPath());
PackageUtil.AppSnippet as = PackageUtil.getAppSnippet(this, appInfo, sourceFile);
@@ -122,41 +121,6 @@ public class InstallInstalling extends AlertActivity {
// Does not happen
}
} else {
- PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
- PackageInstaller.SessionParams.MODE_FULL_INSTALL);
- final Uri referrerUri = getIntent().getParcelableExtra(Intent.EXTRA_REFERRER);
- params.setPackageSource(
- referrerUri != null ? PackageInstaller.PACKAGE_SOURCE_DOWNLOADED_FILE
- : PackageInstaller.PACKAGE_SOURCE_LOCAL_FILE);
- params.setInstallAsInstantApp(false);
- params.setReferrerUri(referrerUri);
- params.setOriginatingUri(getIntent()
- .getParcelableExtra(Intent.EXTRA_ORIGINATING_URI));
- params.setOriginatingUid(getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,
- Process.INVALID_UID));
- params.setInstallerPackageName(getIntent().getStringExtra(
- Intent.EXTRA_INSTALLER_PACKAGE_NAME));
- params.setInstallReason(PackageManager.INSTALL_REASON_USER);
-
- File file = new File(mPackageURI.getPath());
- try {
- final InstallInfo result = getPackageManager().getPackageInstaller()
- .readInstallInfo(file, 0);
- params.setAppPackageName(result.getPackageName());
- params.setInstallLocation(result.getInstallLocation());
- try {
- params.setSize(result.calculateInstalledSize(params));
- } catch (IOException e) {
- e.printStackTrace();
- params.setSize(file.length());
- }
- } catch (PackageInstaller.PackageParsingException e) {
-
- Log.e(LOG_TAG, "Cannot parse package " + file + ". Assuming defaults.", e);
- Log.e(LOG_TAG,
- "Cannot calculate installed size " + file + ". Try only apk size.");
- params.setSize(file.length());
- }
try {
mInstallId = InstallEventReceiver
.addObserver(this, EventResultPersister.GENERATE_NEW_ID,
@@ -166,9 +130,14 @@ public class InstallInstalling extends AlertActivity {
PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
- try {
- mSessionId = getPackageManager().getPackageInstaller().createSession(params);
- } catch (IOException e) {
+ mSessionId = getIntent().getIntExtra(EXTRA_STAGED_SESSION_ID, 0);
+ // Try to open session previously staged in InstallStaging.
+ try (PackageInstaller.Session ignored =
+ getPackageManager().getPackageInstaller().openSession(
+ mSessionId)) {
+ Log.d(LOG_TAG, "Staged session is valid, proceeding with the install");
+ } catch (IOException | SecurityException e) {
+ Log.e(LOG_TAG, "Invalid session id passed", e);
launchFailure(PackageInstaller.STATUS_FAILURE,
PackageManager.INSTALL_FAILED_INTERNAL_ERROR, null);
}
@@ -293,57 +262,9 @@ public class InstallInstalling extends AlertActivity {
@Override
protected PackageInstaller.Session doInBackground(Void... params) {
- PackageInstaller.Session session;
try {
- session = getPackageManager().getPackageInstaller().openSession(mSessionId);
+ return getPackageManager().getPackageInstaller().openSession(mSessionId);
} catch (IOException e) {
- synchronized (this) {
- isDone = true;
- notifyAll();
- }
- return null;
- }
-
- session.setStagingProgress(0);
-
- try {
- File file = new File(mPackageURI.getPath());
-
- try (InputStream in = new FileInputStream(file)) {
- long sizeBytes = file.length();
- long totalRead = 0;
- try (OutputStream out = session
- .openWrite("PackageInstaller", 0, sizeBytes)) {
- byte[] buffer = new byte[1024 * 1024];
- while (true) {
- int numRead = in.read(buffer);
-
- if (numRead == -1) {
- session.fsync(out);
- break;
- }
-
- if (isCancelled()) {
- session.close();
- break;
- }
-
- out.write(buffer, 0, numRead);
- if (sizeBytes > 0) {
- totalRead += numRead;
- float fraction = ((float) totalRead / (float) sizeBytes);
- session.setStagingProgress(fraction);
- }
- }
- }
- }
-
- return session;
- } catch (IOException | SecurityException e) {
- Log.e(LOG_TAG, "Could not write package", e);
-
- session.close();
-
return null;
} finally {
synchronized (this) {
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java
index 68de2f67bd94..097e47f58db1 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStaging.java
@@ -16,6 +16,10 @@
package com.android.packageinstaller;
+import static android.content.res.AssetFileDescriptor.UNKNOWN_LENGTH;
+
+import static com.android.packageinstaller.PackageInstallerActivity.EXTRA_STAGED_SESSION_ID;
+
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -23,40 +27,49 @@ import android.app.DialogFragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
+import android.content.res.AssetFileDescriptor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.ParcelFileDescriptor;
+import android.os.Process;
import android.util.Log;
import android.view.View;
+import android.widget.ProgressBar;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
- * If a package gets installed from an content URI this step loads the package and turns it into
- * and installation from a file. Then it re-starts the installation as usual.
+ * If a package gets installed from a content URI this step stages the installation session
+ * reading bytes from the URI.
*/
public class InstallStaging extends AlertActivity {
private static final String LOG_TAG = InstallStaging.class.getSimpleName();
- private static final String STAGED_FILE = "STAGED_FILE";
+ private static final String STAGED_SESSION_ID = "STAGED_SESSION_ID";
+
+ private @Nullable PackageInstaller mInstaller;
/** Currently running task that loads the file from the content URI into a file */
private @Nullable StagingAsyncTask mStagingTask;
- /** The file the package is in */
- private @Nullable File mStagedFile;
+ /** The session the package is in */
+ private int mStagedSessionId;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mInstaller = getPackageManager().getPackageInstaller();
+
setFinishOnTouchOutside(true);
mAlert.setIcon(R.drawable.ic_file_download);
mAlert.setTitle(getString(R.string.app_name_unknown));
@@ -66,6 +79,9 @@ public class InstallStaging extends AlertActivity {
if (mStagingTask != null) {
mStagingTask.cancel(true);
}
+
+ cleanupStagingSession();
+
setResult(RESULT_CANCELED);
finish();
}, null);
@@ -73,11 +89,7 @@ public class InstallStaging extends AlertActivity {
requireViewById(R.id.staging).setVisibility(View.VISIBLE);
if (savedInstanceState != null) {
- mStagedFile = new File(savedInstanceState.getString(STAGED_FILE));
-
- if (!mStagedFile.exists()) {
- mStagedFile = null;
- }
+ mStagedSessionId = savedInstanceState.getInt(STAGED_SESSION_ID, 0);
}
}
@@ -85,21 +97,41 @@ public class InstallStaging extends AlertActivity {
protected void onResume() {
super.onResume();
- // This is the first onResume in a single life of the activity
+ // This is the first onResume in a single life of the activity.
if (mStagingTask == null) {
- // File does not exist, or became invalid
- if (mStagedFile == null) {
- // Create file delayed to be able to show error
+ if (mStagedSessionId > 0) {
+ final PackageInstaller.SessionInfo info = mInstaller.getSessionInfo(
+ mStagedSessionId);
+ if (info == null || !info.isActive() || info.getResolvedBaseApkPath() == null) {
+ Log.w(LOG_TAG, "Session " + mStagedSessionId + " in funky state; ignoring");
+ if (info != null) {
+ cleanupStagingSession();
+ }
+ mStagedSessionId = 0;
+ }
+ }
+
+ // Session does not exist, or became invalid.
+ if (mStagedSessionId <= 0) {
+ // Create session here to be able to show error.
+ final Uri packageUri = getIntent().getData();
+ final AssetFileDescriptor afd = openAssetFileDescriptor(packageUri);
try {
- mStagedFile = TemporaryFileManager.getStagedFile(this);
+ ParcelFileDescriptor pfd = afd != null ? afd.getParcelFileDescriptor() : null;
+ PackageInstaller.SessionParams params = createSessionParams(
+ mInstaller, getIntent(), pfd, packageUri.toString());
+ mStagedSessionId = mInstaller.createSession(params);
} catch (IOException e) {
+ Log.w(LOG_TAG, "Failed to create a staging session", e);
showError();
return;
+ } finally {
+ PackageUtil.safeClose(afd);
}
}
mStagingTask = new StagingAsyncTask();
- mStagingTask.execute(getIntent().getData());
+ mStagingTask.execute();
}
}
@@ -107,7 +139,7 @@ public class InstallStaging extends AlertActivity {
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
- outState.putString(STAGED_FILE, mStagedFile.getPath());
+ outState.putInt(STAGED_SESSION_ID, mStagedSessionId);
}
@Override
@@ -119,6 +151,65 @@ public class InstallStaging extends AlertActivity {
super.onDestroy();
}
+ private AssetFileDescriptor openAssetFileDescriptor(Uri uri) {
+ try {
+ return getContentResolver().openAssetFileDescriptor(uri, "r");
+ } catch (Exception e) {
+ Log.w(LOG_TAG, "Failed to open asset file descriptor", e);
+ return null;
+ }
+ }
+
+ private static PackageInstaller.SessionParams createSessionParams(
+ @NonNull PackageInstaller installer, @NonNull Intent intent,
+ @Nullable ParcelFileDescriptor pfd, @NonNull String debugPathName) {
+ PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
+ PackageInstaller.SessionParams.MODE_FULL_INSTALL);
+ final Uri referrerUri = intent.getParcelableExtra(Intent.EXTRA_REFERRER);
+ params.setPackageSource(
+ referrerUri != null ? PackageInstaller.PACKAGE_SOURCE_DOWNLOADED_FILE
+ : PackageInstaller.PACKAGE_SOURCE_LOCAL_FILE);
+ params.setInstallAsInstantApp(false);
+ params.setReferrerUri(referrerUri);
+ params.setOriginatingUri(intent
+ .getParcelableExtra(Intent.EXTRA_ORIGINATING_URI));
+ params.setOriginatingUid(intent.getIntExtra(Intent.EXTRA_ORIGINATING_UID,
+ Process.INVALID_UID));
+ params.setInstallerPackageName(intent.getStringExtra(
+ Intent.EXTRA_INSTALLER_PACKAGE_NAME));
+ params.setInstallReason(PackageManager.INSTALL_REASON_USER);
+
+ if (pfd != null) {
+ try {
+ final PackageInstaller.InstallInfo result = installer.readInstallInfo(pfd,
+ debugPathName, 0);
+ params.setAppPackageName(result.getPackageName());
+ params.setInstallLocation(result.getInstallLocation());
+ params.setSize(result.calculateInstalledSize(params, pfd));
+ } catch (PackageInstaller.PackageParsingException | IOException e) {
+ Log.e(LOG_TAG, "Cannot parse package " + debugPathName + ". Assuming defaults.", e);
+ Log.e(LOG_TAG,
+ "Cannot calculate installed size " + debugPathName
+ + ". Try only apk size.");
+ params.setSize(pfd.getStatSize());
+ }
+ } else {
+ Log.e(LOG_TAG, "Cannot parse package " + debugPathName + ". Assuming defaults.");
+ }
+ return params;
+ }
+
+ private void cleanupStagingSession() {
+ if (mStagedSessionId > 0) {
+ try {
+ mInstaller.abandonSession(mStagedSessionId);
+ } catch (SecurityException ignored) {
+
+ }
+ mStagedSessionId = 0;
+ }
+ }
+
/**
* Show an error message and set result as error.
*/
@@ -165,58 +256,109 @@ public class InstallStaging extends AlertActivity {
}
}
- private final class StagingAsyncTask extends AsyncTask<Uri, Void, Boolean> {
+ private final class StagingAsyncTask extends
+ AsyncTask<Void, Integer, PackageInstaller.SessionInfo> {
+ private ProgressBar mProgressBar = null;
+
+ private long getContentSizeBytes() {
+ try (AssetFileDescriptor afd = openAssetFileDescriptor(getIntent().getData())) {
+ return afd != null ? afd.getLength() : UNKNOWN_LENGTH;
+ } catch (IOException ignored) {
+ return UNKNOWN_LENGTH;
+ }
+ }
+
@Override
- protected Boolean doInBackground(Uri... params) {
- if (params == null || params.length <= 0) {
- return false;
+ protected void onPreExecute() {
+ final long sizeBytes = getContentSizeBytes();
+
+ mProgressBar = sizeBytes > 0 ? requireViewById(R.id.progress_indeterminate) : null;
+ if (mProgressBar != null) {
+ mProgressBar.setProgress(0);
+ mProgressBar.setMax(100);
+ mProgressBar.setIndeterminate(false);
}
- Uri packageUri = params[0];
- try (InputStream in = getContentResolver().openInputStream(packageUri)) {
- // Despite the comments in ContentResolver#openInputStream the returned stream can
- // be null.
+ }
+
+ @Override
+ protected PackageInstaller.SessionInfo doInBackground(Void... params) {
+ Uri packageUri = getIntent().getData();
+ try (PackageInstaller.Session session = mInstaller.openSession(mStagedSessionId);
+ InputStream in = getContentResolver().openInputStream(packageUri)) {
+ session.setStagingProgress(0);
+
if (in == null) {
- return false;
+ return null;
}
- try (OutputStream out = new FileOutputStream(mStagedFile)) {
+ long sizeBytes = getContentSizeBytes();
+
+ long totalRead = 0;
+ try (OutputStream out = session.openWrite("PackageInstaller", 0, sizeBytes)) {
byte[] buffer = new byte[1024 * 1024];
- int bytesRead;
- while ((bytesRead = in.read(buffer)) >= 0) {
- // Be nice and respond to a cancellation
+ while (true) {
+ int numRead = in.read(buffer);
+
+ if (numRead == -1) {
+ session.fsync(out);
+ break;
+ }
+
if (isCancelled()) {
- return false;
+ break;
+ }
+
+ out.write(buffer, 0, numRead);
+ if (sizeBytes > 0) {
+ totalRead += numRead;
+ float fraction = ((float) totalRead / (float) sizeBytes);
+ session.setStagingProgress(fraction);
+ publishProgress((int) (fraction * 100.0));
}
- out.write(buffer, 0, bytesRead);
}
}
+
+ return mInstaller.getSessionInfo(mStagedSessionId);
} catch (IOException | SecurityException | IllegalStateException
- | IllegalArgumentException e) {
+ | IllegalArgumentException e) {
Log.w(LOG_TAG, "Error staging apk from content URI", e);
- return false;
+ return null;
}
- return true;
}
@Override
- protected void onPostExecute(Boolean success) {
- if (success) {
- // Now start the installation again from a file
- Intent installIntent = new Intent(getIntent());
- installIntent.setClass(InstallStaging.this, DeleteStagedFileOnResult.class);
- installIntent.setData(Uri.fromFile(mStagedFile));
-
- if (installIntent.getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
- installIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
- }
-
- installIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
- startActivity(installIntent);
+ protected void onProgressUpdate(Integer... progress) {
+ if (mProgressBar != null && progress != null && progress.length > 0) {
+ mProgressBar.setProgress(progress[0], true);
+ }
+ }
- InstallStaging.this.finish();
- } else {
+ @Override
+ protected void onPostExecute(PackageInstaller.SessionInfo sessionInfo) {
+ if (sessionInfo == null || !sessionInfo.isActive()
+ || sessionInfo.getResolvedBaseApkPath() == null) {
+ Log.w(LOG_TAG, "Session info is invalid: " + sessionInfo);
+ cleanupStagingSession();
showError();
+ return;
+ }
+
+ // Pass the staged session to the installer.
+ Intent installIntent = new Intent(getIntent());
+ installIntent.setClass(InstallStaging.this, DeleteStagedFileOnResult.class);
+ installIntent.setData(Uri.fromFile(new File(sessionInfo.getResolvedBaseApkPath())));
+
+ installIntent.putExtra(EXTRA_STAGED_SESSION_ID, mStagedSessionId);
+
+ if (installIntent.getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
+ installIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
}
+
+ installIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
+
+ startActivity(installIntent);
+
+ InstallStaging.this.finish();
}
}
}
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
index ac32020e842a..3f98867cb267 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
@@ -77,7 +77,21 @@ public class InstallStart extends Activity {
}
final ApplicationInfo sourceInfo = getSourceInfo(callingPackage);
- final int originatingUid = getOriginatingUid(sourceInfo);
+ // Uid of the source package, coming from ActivityManager
+ int callingUid = getLaunchedFromUid();
+ if (callingUid == Process.INVALID_UID) {
+ // Cannot reach ActivityManager. Aborting install.
+ Log.e(LOG_TAG, "Could not determine the launching uid.");
+ }
+ // Uid of the source package, with a preference to uid from ApplicationInfo
+ final int originatingUid = sourceInfo != null ? sourceInfo.uid : callingUid;
+
+ if (callingUid == Process.INVALID_UID && sourceInfo == null) {
+ mAbortInstall = true;
+ }
+
+ boolean isDocumentsManager = checkPermission(Manifest.permission.MANAGE_DOCUMENTS,
+ -1, callingUid) == PackageManager.PERMISSION_GRANTED;
boolean isTrustedSource = false;
if (sourceInfo != null && sourceInfo.isPrivilegedApp()) {
isTrustedSource = intent.getBooleanExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, false) || (
@@ -86,7 +100,8 @@ public class InstallStart extends Activity {
== PackageManager.PERMISSION_GRANTED);
}
- if (!isTrustedSource && originatingUid != Process.INVALID_UID) {
+ if (!isTrustedSource && !isSystemDownloadsProvider(callingUid) && !isDocumentsManager
+ && originatingUid != Process.INVALID_UID) {
final int targetSdkVersion = getMaxTargetSdkVersionForUid(this, originatingUid);
if (targetSdkVersion < 0) {
Log.w(LOG_TAG, "Cannot get target sdk version for uid " + originatingUid);
@@ -144,14 +159,15 @@ public class InstallStart extends Activity {
if (packageUri != null
&& packageUri.getScheme().equals(ContentResolver.SCHEME_CONTENT)
- && canPackageQuery(originatingUid, packageUri)) {
+ && canPackageQuery(callingUid, packageUri)) {
// [IMPORTANT] This path is deprecated, but should still work. Only necessary
// features should be added.
- // Copy file to prevent it from being changed underneath this process
+ // Stage a session with this file to prevent it from being changed underneath
+ // this process.
nextActivity.setClass(this, InstallStaging.class);
- } else if (packageUri != null && packageUri.getScheme().equals(
- PackageInstallerActivity.SCHEME_PACKAGE)) {
+ } else if (packageUri != null && PackageInstallerActivity.SCHEME_PACKAGE.equals(
+ packageUri.getScheme())) {
nextActivity.setClass(this, PackageInstallerActivity.class);
} else {
Intent result = new Intent();
@@ -212,41 +228,6 @@ public class InstallStart extends Activity {
return null;
}
- /**
- * Get the originating uid if possible, or {@link Process#INVALID_UID} if not available
- *
- * @param sourceInfo The source of this installation
- * @return The UID of the installation source or INVALID_UID
- */
- private int getOriginatingUid(@Nullable ApplicationInfo sourceInfo) {
- // The originating uid from the intent. We only trust/use this if it comes from either
- // the document manager app or the downloads provider
- final int uidFromIntent = getIntent().getIntExtra(Intent.EXTRA_ORIGINATING_UID,
- Process.INVALID_UID);
-
- final int callingUid;
- if (sourceInfo != null) {
- callingUid = sourceInfo.uid;
- } else {
- callingUid = getLaunchedFromUid();
- if (callingUid == Process.INVALID_UID) {
- // Cannot reach ActivityManager. Aborting install.
- Log.e(LOG_TAG, "Could not determine the launching uid.");
- mAbortInstall = true;
- return Process.INVALID_UID;
- }
- }
- if (checkPermission(Manifest.permission.MANAGE_DOCUMENTS, -1, callingUid)
- == PackageManager.PERMISSION_GRANTED) {
- return uidFromIntent;
- }
- if (isSystemDownloadsProvider(callingUid)) {
- return uidFromIntent;
- }
- // We don't trust uid from the intent. Use the calling uid instead.
- return callingUid;
- }
-
private boolean isSystemDownloadsProvider(int uid) {
final ProviderInfo downloadProviderPackage = getPackageManager().resolveContentProvider(
DOWNLOADS_AUTHORITY, 0);
@@ -260,8 +241,7 @@ public class InstallStart extends Activity {
}
@NonNull
- private boolean canPackageQuery(int originatingUid, Uri packageUri) {
- String callingPackage = mPackageManager.getPackagesForUid(originatingUid)[0];
+ private boolean canPackageQuery(int callingUid, Uri packageUri) {
ProviderInfo info = mPackageManager.resolveContentProvider(packageUri.getAuthority(),
PackageManager.ComponentInfoFlags.of(0));
if (info == null) {
@@ -269,11 +249,20 @@ public class InstallStart extends Activity {
}
String targetPackage = info.packageName;
- try {
- return mPackageManager.canPackageQuery(callingPackage, targetPackage);
- } catch (PackageManager.NameNotFoundException e) {
+ String[] callingPackages = mPackageManager.getPackagesForUid(callingUid);
+ if (callingPackages == null) {
return false;
}
+ for (String callingPackage: callingPackages) {
+ try {
+ if (mPackageManager.canPackageQuery(callingPackage, targetPackage)) {
+ return true;
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ // no-op
+ }
+ }
+ return false;
}
private boolean isCallerSessionOwner(int originatingUid, int sessionId) {
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index 3ba2acb113d3..7e294eee024f 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -82,6 +82,7 @@ public class PackageInstallerActivity extends AlertActivity {
static final String EXTRA_CALLING_PACKAGE = "EXTRA_CALLING_PACKAGE";
static final String EXTRA_CALLING_ATTRIBUTION_TAG = "EXTRA_CALLING_ATTRIBUTION_TAG";
static final String EXTRA_ORIGINAL_SOURCE_INFO = "EXTRA_ORIGINAL_SOURCE_INFO";
+ static final String EXTRA_STAGED_SESSION_ID = "EXTRA_STAGED_SESSION_ID";
private static final String ALLOW_UNKNOWN_SOURCES_KEY =
PackageInstallerActivity.class.getName() + "ALLOW_UNKNOWN_SOURCES_KEY";
@@ -403,6 +404,10 @@ public class PackageInstallerActivity extends AlertActivity {
mReferrerURI = null;
mPendingUserActionReason = info.getPendingUserActionReason();
} else {
+ // Two possible callers:
+ // 1. InstallStart with "SCHEME_PACKAGE".
+ // 2. InstallStaging with "SCHEME_FILE" and EXTRA_STAGED_SESSION_ID with staged
+ // session id.
mSessionId = -1;
packageSource = intent.getData();
mOriginatingURI = intent.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
@@ -721,14 +726,16 @@ public class PackageInstallerActivity extends AlertActivity {
}
private void startInstall() {
+ String installerPackageName = getIntent().getStringExtra(
+ Intent.EXTRA_INSTALLER_PACKAGE_NAME);
+ int stagedSessionId = getIntent().getIntExtra(EXTRA_STAGED_SESSION_ID, 0);
+
// Start subactivity to actually install the application
Intent newIntent = new Intent();
newIntent.putExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO,
mPkgInfo.applicationInfo);
newIntent.setData(mPackageURI);
newIntent.setClass(this, InstallInstalling.class);
- String installerPackageName = getIntent().getStringExtra(
- Intent.EXTRA_INSTALLER_PACKAGE_NAME);
if (mOriginatingURI != null) {
newIntent.putExtra(Intent.EXTRA_ORIGINATING_URI, mOriginatingURI);
}
@@ -745,6 +752,9 @@ public class PackageInstallerActivity extends AlertActivity {
if (getIntent().getBooleanExtra(Intent.EXTRA_RETURN_RESULT, false)) {
newIntent.putExtra(Intent.EXTRA_RETURN_RESULT, true);
}
+ if (stagedSessionId > 0) {
+ newIntent.putExtra(EXTRA_STAGED_SESSION_ID, stagedSessionId);
+ }
newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
if (mLocalLOGV) Log.i(TAG, "downloaded app uri=" + mPackageURI);
startActivity(newIntent);
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java
index 698159f24bb7..0270591acceb 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageUtil.java
@@ -33,7 +33,9 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import java.io.Closeable;
import java.io.File;
+import java.io.IOException;
/**
* This is a utility class for defining some utility methods and constants
@@ -190,4 +192,19 @@ public class PackageUtil {
}
return targetSdkVersion;
}
+
+
+ /**
+ * Quietly close a closeable resource (e.g. a stream or file). The input may already
+ * be closed and it may even be null.
+ */
+ static void safeClose(Closeable resource) {
+ if (resource != null) {
+ try {
+ resource.close();
+ } catch (IOException ioe) {
+ // Catch and discard the error
+ }
+ }
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
index c9e831256cf4..6cf6825e61e0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java
@@ -50,6 +50,7 @@ import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.DoNotInline;
+import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import com.android.internal.annotations.VisibleForTesting;
@@ -638,6 +639,11 @@ public class InfoMediaManager extends MediaManager {
}
@Override
+ public void onSessionReleased(@NonNull RoutingSessionInfo session) {
+ refreshDevices();
+ }
+
+ @Override
public void onRouteListingPreferenceUpdated(
String packageName,
RouteListingPreference routeListingPreference) {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
index 270fda89c212..096932706c88 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java
@@ -141,6 +141,56 @@ public class InfoMediaManagerTest {
}
@Test
+ public void onSessionReleased_shouldUpdateConnectedDevice() {
+ final List<RoutingSessionInfo> routingSessionInfos = new ArrayList<>();
+ final RoutingSessionInfo sessionInfo1 = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(sessionInfo1);
+ final RoutingSessionInfo sessionInfo2 = mock(RoutingSessionInfo.class);
+ routingSessionInfos.add(sessionInfo2);
+
+ final List<String> selectedRoutesSession1 = new ArrayList<>();
+ selectedRoutesSession1.add(TEST_ID_1);
+ when(sessionInfo1.getSelectedRoutes()).thenReturn(selectedRoutesSession1);
+
+ final List<String> selectedRoutesSession2 = new ArrayList<>();
+ selectedRoutesSession2.add(TEST_ID_2);
+ when(sessionInfo2.getSelectedRoutes()).thenReturn(selectedRoutesSession2);
+
+ mShadowRouter2Manager.setRoutingSessions(routingSessionInfos);
+
+ final MediaRoute2Info info1 = mock(MediaRoute2Info.class);
+ when(info1.getId()).thenReturn(TEST_ID_1);
+ when(info1.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+
+ final MediaRoute2Info info2 = mock(MediaRoute2Info.class);
+ when(info2.getId()).thenReturn(TEST_ID_2);
+ when(info2.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME);
+
+ final List<MediaRoute2Info> routes = new ArrayList<>();
+ routes.add(info1);
+ routes.add(info2);
+ mShadowRouter2Manager.setAllRoutes(routes);
+ mShadowRouter2Manager.setTransferableRoutes(routes);
+
+ final MediaDevice mediaDevice1 = mInfoMediaManager.findMediaDevice(TEST_ID_1);
+ assertThat(mediaDevice1).isNull();
+ final MediaDevice mediaDevice2 = mInfoMediaManager.findMediaDevice(TEST_ID_2);
+ assertThat(mediaDevice2).isNull();
+
+ mInfoMediaManager.mMediaRouterCallback.onRoutesUpdated();
+ final MediaDevice infoDevice1 = mInfoMediaManager.mMediaDevices.get(0);
+ assertThat(infoDevice1.getId()).isEqualTo(TEST_ID_1);
+ final MediaDevice infoDevice2 = mInfoMediaManager.mMediaDevices.get(1);
+ assertThat(infoDevice2.getId()).isEqualTo(TEST_ID_2);
+ // The active routing session is the last one in the list, which maps to infoDevice2.
+ assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(infoDevice2);
+
+ routingSessionInfos.remove(sessionInfo2);
+ mInfoMediaManager.mMediaRouterCallback.onSessionReleased(sessionInfo2);
+ assertThat(mInfoMediaManager.getCurrentConnectedDevice()).isEqualTo(infoDevice1);
+ }
+
+ @Test
public void onRouteAdded_buildAllRoutes_shouldAddMediaDevice() {
final MediaRoute2Info info = mock(MediaRoute2Info.class);
when(info.getId()).thenReturn(TEST_ID);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index a110f56d09bd..34a2ce34738d 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -834,6 +834,9 @@
<uses-permission android:name="android.permission.LOG_FOREGROUND_RESOURCE_USE"/>
+ <!-- Permission required for GTS test - GtsAttestationVerificationDeviceSideTestCases -->
+ <uses-permission android:name="android.permission.USE_ATTESTATION_VERIFICATION_SERVICE" />
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index e6bbf9759651..6a7b8cdfceec 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -158,6 +158,7 @@ android_library {
"SystemUIAnimationLib",
"SystemUICommon",
"SystemUICustomizationLib",
+ "SystemUILogLib",
"SystemUIPluginLib",
"SystemUISharedLib",
"SystemUI-statsd",
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
index 9346a2f7ebb7..00108940e6ec 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextAnimator.kt
@@ -23,8 +23,8 @@ import android.animation.ValueAnimator
import android.graphics.Canvas
import android.graphics.Typeface
import android.graphics.fonts.Font
+import android.graphics.fonts.FontVariationAxis
import android.text.Layout
-import android.text.TextPaint
import android.util.LruCache
private const val DEFAULT_ANIMATION_DURATION: Long = 300
@@ -33,18 +33,39 @@ private const val TYPEFACE_CACHE_MAX_ENTRIES = 5
typealias GlyphCallback = (TextAnimator.PositionedGlyph, Float) -> Unit
interface TypefaceVariantCache {
- fun getTypefaceForVariant(fvar: String, targetPaint: TextPaint): Typeface?
+ fun getTypefaceForVariant(fvar: String?): Typeface?
+
+ companion object {
+ fun createVariantTypeface(baseTypeface: Typeface, fVar: String?): Typeface {
+ if (fVar.isNullOrEmpty()) {
+ return baseTypeface
+ }
+
+ val axes = FontVariationAxis.fromFontVariationSettings(fVar).toMutableList()
+ axes.removeIf { !baseTypeface.isSupportedAxes(it.getOpenTypeTagValue()) }
+ if (axes.isEmpty()) {
+ return baseTypeface
+ }
+ return Typeface.createFromTypefaceWithVariation(baseTypeface, axes)
+ }
+ }
}
-class TypefaceVariantCacheImpl() : TypefaceVariantCache {
+class TypefaceVariantCacheImpl(
+ var baseTypeface: Typeface,
+) : TypefaceVariantCache {
private val cache = LruCache<String, Typeface>(TYPEFACE_CACHE_MAX_ENTRIES)
- override fun getTypefaceForVariant(fvar: String, targetPaint: TextPaint): Typeface? {
+ override fun getTypefaceForVariant(fvar: String?): Typeface? {
+ if (fvar == null) {
+ return baseTypeface
+ }
cache.get(fvar)?.let {
return it
}
- targetPaint.fontVariationSettings = fvar
- return targetPaint.typeface?.also { cache.put(fvar, it) }
+ return TypefaceVariantCache
+ .createVariantTypeface(baseTypeface, fvar)
+ .also { cache.put(fvar, it) }
}
}
@@ -78,7 +99,7 @@ class TextAnimator(
layout: Layout,
private val invalidateCallback: () -> Unit,
) {
- var typefaceCache: TypefaceVariantCache = TypefaceVariantCacheImpl()
+ var typefaceCache: TypefaceVariantCache = TypefaceVariantCacheImpl(layout.paint.typeface)
get() = field
set(value) {
field = value
@@ -244,8 +265,7 @@ class TextAnimator(
}
if (!fvar.isNullOrBlank()) {
- textInterpolator.targetPaint.typeface =
- typefaceCache.getTypefaceForVariant(fvar, textInterpolator.targetPaint)
+ textInterpolator.targetPaint.typeface = typefaceCache.getTypefaceForVariant(fvar)
}
if (color != null) {
@@ -339,4 +359,3 @@ class TextAnimator(
)
}
}
-
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
index 79189bc3e5c3..8ed8d8fb61fd 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/TextInterpolator.kt
@@ -38,6 +38,8 @@ class TextInterpolator(
* Once you modified the style parameters, you have to call reshapeText to recalculate base text
* layout.
*
+ * Do not bypass the cache and update the typeface or font variation directly.
+ *
* @return a paint object
*/
val basePaint = TextPaint(layout.paint)
@@ -48,6 +50,8 @@ class TextInterpolator(
* Once you modified the style parameters, you have to call reshapeText to recalculate target
* text layout.
*
+ * Do not bypass the cache and update the typeface or font variation directly.
+ *
* @return a paint object
*/
val targetPaint = TextPaint(layout.paint)
@@ -217,14 +221,8 @@ class TextInterpolator(
run.fontRuns.forEach { fontRun ->
fontRun.baseFont =
fontInterpolator.lerp(fontRun.baseFont, fontRun.targetFont, progress)
- val fvar = run {
- val tmpFontVariationsArray = mutableListOf<FontVariationAxis>()
- fontRun.baseFont.axes.forEach {
- tmpFontVariationsArray.add(FontVariationAxis(it.tag, it.styleValue))
- }
- FontVariationAxis.toFontVariationSettings(tmpFontVariationsArray)
- }
- basePaint.typeface = typefaceCache.getTypefaceForVariant(fvar, basePaint)
+ val fvar = FontVariationAxis.toFontVariationSettings(fontRun.baseFont.axes)
+ basePaint.typeface = typefaceCache.getTypefaceForVariant(fvar)
}
}
}
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 3a19990f0627..941a925c9d10 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
@@ -33,8 +33,8 @@ import com.android.systemui.animation.GlyphCallback
import com.android.systemui.animation.Interpolators
import com.android.systemui.animation.TextAnimator
import com.android.systemui.customization.R
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.DEBUG
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
import java.io.PrintWriter
import java.util.Calendar
import java.util.Locale
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 b0c02407873c..aa1bb3f640ee 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
@@ -23,6 +23,12 @@ import android.os.UserHandle
import android.provider.Settings
import android.util.Log
import androidx.annotation.OpenForTesting
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.LogMessage
+import com.android.systemui.log.LogMessageImpl
+import com.android.systemui.log.MessageInitializer
+import com.android.systemui.log.MessagePrinter
import com.android.systemui.plugins.ClockController
import com.android.systemui.plugins.ClockId
import com.android.systemui.plugins.ClockMetadata
@@ -32,12 +38,6 @@ import com.android.systemui.plugins.ClockSettings
import com.android.systemui.plugins.PluginLifecycleManager
import com.android.systemui.plugins.PluginListener
import com.android.systemui.plugins.PluginManager
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
-import com.android.systemui.plugins.log.LogMessage
-import com.android.systemui.plugins.log.LogMessageImpl
-import com.android.systemui.plugins.log.MessageInitializer
-import com.android.systemui.plugins.log.MessagePrinter
import com.android.systemui.util.Assert
import java.io.PrintWriter
import java.util.concurrent.ConcurrentHashMap
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 2cc36008e4f8..6aa74fbf24e7 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
@@ -24,6 +24,7 @@ import android.view.View
import android.widget.FrameLayout
import androidx.annotation.VisibleForTesting
import com.android.systemui.customization.R
+import com.android.systemui.log.LogBuffer
import com.android.systemui.plugins.ClockAnimations
import com.android.systemui.plugins.ClockConfig
import com.android.systemui.plugins.ClockController
@@ -32,7 +33,6 @@ import com.android.systemui.plugins.ClockFaceConfig
import com.android.systemui.plugins.ClockFaceController
import com.android.systemui.plugins.ClockFaceEvents
import com.android.systemui.plugins.ClockSettings
-import com.android.systemui.plugins.log.LogBuffer
import java.io.PrintWriter
import java.util.Locale
import java.util.TimeZone
diff --git a/packages/SystemUI/log/.gitignore b/packages/SystemUI/log/.gitignore
new file mode 100644
index 000000000000..f9a33dbbcc7e
--- /dev/null
+++ b/packages/SystemUI/log/.gitignore
@@ -0,0 +1,9 @@
+.idea/
+.gradle/
+gradle/
+build/
+gradlew*
+local.properties
+*.iml
+android.properties
+buildSrc \ No newline at end of file
diff --git a/packages/SystemUI/log/Android.bp b/packages/SystemUI/log/Android.bp
new file mode 100644
index 000000000000..627ac4b7c381
--- /dev/null
+++ b/packages/SystemUI/log/Android.bp
@@ -0,0 +1,38 @@
+// 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_packages_SystemUI_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_packages_SystemUI_license"],
+}
+
+android_library {
+ name: "SystemUILogLib",
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
+ static_libs: [
+ "androidx.core_core-ktx",
+ "androidx.annotation_annotation",
+ "error_prone_annotations",
+ "SystemUICommon",
+ ],
+ manifest: "AndroidManifest.xml",
+ kotlincflags: ["-Xjvm-default=all"],
+}
diff --git a/packages/SystemUI/log/AndroidManifest.xml b/packages/SystemUI/log/AndroidManifest.xml
new file mode 100644
index 000000000000..4021e1a5f751
--- /dev/null
+++ b/packages/SystemUI/log/AndroidManifest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.systemui.log">
+
+
+</manifest>
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/ConstantStringsLogger.kt b/packages/SystemUI/log/src/com/android/systemui/log/ConstantStringsLogger.kt
index f95b1874da36..bc35095a3436 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/ConstantStringsLogger.kt
+++ b/packages/SystemUI/log/src/com/android/systemui/log/ConstantStringsLogger.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.plugins.log
+package com.android.systemui.log
import com.google.errorprone.annotations.CompileTimeConstant
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/ConstantStringsLoggerImpl.kt b/packages/SystemUI/log/src/com/android/systemui/log/ConstantStringsLoggerImpl.kt
index 91b39e6fcc13..6fc525369e8b 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/ConstantStringsLoggerImpl.kt
+++ b/packages/SystemUI/log/src/com/android/systemui/log/ConstantStringsLoggerImpl.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.plugins.log
+package com.android.systemui.log
import com.google.errorprone.annotations.CompileTimeConstant
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt b/packages/SystemUI/log/src/com/android/systemui/log/LogBuffer.kt
index 0a7ccc525a73..af1a11f6597a 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogBuffer.kt
+++ b/packages/SystemUI/log/src/com/android/systemui/log/LogBuffer.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.plugins.log
+package com.android.systemui.log
import android.os.Trace
import android.util.Log
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogLevel.kt b/packages/SystemUI/log/src/com/android/systemui/log/LogLevel.kt
index b036cf0be1d6..7d9647a13149 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogLevel.kt
+++ b/packages/SystemUI/log/src/com/android/systemui/log/LogLevel.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.plugins.log
+package com.android.systemui.log
import android.util.Log
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogMessage.kt b/packages/SystemUI/log/src/com/android/systemui/log/LogMessage.kt
index 9468681289bf..88c34f82a089 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogMessage.kt
+++ b/packages/SystemUI/log/src/com/android/systemui/log/LogMessage.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.plugins.log
+package com.android.systemui.log
import java.io.PrintWriter
import java.text.SimpleDateFormat
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogMessageImpl.kt b/packages/SystemUI/log/src/com/android/systemui/log/LogMessageImpl.kt
index f2a6a91adcdf..5e10f783850f 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogMessageImpl.kt
+++ b/packages/SystemUI/log/src/com/android/systemui/log/LogMessageImpl.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.plugins.log
+package com.android.systemui.log
/** Recyclable implementation of [LogMessage]. */
data class LogMessageImpl(
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTracker.kt b/packages/SystemUI/log/src/com/android/systemui/log/LogcatEchoTracker.kt
index cfe894f276a0..55f3a738e4f1 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTracker.kt
+++ b/packages/SystemUI/log/src/com/android/systemui/log/LogcatEchoTracker.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.plugins.log
+package com.android.systemui.log
/** Keeps track of which [LogBuffer] messages should also appear in logcat. */
interface LogcatEchoTracker {
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt b/packages/SystemUI/log/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt
index 7a125ac14ea1..d0ad28f04670 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerDebug.kt
+++ b/packages/SystemUI/log/src/com/android/systemui/log/LogcatEchoTrackerDebug.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.plugins.log
+package com.android.systemui.log
import android.content.ContentResolver
import android.database.ContentObserver
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerProd.kt b/packages/SystemUI/log/src/com/android/systemui/log/LogcatEchoTrackerProd.kt
index 3c8bda4a44e0..56966773d1b0 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/log/LogcatEchoTrackerProd.kt
+++ b/packages/SystemUI/log/src/com/android/systemui/log/LogcatEchoTrackerProd.kt
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.systemui.plugins.log
+package com.android.systemui.log
/** Production version of [LogcatEchoTracker] that isn't configurable. */
class LogcatEchoTrackerProd : LogcatEchoTracker {
diff --git a/packages/SystemUI/plugin/Android.bp b/packages/SystemUI/plugin/Android.bp
index 22bcba4a2b6c..fec093b26bcc 100644
--- a/packages/SystemUI/plugin/Android.bp
+++ b/packages/SystemUI/plugin/Android.bp
@@ -36,10 +36,10 @@ java_library {
// in PluginInstance. That will ensure that loaded plugins have access to the related classes.
static_libs: [
"androidx.annotation_annotation",
- "error_prone_annotations",
"PluginCoreLib",
"SystemUIAnimationLib",
"SystemUICommon",
+ "SystemUILogLib",
],
}
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 ca3e710a4acb..7bf139e69f2e 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -18,8 +18,8 @@ import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.view.View
import com.android.internal.annotations.Keep
+import com.android.systemui.log.LogBuffer
import com.android.systemui.plugins.annotations.ProvidesInterface
-import com.android.systemui.plugins.log.LogBuffer
import java.io.PrintWriter
import java.util.Locale
import java.util.TimeZone
diff --git a/packages/SystemUI/res-keyguard/layout/status_bar_mobile_signal_group_inner.xml b/packages/SystemUI/res-keyguard/layout/status_bar_mobile_signal_group_inner.xml
index 934fa6f54286..29832a081612 100644
--- a/packages/SystemUI/res-keyguard/layout/status_bar_mobile_signal_group_inner.xml
+++ b/packages/SystemUI/res-keyguard/layout/status_bar_mobile_signal_group_inner.xml
@@ -30,7 +30,7 @@
<FrameLayout
android:id="@+id/inout_container"
- android:layout_height="@*android:dimen/status_bar_system_icon_intrinsic_size"
+ android:layout_height="17dp"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical">
<ImageView
@@ -39,25 +39,24 @@
android:layout_width="wrap_content"
android:src="@drawable/ic_activity_down"
android:visibility="gone"
- android:paddingEnd="2sp"
+ android:paddingEnd="2dp"
/>
<ImageView
android:id="@+id/mobile_out"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/ic_activity_up"
- android:paddingEnd="2sp"
+ android:paddingEnd="2dp"
android:visibility="gone"
/>
</FrameLayout>
<ImageView
android:id="@+id/mobile_type"
- android:layout_height="@dimen/status_bar_mobile_signal_size"
+ android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="center_vertical"
- android:adjustViewBounds="true"
- android:paddingStart="2.5sp"
- android:paddingEnd="1sp"
+ android:paddingStart="2.5dp"
+ android:paddingEnd="1dp"
android:visibility="gone" />
<Space
android:id="@+id/mobile_roaming_space"
@@ -71,14 +70,14 @@
android:layout_gravity="center_vertical">
<com.android.systemui.statusbar.AnimatedImageView
android:id="@+id/mobile_signal"
- android:layout_height="@dimen/status_bar_mobile_signal_size"
- android:layout_width="@dimen/status_bar_mobile_signal_size"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
systemui:hasOverlappingRendering="false"
/>
<ImageView
android:id="@+id/mobile_roaming"
- android:layout_width="@dimen/status_bar_mobile_signal_size"
- android:layout_height="@dimen/status_bar_mobile_signal_size"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:src="@drawable/stat_sys_roaming"
android:contentDescription="@string/data_connection_roaming"
android:visibility="gone" />
diff --git a/packages/SystemUI/res/layout/combined_qs_header.xml b/packages/SystemUI/res/layout/combined_qs_header.xml
index e989372adde3..441f963a855a 100644
--- a/packages/SystemUI/res/layout/combined_qs_header.xml
+++ b/packages/SystemUI/res/layout/combined_qs_header.xml
@@ -126,7 +126,8 @@
<com.android.systemui.battery.BatteryMeterView
android:id="@+id/batteryRemainingIcon"
android:layout_width="wrap_content"
- android:layout_height="0dp"
+ android:layout_height="@dimen/large_screen_shade_header_min_height"
+ app:layout_constraintHeight_min="@dimen/large_screen_shade_header_min_height"
app:layout_constrainedWidth="true"
app:textAppearance="@style/TextAppearance.QS.Status"
app:layout_constraintStart_toEndOf="@id/statusIcons"
diff --git a/packages/SystemUI/res/layout/smart_action_button.xml b/packages/SystemUI/res/layout/smart_action_button.xml
index 488be3a4479e..4e5785d284ee 100644
--- a/packages/SystemUI/res/layout/smart_action_button.xml
+++ b/packages/SystemUI/res/layout/smart_action_button.xml
@@ -29,8 +29,8 @@
android:textSize="@dimen/smart_reply_button_font_size"
android:lineSpacingExtra="@dimen/smart_reply_button_line_spacing_extra"
android:textColor="@color/smart_reply_button_text"
- android:paddingLeft="@dimen/smart_reply_button_action_padding_left"
- android:paddingRight="@dimen/smart_reply_button_padding_horizontal"
+ android:paddingStart="@dimen/smart_reply_button_action_padding_left"
+ android:paddingEnd="@dimen/smart_reply_button_padding_horizontal"
android:drawablePadding="@dimen/smart_action_button_icon_padding"
android:textStyle="normal"
android:ellipsize="none"/>
diff --git a/packages/SystemUI/res/layout/smart_reply_button.xml b/packages/SystemUI/res/layout/smart_reply_button.xml
index ddf16e0afed7..b24362febbdd 100644
--- a/packages/SystemUI/res/layout/smart_reply_button.xml
+++ b/packages/SystemUI/res/layout/smart_reply_button.xml
@@ -31,7 +31,7 @@
android:textSize="@dimen/smart_reply_button_font_size"
android:lineSpacingExtra="@dimen/smart_reply_button_line_spacing_extra"
android:textColor="@color/smart_reply_button_text"
- android:paddingLeft="@dimen/smart_reply_button_padding_horizontal"
- android:paddingRight="@dimen/smart_reply_button_padding_horizontal"
+ android:paddingStart="@dimen/smart_reply_button_padding_horizontal"
+ android:paddingEnd="@dimen/smart_reply_button_padding_horizontal"
android:textStyle="normal"
android:ellipsize="none"/>
diff --git a/packages/SystemUI/res/layout/status_bar_wifi_group_inner.xml b/packages/SystemUI/res/layout/status_bar_wifi_group_inner.xml
index 473ab08a1935..0ea0653ab89f 100644
--- a/packages/SystemUI/res/layout/status_bar_wifi_group_inner.xml
+++ b/packages/SystemUI/res/layout/status_bar_wifi_group_inner.xml
@@ -24,11 +24,11 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
- android:layout_marginStart="2.5sp"
+ android:layout_marginStart="2.5dp"
>
<FrameLayout
android:id="@+id/inout_container"
- android:layout_height="@*android:dimen/status_bar_system_icon_intrinsic_size"
+ android:layout_height="17dp"
android:layout_width="wrap_content"
android:gravity="center_vertical" >
<ImageView
@@ -37,14 +37,14 @@
android:layout_width="wrap_content"
android:src="@drawable/ic_activity_down"
android:visibility="gone"
- android:paddingEnd="2sp"
+ android:paddingEnd="2dp"
/>
<ImageView
android:id="@+id/wifi_out"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/ic_activity_up"
- android:paddingEnd="2sp"
+ android:paddingEnd="2dp"
android:visibility="gone"
/>
</FrameLayout>
@@ -62,7 +62,7 @@
<View
android:id="@+id/wifi_signal_spacer"
android:layout_width="@dimen/status_bar_wifi_signal_spacer_width"
- android:layout_height="4sp"
+ android:layout_height="4dp"
android:visibility="gone" />
<!-- Looks like CarStatusBar uses this... -->
@@ -75,7 +75,7 @@
<View
android:id="@+id/wifi_airplane_spacer"
android:layout_width="@dimen/status_bar_airplane_spacer_width"
- android:layout_height="4sp"
+ android:layout_height="4dp"
android:visibility="gone"
/>
</com.android.keyguard.AlphaOptimizedLinearLayout>
diff --git a/packages/SystemUI/res/layout/udfps_keyguard_view_internal.xml b/packages/SystemUI/res/layout/udfps_keyguard_view_internal.xml
index 18386637e8f8..191158e4e8c2 100644
--- a/packages/SystemUI/res/layout/udfps_keyguard_view_internal.xml
+++ b/packages/SystemUI/res/layout/udfps_keyguard_view_internal.xml
@@ -20,7 +20,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/udfps_animation_view_internal"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:contentDescription="@string/accessibility_fingerprint_label">
<!-- Background protection -->
<ImageView
diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml
index f40615eb46d0..20864591ae5a 100644
--- a/packages/SystemUI/res/values-sw720dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp/dimens.xml
@@ -17,7 +17,7 @@
-->
<resources>
<!-- gap on either side of status bar notification icons -->
- <dimen name="status_bar_icon_padding">1sp</dimen>
+ <dimen name="status_bar_icon_padding">1dp</dimen>
<dimen name="controls_header_horizontal_padding">28dp</dimen>
<dimen name="controls_content_margin_horizontal">40dp</dimen>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index f5c4a4e4bb52..0aa880fe6d88 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -122,26 +122,26 @@
<dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
<!-- Default horizontal drawable padding for status bar icons. -->
- <dimen name="status_bar_horizontal_padding">2.5sp</dimen>
+ <dimen name="status_bar_horizontal_padding">2.5dp</dimen>
<!-- Height of the battery icon in the status bar. -->
- <dimen name="status_bar_battery_icon_height">13.0sp</dimen>
+ <dimen name="status_bar_battery_icon_height">13.0dp</dimen>
<!-- Width of the battery icon in the status bar. The battery drawable assumes a 12x20 canvas,
- so the width of the icon should be 13.0sp * (12.0 / 20.0) -->
- <dimen name="status_bar_battery_icon_width">7.8sp</dimen>
+ so the width of the icon should be 13.0dp * (12.0 / 20.0) -->
+ <dimen name="status_bar_battery_icon_width">7.8dp</dimen>
- <!-- The battery icon is 13sp tall, but the other system icons are 15sp tall (see
+ <!-- The battery icon is 13dp tall, but the other system icons are 15dp tall (see
@*android:dimen/status_bar_system_icon_size) with some top and bottom padding embedded in
- the drawables themselves. So, the battery icon may need an extra 1sp of spacing so that its
+ the drawables themselves. So, the battery icon may need an extra 1dp of spacing so that its
bottom still aligns with the bottom of all the other system icons. See b/258672854. -->
- <dimen name="status_bar_battery_extra_vertical_spacing">1sp</dimen>
+ <dimen name="status_bar_battery_extra_vertical_spacing">1dp</dimen>
<!-- The font size for the clock in the status bar. -->
<dimen name="status_bar_clock_size">14sp</dimen>
<!-- The starting padding for the clock in the status bar. -->
- <dimen name="status_bar_clock_starting_padding">7sp</dimen>
+ <dimen name="status_bar_clock_starting_padding">7dp</dimen>
<!-- The end padding for the clock in the status bar. -->
<dimen name="status_bar_clock_end_padding">0dp</dimen>
@@ -153,19 +153,16 @@
<dimen name="status_bar_left_clock_end_padding">2dp</dimen>
<!-- Spacing after the wifi signals that is present if there are any icons following it. -->
- <dimen name="status_bar_wifi_signal_spacer_width">2.5sp</dimen>
+ <dimen name="status_bar_wifi_signal_spacer_width">2.5dp</dimen>
<!-- Size of the view displaying the wifi signal icon in the status bar. -->
- <dimen name="status_bar_wifi_signal_size">13sp</dimen>
-
- <!-- Size of the view displaying the mobile signal icon in the status bar. -->
- <dimen name="status_bar_mobile_signal_size">13sp</dimen>
+ <dimen name="status_bar_wifi_signal_size">@*android:dimen/status_bar_system_icon_size</dimen>
<!-- Spacing before the airplane mode icon if there are any icons preceding it. -->
- <dimen name="status_bar_airplane_spacer_width">4sp</dimen>
+ <dimen name="status_bar_airplane_spacer_width">4dp</dimen>
<!-- Spacing between system icons. -->
- <dimen name="status_bar_system_icon_spacing">2sp</dimen>
+ <dimen name="status_bar_system_icon_spacing">0dp</dimen>
<!-- The amount to scale each of the status bar icons by. A value of 1 means no scaling. -->
<item name="status_bar_icon_scale_factor" format="float" type="dimen">1.0</item>
@@ -313,7 +310,7 @@
<dimen name="snooze_snackbar_min_height">56dp</dimen>
<!-- size at which Notification icons will be drawn in the status bar -->
- <dimen name="status_bar_icon_drawing_size">15sp</dimen>
+ <dimen name="status_bar_icon_drawing_size">15dp</dimen>
<!-- size at which Notification icons will be drawn on Ambient Display -->
<dimen name="status_bar_icon_drawing_size_dark">
@@ -324,22 +321,22 @@
<item type="dimen" name="status_bar_icon_drawing_alpha">90%</item>
<!-- gap on either side of status bar notification icons -->
- <dimen name="status_bar_icon_padding">0sp</dimen>
+ <dimen name="status_bar_icon_padding">0dp</dimen>
<!-- the padding on the start of the statusbar -->
- <dimen name="status_bar_padding_start">8sp</dimen>
+ <dimen name="status_bar_padding_start">8dp</dimen>
<!-- the padding on the end of the statusbar -->
- <dimen name="status_bar_padding_end">8sp</dimen>
+ <dimen name="status_bar_padding_end">8dp</dimen>
<!-- the padding on the top of the statusbar (usually 0) -->
- <dimen name="status_bar_padding_top">0sp</dimen>
+ <dimen name="status_bar_padding_top">0dp</dimen>
<!-- the radius of the overflow dot in the status bar -->
- <dimen name="overflow_dot_radius">2sp</dimen>
+ <dimen name="overflow_dot_radius">2dp</dimen>
<!-- the padding between dots in the icon overflow -->
- <dimen name="overflow_icon_dot_padding">3sp</dimen>
+ <dimen name="overflow_icon_dot_padding">3dp</dimen>
<!-- Dimensions related to screenshots -->
@@ -620,8 +617,8 @@
<dimen name="qs_footer_icon_size">20dp</dimen>
<dimen name="qs_header_row_min_height">48dp</dimen>
- <dimen name="qs_header_non_clickable_element_height">24sp</dimen>
- <dimen name="new_qs_header_non_clickable_element_height">24sp</dimen>
+ <dimen name="qs_header_non_clickable_element_height">24dp</dimen>
+ <dimen name="new_qs_header_non_clickable_element_height">24dp</dimen>
<dimen name="qs_footer_padding">20dp</dimen>
<dimen name="qs_security_footer_height">88dp</dimen>
@@ -825,7 +822,7 @@
<!-- Padding between the mobile signal indicator and the start icon when the roaming icon
is displayed in the upper left corner. -->
- <dimen name="roaming_icon_start_padding">2sp</dimen>
+ <dimen name="roaming_icon_start_padding">2dp</dimen>
<!-- Extra padding between the mobile data type icon and the strength indicator when the data
type icon is wide for the tile in quick settings. -->
@@ -1045,13 +1042,13 @@
<dimen name="display_cutout_margin_consumption">0px</dimen>
<!-- Height of the Ongoing App Ops chip -->
- <dimen name="ongoing_appops_chip_height">24sp</dimen>
+ <dimen name="ongoing_appops_chip_height">24dp</dimen>
<!-- Side padding between background of Ongoing App Ops chip and content -->
<dimen name="ongoing_appops_chip_side_padding">8dp</dimen>
<!-- Margin between icons of Ongoing App Ops chip -->
<dimen name="ongoing_appops_chip_icon_margin">4dp</dimen>
<!-- Icon size of Ongoing App Ops chip -->
- <dimen name="ongoing_appops_chip_icon_size">16sp</dimen>
+ <dimen name="ongoing_appops_chip_icon_size">16dp</dimen>
<!-- Radius of Ongoing App Ops chip corners -->
<dimen name="ongoing_appops_chip_bg_corner_radius">28dp</dimen>
<!-- One or two privacy items -->
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 499dfa4b3c9f..eaeaabe8779a 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -198,6 +198,9 @@
<item type="id" name="pm_lite"/>
<item type="id" name="settings_button_container"/>
+ <!--Keyboard Backlight Dialog -->
+ <item type="id" name="keyboard_backlight_dialog_container"/>
+
<item type="id" name="log_access_dialog_allow_button" />
<item type="id" name="log_access_dialog_deny_button" />
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/CombinedCondition.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/CombinedCondition.kt
index 2d83458ec2f7..a2b6e2cf9ae3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/CombinedCondition.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/CombinedCondition.kt
@@ -16,27 +16,179 @@
package com.android.systemui.shared.condition
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.launch
+
/**
* A higher order [Condition] which combines multiple conditions with a specified
- * [Evaluator.ConditionOperand].
+ * [Evaluator.ConditionOperand]. Conditions are executed lazily as-needed.
+ *
+ * @param scope The [CoroutineScope] to execute in.
+ * @param conditions The list of conditions to evaluate. Since conditions are executed lazily, the
+ * ordering is important here.
+ * @param operand The [Evaluator.ConditionOperand] to apply to the conditions.
*/
-internal class CombinedCondition
+@OptIn(ExperimentalCoroutinesApi::class)
+class CombinedCondition
constructor(
+ private val scope: CoroutineScope,
private val conditions: Collection<Condition>,
@Evaluator.ConditionOperand private val operand: Int
-) : Condition(null, false), Condition.Callback {
+) : Condition(scope, null, false) {
+
+ private var job: Job? = null
+ private val _startStrategy by lazy { calculateStartStrategy() }
override fun start() {
- onConditionChanged(this)
- conditions.forEach { it.addCallback(this) }
- }
+ job =
+ scope.launch {
+ val groupedConditions = conditions.groupBy { it.isOverridingCondition }
- override fun onConditionChanged(condition: Condition) {
- Evaluator.evaluate(conditions, operand)?.also { value -> updateCondition(value) }
- ?: clearCondition()
+ lazilyEvaluate(
+ conditions = groupedConditions.getOrDefault(true, emptyList()),
+ filterUnknown = true
+ )
+ .distinctUntilChanged()
+ .flatMapLatest { overriddenValue ->
+ // If there are overriding conditions with values set, they take precedence.
+ if (overriddenValue == null) {
+ lazilyEvaluate(
+ conditions = groupedConditions.getOrDefault(false, emptyList()),
+ filterUnknown = false
+ )
+ } else {
+ flowOf(overriddenValue)
+ }
+ }
+ .collect { conditionMet ->
+ if (conditionMet == null) {
+ clearCondition()
+ } else {
+ updateCondition(conditionMet)
+ }
+ }
+ }
}
override fun stop() {
- conditions.forEach { it.removeCallback(this) }
+ job?.cancel()
+ job = null
+ }
+
+ /**
+ * Evaluates a list of conditions lazily with support for short-circuiting. Conditions are
+ * executed serially in the order provided. At any point if the result can be determined, we
+ * short-circuit and return the result without executing all conditions.
+ */
+ private fun lazilyEvaluate(
+ conditions: Collection<Condition>,
+ filterUnknown: Boolean,
+ ): Flow<Boolean?> = callbackFlow {
+ val jobs = MutableList<Job?>(conditions.size) { null }
+ val values = MutableList<Boolean?>(conditions.size) { null }
+ val flows = conditions.map { it.toFlow() }
+
+ fun cancelAllExcept(indexToSkip: Int) {
+ for (index in 0 until jobs.size) {
+ if (index == indexToSkip) {
+ continue
+ }
+ if (
+ indexToSkip == -1 ||
+ conditions.elementAt(index).startStrategy == START_WHEN_NEEDED
+ ) {
+ jobs[index]?.cancel()
+ jobs[index] = null
+ values[index] = null
+ }
+ }
+ }
+
+ fun collectFlow(index: Int) {
+ // Base case which is triggered once we have collected all the flows. In this case,
+ // we never short-circuited and therefore should return the fully evaluated
+ // conditions.
+ if (flows.isEmpty() || index == -1) {
+ val filteredValues =
+ if (filterUnknown) {
+ values.filterNotNull()
+ } else {
+ values
+ }
+ trySend(Evaluator.evaluate(filteredValues, operand))
+ return
+ }
+ jobs[index] =
+ scope.launch {
+ flows.elementAt(index).collect { value ->
+ values[index] = value
+ if (shouldEarlyReturn(value)) {
+ trySend(value)
+ // The overall result is contingent on this condition, so we don't need
+ // to monitor any other conditions.
+ cancelAllExcept(index)
+ } else {
+ collectFlow(jobs.indexOfFirst { it == null })
+ }
+ }
+ }
+ }
+
+ // Collect any eager conditions immediately.
+ var started = false
+ for ((index, condition) in conditions.withIndex()) {
+ if (condition.startStrategy == START_EAGERLY) {
+ collectFlow(index)
+ started = true
+ }
+ }
+
+ // If no eager conditions started, start the first condition to kick off evaluation.
+ if (!started) {
+ collectFlow(0)
+ }
+ awaitClose { cancelAllExcept(-1) }
+ }
+
+ private fun shouldEarlyReturn(conditionMet: Boolean?): Boolean {
+ return when (operand) {
+ Evaluator.OP_AND -> conditionMet == false
+ Evaluator.OP_OR -> conditionMet == true
+ else -> false
+ }
+ }
+
+ /**
+ * Calculate the start strategy for this condition. This depends on the strategies of the child
+ * conditions. If there are any eager conditions, we must also start this condition eagerly. In
+ * the absence of eager conditions, we check for lazy conditions. In the absence of either, we
+ * make the condition only start when needed.
+ */
+ private fun calculateStartStrategy(): Int {
+ var startStrategy = START_WHEN_NEEDED
+ for (condition in conditions) {
+ when (condition.startStrategy) {
+ START_EAGERLY -> return START_EAGERLY
+ START_LAZILY -> {
+ startStrategy = START_LAZILY
+ }
+ START_WHEN_NEEDED -> {
+ // this is the default, so do nothing
+ }
+ }
+ }
+ return startStrategy
+ }
+
+ override fun getStartStrategy(): Int {
+ return _startStrategy
}
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java
index cc48090e1217..6bf1ce57b01e 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Condition.java
@@ -18,11 +18,14 @@ package com.android.systemui.shared.condition;
import android.util.Log;
+import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleOwner;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
@@ -30,6 +33,8 @@ import java.util.Collection;
import java.util.Iterator;
import java.util.List;
+import kotlinx.coroutines.CoroutineScope;
+
/**
* Base class for a condition that needs to be fulfilled in order for {@link Monitor} to inform
* its callbacks.
@@ -39,24 +44,27 @@ public abstract class Condition {
private final ArrayList<WeakReference<Callback>> mCallbacks = new ArrayList<>();
private final boolean mOverriding;
+ private final CoroutineScope mScope;
private Boolean mIsConditionMet;
private boolean mStarted = false;
/**
* By default, conditions have an initial value of false and are not overriding.
*/
- public Condition() {
- this(false, false);
+ public Condition(CoroutineScope scope) {
+ this(scope, false, false);
}
/**
* Constructor for specifying initial state and overriding condition attribute.
+ *
* @param initialConditionMet Initial state of the condition.
- * @param overriding Whether this condition overrides others.
+ * @param overriding Whether this condition overrides others.
*/
- protected Condition(Boolean initialConditionMet, boolean overriding) {
+ protected Condition(CoroutineScope scope, Boolean initialConditionMet, boolean overriding) {
mIsConditionMet = initialConditionMet;
mOverriding = overriding;
+ mScope = scope;
}
/**
@@ -70,6 +78,29 @@ public abstract class Condition {
protected abstract void stop();
/**
+ * Condition should be started as soon as there is an active subscription.
+ */
+ public static final int START_EAGERLY = 0;
+ /**
+ * Condition should be started lazily only if needed. But once started, it will not be cancelled
+ * unless there are no more active subscriptions.
+ */
+ public static final int START_LAZILY = 1;
+ /**
+ * Condition should be started lazily only if needed, and can be stopped when not needed. This
+ * should be used for conditions which are expensive to keep running.
+ */
+ public static final int START_WHEN_NEEDED = 2;
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({START_EAGERLY, START_LAZILY, START_WHEN_NEEDED})
+ @interface StartStrategy {
+ }
+
+ @StartStrategy
+ protected abstract int getStartStrategy();
+
+ /**
* Returns whether the current condition overrides
*/
public boolean isOverridingCondition() {
@@ -183,6 +214,7 @@ public abstract class Condition {
/**
* Returns whether the condition is set. This method should be consulted to understand the
* value of {@link #isConditionMet()}.
+ *
* @return {@code true} if value is present, {@code false} otherwise.
*/
public boolean isConditionSet() {
@@ -210,17 +242,18 @@ public abstract class Condition {
* conditions are true.
*/
public Condition and(@NonNull Collection<Condition> others) {
- final List<Condition> conditions = new ArrayList<>(others);
+ final List<Condition> conditions = new ArrayList<>();
conditions.add(this);
- return new CombinedCondition(conditions, Evaluator.OP_AND);
+ conditions.addAll(others);
+ return new CombinedCondition(mScope, conditions, Evaluator.OP_AND);
}
/**
* Creates a new condition which will only be true when both this condition and the provided
* condition is true.
*/
- public Condition and(@NonNull Condition other) {
- return new CombinedCondition(Arrays.asList(this, other), Evaluator.OP_AND);
+ public Condition and(@NonNull Condition... others) {
+ return and(Arrays.asList(others));
}
/**
@@ -228,17 +261,18 @@ public abstract class Condition {
* provided conditions are true.
*/
public Condition or(@NonNull Collection<Condition> others) {
- final List<Condition> conditions = new ArrayList<>(others);
+ final List<Condition> conditions = new ArrayList<>();
conditions.add(this);
- return new CombinedCondition(conditions, Evaluator.OP_OR);
+ conditions.addAll(others);
+ return new CombinedCondition(mScope, conditions, Evaluator.OP_OR);
}
/**
* Creates a new condition which will only be true when either this condition or the provided
* condition is true.
*/
- public Condition or(@NonNull Condition other) {
- return new CombinedCondition(Arrays.asList(this, other), Evaluator.OP_OR);
+ public Condition or(@NonNull Condition... others) {
+ return or(Arrays.asList(others));
}
/**
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/ConditionExtensions.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/ConditionExtensions.kt
index 8f8bff86f64d..84edc3577007 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/ConditionExtensions.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/ConditionExtensions.kt
@@ -1,14 +1,22 @@
package com.android.systemui.shared.condition
+import com.android.systemui.shared.condition.Condition.StartStrategy
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
+import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
/** Converts a boolean flow to a [Condition] object which can be used with a [Monitor] */
@JvmOverloads
-fun Flow<Boolean>.toCondition(scope: CoroutineScope, initialValue: Boolean? = null): Condition {
- return object : Condition(initialValue, false) {
+fun Flow<Boolean>.toCondition(
+ scope: CoroutineScope,
+ @StartStrategy strategy: Int,
+ initialValue: Boolean? = null
+): Condition {
+ return object : Condition(scope, initialValue, false) {
var job: Job? = null
override fun start() {
@@ -19,5 +27,25 @@ fun Flow<Boolean>.toCondition(scope: CoroutineScope, initialValue: Boolean? = nu
job?.cancel()
job = null
}
+
+ override fun getStartStrategy() = strategy
}
}
+
+/** Converts a [Condition] to a boolean flow */
+fun Condition.toFlow(): Flow<Boolean?> {
+ return callbackFlow {
+ val callback =
+ Condition.Callback { condition ->
+ if (condition.isConditionSet) {
+ trySend(condition.isConditionMet)
+ } else {
+ trySend(null)
+ }
+ }
+ addCallback(callback)
+ callback.onConditionChanged(this@toFlow)
+ awaitClose { removeCallback(callback) }
+ }
+ .distinctUntilChanged()
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
index 454294f36d2a..584d9785c300 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/condition/Evaluator.kt
@@ -22,7 +22,7 @@ import android.annotation.IntDef
* Helper for evaluating a collection of [Condition] objects with a given
* [Evaluator.ConditionOperand]
*/
-internal object Evaluator {
+object Evaluator {
/** Operands for combining multiple conditions together */
@Retention(AnnotationRetention.SOURCE)
@IntDef(value = [OP_AND, OP_OR])
@@ -70,15 +70,31 @@ internal object Evaluator {
fun evaluate(conditions: Collection<Condition>, @ConditionOperand operand: Int): Boolean? {
if (conditions.isEmpty()) return null
// If there are overriding conditions with values set, they take precedence.
- val targetConditions =
+ val values: Collection<Boolean?> =
conditions
.filter { it.isConditionSet && it.isOverridingCondition }
.ifEmpty { conditions }
+ .map { condition ->
+ if (condition.isConditionSet) {
+ condition.isConditionMet
+ } else {
+ null
+ }
+ }
+ return evaluate(values = values, operand = operand)
+ }
+
+ /**
+ * Evaluates a set of booleans with a given operand
+ *
+ * @param operand The operand to use when evaluating.
+ * @return Either true or false if the value is known, or null if value is unknown
+ */
+ internal fun evaluate(values: Collection<Boolean?>, @ConditionOperand operand: Int): Boolean? {
+ if (values.isEmpty()) return null
return when (operand) {
- OP_AND ->
- threeValuedAndOrOr(conditions = targetConditions, returnValueIfAnyMatches = false)
- OP_OR ->
- threeValuedAndOrOr(conditions = targetConditions, returnValueIfAnyMatches = true)
+ OP_AND -> threeValuedAndOrOr(values = values, returnValueIfAnyMatches = false)
+ OP_OR -> threeValuedAndOrOr(values = values, returnValueIfAnyMatches = true)
else -> null
}
}
@@ -90,16 +106,16 @@ internal object Evaluator {
* any value is true.
*/
private fun threeValuedAndOrOr(
- conditions: Collection<Condition>,
+ values: Collection<Boolean?>,
returnValueIfAnyMatches: Boolean
): Boolean? {
var hasUnknown = false
- for (condition in conditions) {
- if (!condition.isConditionSet) {
+ for (value in values) {
+ if (value == null) {
hasUnknown = true
continue
}
- if (condition.isConditionMet == returnValueIfAnyMatches) {
+ if (value == returnValueIfAnyMatches) {
return returnValueIfAnyMatches
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 8b87e2a538ca..4bf7be6df5be 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -42,14 +42,14 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
import com.android.systemui.log.dagger.KeyguardLargeClockLog
import com.android.systemui.log.dagger.KeyguardSmallClockLog
import com.android.systemui.plugins.ClockController
import com.android.systemui.plugins.ClockFaceController
import com.android.systemui.plugins.ClockTickRate
import com.android.systemui.plugins.WeatherData
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.DEBUG
import com.android.systemui.shared.regionsampling.RegionSampler
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index a6c782d88e18..1ca63fb88342 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -18,9 +18,10 @@ import androidx.annotation.VisibleForTesting;
import com.android.keyguard.dagger.KeyguardStatusViewScope;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
+import com.android.systemui.log.LogBuffer;
+import com.android.systemui.log.LogLevel;
import com.android.systemui.plugins.ClockController;
-import com.android.systemui.plugins.log.LogBuffer;
-import com.android.systemui.plugins.log.LogLevel;
+import com.android.systemui.shared.clocks.DefaultClockController;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -46,6 +47,9 @@ public class KeyguardClockSwitch extends RelativeLayout {
public static final int LARGE = 0;
public static final int SMALL = 1;
+ // compensate for translation of parents subject to device screen
+ // In this case, the translation comes from KeyguardStatusView
+ public int screenOffsetYPadding = 0;
/** Returns a region for the large clock to position itself, based on the given parent. */
public static Rect getLargeClockRegion(ViewGroup parent) {
@@ -161,8 +165,18 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
if (mLargeClockFrame.isLaidOut()) {
- mClock.getLargeClock().getEvents().onTargetRegionChanged(
- getLargeClockRegion(mLargeClockFrame));
+ Rect targetRegion = getLargeClockRegion(mLargeClockFrame);
+ if (mClock instanceof DefaultClockController) {
+ mClock.getLargeClock().getEvents().onTargetRegionChanged(
+ targetRegion);
+ } else {
+ mClock.getLargeClock().getEvents().onTargetRegionChanged(
+ new Rect(
+ targetRegion.left,
+ targetRegion.top - screenOffsetYPadding,
+ targetRegion.right,
+ targetRegion.bottom - screenOffsetYPadding));
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index a34c9fa5aced..d8bf570954df 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -39,10 +39,10 @@ import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.log.LogBuffer;
+import com.android.systemui.log.LogLevel;
import com.android.systemui.log.dagger.KeyguardClockLog;
import com.android.systemui.plugins.ClockController;
-import com.android.systemui.plugins.log.LogBuffer;
-import com.android.systemui.plugins.log.LogLevel;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.clocks.ClockRegistry;
import com.android.systemui.shared.regionsampling.RegionSampler;
@@ -169,6 +169,16 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
}
/**
+ * Used for status view to pass the screen offset from parent view
+ */
+ public void setLockscreenClockY(int clockY) {
+ if (mView.screenOffsetYPadding != clockY) {
+ mView.screenOffsetYPadding = clockY;
+ mView.updateClockTargetRegions();
+ }
+ }
+
+ /**
* Attach the controller to the view it relates to.
*/
@Override
@@ -394,13 +404,6 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
PropertyAnimator.setProperty(mStatusArea, AnimatableProperty.TRANSLATION_X,
x, props, animate);
}
-
- }
-
- void updateKeyguardStatusViewOffset() {
- // updateClockTargetRegions will call onTargetRegionChanged
- // which will require the correct translationY property of keyguardStatusView after updating
- mView.updateClockTargetRegions();
}
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 0826f8a8b985..68d8143a4154 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -215,6 +215,15 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
}
/**
+ * Pass top margin from ClockPositionAlgorithm in NotificationPanelViewController
+ * Use for clock view in LS to compensate for top margin to align to the screen
+ * Regardless of translation from AOD and unlock gestures
+ */
+ public void setLockscreenClockY(int clockY) {
+ mKeyguardClockSwitchController.setLockscreenClockY(clockY);
+ }
+
+ /**
* Set whether the view accessibility importance mode.
*/
public void setStatusAccessibilityImportance(int mode) {
@@ -230,7 +239,6 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
* Update position of the view with an optional animation
*/
public void updatePosition(int x, int y, float scale, boolean animate) {
- float oldY = mView.getY();
setProperty(AnimatableProperty.Y, y, animate);
ClockController clock = mKeyguardClockSwitchController.getClock();
@@ -246,10 +254,6 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
setProperty(AnimatableProperty.SCALE_X, 1f, animate);
setProperty(AnimatableProperty.SCALE_Y, 1f, animate);
}
-
- if (oldY != y) {
- mKeyguardClockSwitchController.updateKeyguardStatusViewOffset();
- }
}
/**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
index 651c9796140e..d8568ba56ebc 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardVisibilityHelper.java
@@ -22,8 +22,8 @@ import android.util.Property;
import android.view.View;
import com.android.systemui.animation.Interpolators;
-import com.android.systemui.plugins.log.LogBuffer;
-import com.android.systemui.plugins.log.LogLevel;
+import com.android.systemui.log.LogBuffer;
+import com.android.systemui.log.LogLevel;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.notification.AnimatableProperty;
import com.android.systemui.statusbar.notification.PropertyAnimator;
diff --git a/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java b/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java
index 6740375c4329..2d0bf9cc2aba 100644
--- a/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java
+++ b/packages/SystemUI/src/com/android/keyguard/dagger/ClockRegistryModule.java
@@ -27,9 +27,9 @@ import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
+import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.dagger.KeyguardClockLog;
import com.android.systemui.plugins.PluginManager;
-import com.android.systemui.plugins.log.LogBuffer;
import com.android.systemui.shared.clocks.ClockRegistry;
import com.android.systemui.shared.clocks.DefaultClockProvider;
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/BiometricMessageDeferralLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/BiometricMessageDeferralLogger.kt
index 2bb75aa34c6a..e7295ef9052c 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/BiometricMessageDeferralLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/BiometricMessageDeferralLogger.kt
@@ -17,9 +17,9 @@
package com.android.keyguard.logging
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
import com.android.systemui.log.dagger.BiometricLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.DEBUG
import javax.inject.Inject
/** Helper class for logging for [com.android.systemui.biometrics.FaceHelpMessageDeferral] */
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/BiometricUnlockLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/BiometricUnlockLogger.kt
index 20f90072161b..c00b2c612fa2 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/BiometricUnlockLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/BiometricUnlockLogger.kt
@@ -18,11 +18,11 @@ package com.android.keyguard.logging
import android.hardware.biometrics.BiometricSourceType
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogLevel.INFO
import com.android.systemui.log.dagger.BiometricLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
-import com.android.systemui.plugins.log.LogLevel.DEBUG
-import com.android.systemui.plugins.log.LogLevel.INFO
import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_DISMISS_BOUNCER
import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_NONE
import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_ONLY_WAKE
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt
index 4d71a8952021..8b925b1bfb54 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardLogger.kt
@@ -18,9 +18,9 @@ package com.android.keyguard.logging
import com.android.systemui.biometrics.AuthRippleController
import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.log.dagger.KeyguardLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
import com.android.systemui.statusbar.KeyguardIndicationController
import com.google.errorprone.annotations.CompileTimeConstant
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
index 4974f797d59a..c2d22c3e1d14 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt
@@ -27,13 +27,13 @@ import com.android.keyguard.KeyguardListenModel
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.keyguard.TrustGrantFlags
import com.android.systemui.log.dagger.KeyguardUpdateMonitorLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
-import com.android.systemui.plugins.log.LogLevel.DEBUG
-import com.android.systemui.plugins.log.LogLevel.ERROR
-import com.android.systemui.plugins.log.LogLevel.INFO
-import com.android.systemui.plugins.log.LogLevel.VERBOSE
-import com.android.systemui.plugins.log.LogLevel.WARNING
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogLevel.ERROR
+import com.android.systemui.log.LogLevel.INFO
+import com.android.systemui.log.LogLevel.VERBOSE
+import com.android.systemui.log.LogLevel.WARNING
import com.google.errorprone.annotations.CompileTimeConstant
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/keyguard/logging/TrustRepositoryLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/TrustRepositoryLogger.kt
index 249b3fe97d81..daafea8b62c7 100644
--- a/packages/SystemUI/src/com/android/keyguard/logging/TrustRepositoryLogger.kt
+++ b/packages/SystemUI/src/com/android/keyguard/logging/TrustRepositoryLogger.kt
@@ -18,9 +18,9 @@ package com.android.keyguard.logging
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.TrustModel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.log.dagger.KeyguardUpdateMonitorLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
import javax.inject.Inject
/** Logging helper for trust repository. */
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 3579e8cc0218..fd9cee0d6144 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -829,9 +829,9 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
final Rect overlayBounds = new Rect(
0, /* left */
- 0, /* top */
+ mCachedDisplayInfo.getNaturalHeight() / 2, /* top */
mCachedDisplayInfo.getNaturalWidth(), /* right */
- mCachedDisplayInfo.getNaturalHeight() /* botom */);
+ mCachedDisplayInfo.getNaturalHeight() /* bottom */);
mUdfpsOverlayParams = new UdfpsOverlayParams(
mUdfpsBounds,
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
index d0ac2968ae8e..55f6d072563b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt
@@ -37,7 +37,7 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.WakefulnessLifecycle
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogLevel
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.CircleReveal
import com.android.systemui.statusbar.LiftReveal
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
index f876affb2a9c..d953a885fe1f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt
@@ -364,7 +364,12 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
if (accessibilityManager.isTouchExplorationEnabled && isEnrollment) {
Rect(overlayParams.sensorBounds)
} else {
- Rect(overlayParams.overlayBounds)
+ Rect(
+ 0,
+ 0,
+ overlayParams.naturalDisplayWidth,
+ overlayParams.naturalDisplayHeight
+ )
}
} else {
Rect(overlayParams.sensorBounds)
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsLogger.kt b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsLogger.kt
index 0d08b4307f12..39199d194cc9 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsLogger.kt
@@ -16,12 +16,12 @@
package com.android.systemui.biometrics
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.LogLevel.ERROR
+import com.android.systemui.log.LogLevel.VERBOSE
+import com.android.systemui.log.LogLevel.WARNING
import com.android.systemui.log.dagger.UdfpsLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
-import com.android.systemui.plugins.log.LogLevel.ERROR
-import com.android.systemui.plugins.log.LogLevel.VERBOSE
-import com.android.systemui.plugins.log.LogLevel.WARNING
import com.google.errorprone.annotations.CompileTimeConstant
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BluetoothLogger.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/BluetoothLogger.kt
index d99625a9fbf2..96af42bfda22 100644
--- a/packages/SystemUI/src/com/android/systemui/bluetooth/BluetoothLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/bluetooth/BluetoothLogger.kt
@@ -17,9 +17,9 @@
package com.android.systemui.bluetooth
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.log.dagger.BluetoothLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
import javax.inject.Inject
/** Helper class for logging bluetooth events. */
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt b/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
index d27708fc04d7..5b3a982ab5e2 100644
--- a/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/logging/BroadcastDispatcherLogger.kt
@@ -20,11 +20,11 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
-import com.android.systemui.plugins.log.LogLevel.DEBUG
-import com.android.systemui.plugins.log.LogLevel.INFO
-import com.android.systemui.plugins.log.LogMessage
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogLevel.INFO
+import com.android.systemui.log.LogMessage
import com.android.systemui.log.dagger.BroadcastDispatcherLog
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
index d19c6ec01109..536978009f71 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLogger.kt
@@ -19,10 +19,10 @@ package com.android.systemui.doze
import android.view.Display
import com.android.systemui.doze.DozeLog.Reason
import com.android.systemui.doze.DozeLog.reasonToString
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.DEBUG
-import com.android.systemui.plugins.log.LogLevel.ERROR
-import com.android.systemui.plugins.log.LogLevel.INFO
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogLevel.ERROR
+import com.android.systemui.log.LogLevel.INFO
import com.android.systemui.log.dagger.DozeLog
import com.android.systemui.statusbar.policy.DevicePostureController
import com.google.errorprone.annotations.CompileTimeConstant
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamLogger.kt b/packages/SystemUI/src/com/android/systemui/dreams/DreamLogger.kt
index eb7929095a4b..fdb765130157 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamLogger.kt
@@ -16,9 +16,9 @@
package com.android.systemui.dreams
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
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}. */
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java b/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java
index 250cfeca5aa4..c889ac214cda 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/conditions/AssistantAttentionCondition.java
@@ -18,11 +18,14 @@ package com.android.systemui.dreams.conditions;
import com.android.internal.app.AssistUtils;
import com.android.internal.app.IVisualQueryDetectionAttentionListener;
+import com.android.systemui.dagger.qualifiers.Application;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.shared.condition.Condition;
import javax.inject.Inject;
+import kotlinx.coroutines.CoroutineScope;
+
/**
* {@link AssistantAttentionCondition} provides a signal when assistant has the user's attention.
*/
@@ -58,8 +61,10 @@ public class AssistantAttentionCondition extends Condition {
@Inject
public AssistantAttentionCondition(
+ @Application CoroutineScope scope,
DreamOverlayStateController dreamOverlayStateController,
AssistUtils assistUtils) {
+ super(scope);
mDreamOverlayStateController = dreamOverlayStateController;
mAssistUtils = assistUtils;
}
@@ -75,6 +80,11 @@ public class AssistantAttentionCondition extends Condition {
mDreamOverlayStateController.removeCallback(mCallback);
}
+ @Override
+ protected int getStartStrategy() {
+ return START_EAGERLY;
+ }
+
private void enableVisualQueryDetection() {
if (mEnabled) {
return;
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java b/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java
index 3ef19b760826..99688bee68e0 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/conditions/DreamCondition.java
@@ -19,19 +19,20 @@ import android.app.DreamManager;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.dagger.qualifiers.Application;
import com.android.systemui.shared.condition.Condition;
import javax.inject.Inject;
+import kotlinx.coroutines.CoroutineScope;
+
/**
* {@link DreamCondition} provides a signal when a dream begins and ends.
*/
public class DreamCondition extends Condition {
private final DreamManager mDreamManager;
-
private final KeyguardUpdateMonitor mUpdateMonitor;
-
private final KeyguardUpdateMonitorCallback mUpdateCallback =
new KeyguardUpdateMonitorCallback() {
@Override
@@ -41,7 +42,11 @@ public class DreamCondition extends Condition {
};
@Inject
- public DreamCondition(DreamManager dreamManager, KeyguardUpdateMonitor monitor) {
+ public DreamCondition(
+ @Application CoroutineScope scope,
+ DreamManager dreamManager,
+ KeyguardUpdateMonitor monitor) {
+ super(scope);
mDreamManager = dreamManager;
mUpdateMonitor = monitor;
}
@@ -56,4 +61,9 @@ public class DreamCondition extends Condition {
protected void stop() {
mUpdateMonitor.removeCallback(mUpdateCallback);
}
+
+ @Override
+ protected int getStartStrategy() {
+ return START_EAGERLY;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt
index a2f65ba747ab..4b03fd334cb5 100644
--- a/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt
+++ b/packages/SystemUI/src/com/android/systemui/dump/DumpHandler.kt
@@ -24,7 +24,7 @@ import com.android.systemui.R
import com.android.systemui.dump.DumpHandler.Companion.PRIORITY_ARG_CRITICAL
import com.android.systemui.dump.DumpHandler.Companion.PRIORITY_ARG_NORMAL
import com.android.systemui.dump.nano.SystemUIProtoDump
-import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.log.LogBuffer
import com.android.systemui.shared.system.UncaughtExceptionPreHandlerManager
import com.google.protobuf.nano.MessageNano
import java.io.BufferedOutputStream
diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
index ab8052c54f92..2d57633e47a8 100644
--- a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt
@@ -19,7 +19,7 @@ package com.android.systemui.dump
import com.android.systemui.Dumpable
import com.android.systemui.ProtoDumpable
import com.android.systemui.dump.nano.SystemUIProtoDump
-import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.log.LogBuffer
import java.io.PrintWriter
import java.util.TreeMap
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt b/packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
index 8299b13d305f..0eab1afc4119 100644
--- a/packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
+++ b/packages/SystemUI/src/com/android/systemui/dump/LogBufferEulogizer.kt
@@ -19,7 +19,7 @@ package com.android.systemui.dump
import android.content.Context
import android.util.Log
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.log.LogBuffer
import com.android.systemui.util.io.Files
import com.android.systemui.util.time.SystemClock
import java.io.IOException
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 6ca409f07f6f..1fafa3d97c48 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -62,7 +62,8 @@ object Flags {
val INSTANT_VOICE_REPLY = unreleasedFlag(111, "instant_voice_reply")
// TODO(b/279735475): Tracking Bug
- @JvmField val NEW_LIGHT_BAR_LOGIC = unreleasedFlag(279735475, "new_light_bar_logic")
+ @JvmField
+ val NEW_LIGHT_BAR_LOGIC = unreleasedFlag(279735475, "new_light_bar_logic", teamfood = true)
/**
* This flag is server-controlled and should stay as [unreleasedFlag] since we never want to
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt
index 2ef5e19bf382..328beed3ae4b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt
@@ -159,6 +159,7 @@ class KeyboardBacklightDialog(
private fun buildRootView(): LinearLayout {
val linearLayout =
LinearLayout(context).apply {
+ id = R.id.keyboard_backlight_dialog_container
orientation = LinearLayout.HORIZONTAL
layoutParams = LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
setPadding(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
index e650b9fc0e47..7c5641fcda9c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt
@@ -19,7 +19,7 @@ package com.android.systemui.keyguard.domain.interactor
import com.android.keyguard.logging.KeyguardLogger
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.plugins.log.LogLevel.VERBOSE
+import com.android.systemui.log.LogLevel.VERBOSE
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
diff --git a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
index 8e9328117e38..fefa1b29b576 100644
--- a/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/FaceAuthenticationLogger.kt
@@ -6,9 +6,8 @@ import com.android.keyguard.FaceAuthUiEvent
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.ErrorAuthenticationStatus
import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.log.LogLevel.DEBUG
import com.android.systemui.log.dagger.FaceAuthLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.DEBUG
import javax.inject.Inject
private const val TAG = "DeviceEntryFaceAuthRepositoryLog"
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt b/packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt
index d6e29e0f2067..e4465acb14ab 100644
--- a/packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt
@@ -19,9 +19,6 @@ package com.android.systemui.log
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
import com.android.systemui.log.LogBufferHelper.Companion.adjustMaxSize
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogcatEchoTracker
-
import javax.inject.Inject
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
index 4300f371e2e1..f7277842c026 100644
--- a/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/ScreenDecorationsLogger.kt
@@ -21,10 +21,10 @@ import android.graphics.Rect
import android.graphics.RectF
import androidx.core.graphics.toRectF
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogLevel.ERROR
import com.android.systemui.log.dagger.ScreenDecorationsLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.DEBUG
-import com.android.systemui.plugins.log.LogLevel.ERROR
import com.google.errorprone.annotations.CompileTimeConstant
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/BiometricLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/BiometricLog.java
index 4b774d3b2192..233f7a123ff4 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/BiometricLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/BiometricLog.java
@@ -23,7 +23,7 @@ import java.lang.annotation.RetentionPolicy;
import javax.inject.Qualifier;
/**
- * A {@link com.android.systemui.plugins.log.LogBuffer} for BiometricMessages processing such as
+ * A {@link com.android.systemui.log.LogBuffer} for BiometricMessages processing such as
* {@link com.android.systemui.biometrics.FaceHelpMessageDeferral}
*/
@Qualifier
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/BroadcastDispatcherLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/BroadcastDispatcherLog.java
index 5cca1ab2abe7..7d1f1c2709fa 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/BroadcastDispatcherLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/BroadcastDispatcherLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java
index 1d016d837b02..9ca0293fbd86 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/DozeLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/DozeLog.java
index c9f78bcdeef8..7c5f4025117f 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/DozeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/DozeLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardClockLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardClockLog.kt
index 9f563fe4eae5..8732ef576335 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardClockLog.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardClockLog.kt
@@ -18,19 +18,19 @@ package com.android.systemui.log.dagger
import javax.inject.Qualifier
-/** A [com.android.systemui.plugins.log.LogBuffer] for keyguard clock logs. */
+/** A [com.android.systemui.log.LogBuffer] for keyguard clock logs. */
@Qualifier
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class KeyguardClockLog
-/** A [com.android.systemui.plugins.log.LogBuffer] for small keyguard clock logs. */
+/** A [com.android.systemui.log.LogBuffer] for small keyguard clock logs. */
@Qualifier
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class KeyguardSmallClockLog
-/** A [com.android.systemui.plugins.log.LogBuffer] for large keyguard clock logs. */
+/** A [com.android.systemui.log.LogBuffer] for large keyguard clock logs. */
@Qualifier
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LSShadeTransitionLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LSShadeTransitionLog.java
index 76d20bea4bdf..08d969b5eb77 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LSShadeTransitionLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LSShadeTransitionLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
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 6988bd899e23..9be18ace79fa 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -22,13 +22,13 @@ import android.os.Looper;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.LogBufferFactory;
+import com.android.systemui.log.LogcatEchoTracker;
+import com.android.systemui.log.LogcatEchoTrackerDebug;
+import com.android.systemui.log.LogcatEchoTrackerProd;
import com.android.systemui.log.table.TableLogBuffer;
import com.android.systemui.log.table.TableLogBufferFactory;
-import com.android.systemui.plugins.log.LogBuffer;
-import com.android.systemui.plugins.log.LogcatEchoTracker;
-import com.android.systemui.plugins.log.LogcatEchoTrackerDebug;
-import com.android.systemui.plugins.log.LogcatEchoTrackerProd;
import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.util.Compile;
import com.android.systemui.util.wakelock.WakeLockLog;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/MediaBrowserLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/MediaBrowserLog.java
index af433476b38c..1c00c93f4e38 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/MediaBrowserLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/MediaBrowserLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/MediaCarouselControllerLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/MediaCarouselControllerLog.java
index f4dac6efe371..86a916ef6541 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/MediaCarouselControllerLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/MediaCarouselControllerLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/MediaMuteAwaitLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/MediaMuteAwaitLog.java
index 73690ab6c24d..c67d8bebe313 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/MediaMuteAwaitLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/MediaMuteAwaitLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/MediaTimeoutListenerLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/MediaTimeoutListenerLog.java
index 0c2cd92d1bb0..98e6556d7f53 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/MediaTimeoutListenerLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/MediaTimeoutListenerLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/MediaViewLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/MediaViewLog.java
index 5b7f4bb103b4..dde0ee0796d4 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/MediaViewLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/MediaViewLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NearbyMediaDevicesLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NearbyMediaDevicesLog.java
index 6d91f0c97c8a..b1c6dcfcb13b 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/NearbyMediaDevicesLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NearbyMediaDevicesLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotifInteractionLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotifInteractionLog.java
index 26af4964f7b8..20fc6ff445a6 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/NotifInteractionLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotifInteractionLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationHeadsUpLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationHeadsUpLog.java
index 61daf9c8d71c..fcc184a317b8 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationHeadsUpLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationHeadsUpLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationInterruptLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationInterruptLog.java
index a59afa0fed1b..760fbf3928b6 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationInterruptLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationInterruptLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java
index a2d381ec90f0..f1646a837132 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLockscreenLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLog.java
index 6f8ea7ff2e9b..a0b686487bec 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationRenderLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationRenderLog.java
index 835d3490293c..8c8753a07339 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationRenderLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationRenderLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationSectionLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationSectionLog.java
index 6e2bd7b2e1b5..7259eebf19b6 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationSectionLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/NotificationSectionLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/PrivacyLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/PrivacyLog.java
index 77b1bf5fd630..e96e532f94bf 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/PrivacyLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/PrivacyLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/QSConfigLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/QSConfigLog.java
index 295bf88d498f..973f6501bbfd 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/QSConfigLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/QSConfigLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/QSFragmentDisableLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/QSFragmentDisableLog.java
index 9fd166b759d2..557a254e5c09 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/QSFragmentDisableLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/QSFragmentDisableLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/QSLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/QSLog.java
index dd168bac5654..dd5010cf39a8 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/QSLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/QSLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/ShadeLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/ShadeLog.java
index d24bfcb88188..bd0d298ebdee 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/ShadeLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/ShadeLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/ShadeWindowLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/ShadeWindowLog.java
index 1d2b68c3bf46..4aa2b1d84b21 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/ShadeWindowLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/ShadeWindowLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/StatusBarNetworkControllerLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/StatusBarNetworkControllerLog.java
index af0f7c518e64..f26b3164f488 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/StatusBarNetworkControllerLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/StatusBarNetworkControllerLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/SwipeUpLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/SwipeUpLog.java
index d58b538f2047..4d797c1a88cd 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/SwipeUpLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/SwipeUpLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/ToastLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/ToastLog.java
index ba8b27c23ec1..8671dbfdf1fe 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/ToastLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/ToastLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/UnseenNotificationLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/UnseenNotificationLog.java
index 5c2321be4388..dbb6e8cbcc07 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/UnseenNotificationLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/UnseenNotificationLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.log.dagger;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
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 8babfc90d269..1d785ae62d87 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBuffer.kt
@@ -20,8 +20,8 @@ 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.log.LogLevel
+import com.android.systemui.log.LogcatEchoTracker
import com.android.systemui.util.time.SystemClock
import java.io.PrintWriter
import java.text.SimpleDateFormat
@@ -35,7 +35,7 @@ import kotlinx.coroutines.launch
* A logger that logs changes in table format.
*
* Some parts of System UI maintain a lot of pieces of state at once.
- * [com.android.systemui.plugins.log.LogBuffer] allows us to easily log change events:
+ * [com.android.systemui.log.LogBuffer] allows us to easily log change events:
* - 10-10 10:10:10.456: state2 updated to newVal2
* - 10-10 10:11:00.000: stateN updated to StateN(val1=true, val2=1)
* - 10-10 10:11:02.123: stateN updated to StateN(val1=true, val2=2)
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 42e742db2842..19e112487c46 100644
--- a/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/table/TableLogBufferFactory.kt
@@ -21,7 +21,7 @@ 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.log.LogcatEchoTracker
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutLogger.kt
index f731dc064355..e2e269de71a0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaTimeoutLogger.kt
@@ -18,9 +18,9 @@ package com.android.systemui.media.controls.pipeline
import android.media.session.PlaybackState
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.log.dagger.MediaTimeoutListenerLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
import javax.inject.Inject
private const val TAG = "MediaTimeout"
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
index 095cf09a6c2c..9e53d77dec99 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/resume/ResumeMediaBrowserLogger.kt
@@ -18,9 +18,9 @@ package com.android.systemui.media.controls.resume
import android.content.ComponentName
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.log.dagger.MediaBrowserLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
import javax.inject.Inject
/** A logger for events in [ResumeMediaBrowser]. */
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselControllerLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselControllerLogger.kt
index 9af11b924ec8..0ed24349bdf4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselControllerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselControllerLogger.kt
@@ -17,9 +17,9 @@
package com.android.systemui.media.controls.ui
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.log.dagger.MediaCarouselControllerLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
import javax.inject.Inject
/** A debug logger for [MediaCarouselController]. */
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewLogger.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewLogger.kt
index fdac33ac20b0..c781b7699b26 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaViewLogger.kt
@@ -17,9 +17,9 @@
package com.android.systemui.media.controls.ui
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.log.dagger.MediaViewLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
import javax.inject.Inject
private const val TAG = "MediaView"
diff --git a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
index 9ae4577b0394..46efac56ab9d 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
@@ -17,6 +17,7 @@
package com.android.systemui.media.dagger;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.LogBufferFactory;
import com.android.systemui.media.controls.pipeline.MediaDataManager;
import com.android.systemui.media.controls.ui.MediaHierarchyManager;
@@ -30,16 +31,15 @@ import com.android.systemui.media.taptotransfer.MediaTttCommandLineHelper;
import com.android.systemui.media.taptotransfer.MediaTttFlags;
import com.android.systemui.media.taptotransfer.receiver.MediaTttReceiverLogBuffer;
import com.android.systemui.media.taptotransfer.sender.MediaTttSenderLogBuffer;
-import com.android.systemui.plugins.log.LogBuffer;
-
-import java.util.Optional;
-
-import javax.inject.Named;
import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
+import java.util.Optional;
+
+import javax.inject.Named;
+
/** Dagger module for the media package. */
@Module(subcomponents = {
MediaComplicationComponent.class,
diff --git a/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitLogger.kt b/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitLogger.kt
index 5ace3ea8a05b..bbcf259418c8 100644
--- a/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/muteawait/MediaMuteAwaitLogger.kt
@@ -2,8 +2,8 @@ package com.android.systemui.media.muteawait
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.dagger.MediaMuteAwaitLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import javax.inject.Inject
/** Log messages for [MediaMuteAwaitConnectionManager]. */
diff --git a/packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesLogger.kt b/packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesLogger.kt
index 78408fce5a36..66399d580582 100644
--- a/packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesLogger.kt
@@ -2,8 +2,8 @@ package com.android.systemui.media.nearby
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.dagger.NearbyMediaDevicesLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import javax.inject.Inject
/** Log messages for [NearbyMediaDevicesManager]. */
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtils.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtils.kt
index 0e839c6dbc7a..eeda102702d2 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtils.kt
@@ -16,8 +16,8 @@
package com.android.systemui.media.taptotransfer.common
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
/** A helper for logging media tap-to-transfer events. */
object MediaTttLoggerUtils {
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLogBuffer.java b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLogBuffer.java
index 67e464c344c5..31ccb9afac9f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLogBuffer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLogBuffer.java
@@ -18,7 +18,7 @@ package com.android.systemui.media.taptotransfer.receiver;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLogger.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLogger.kt
index b0c6257df96c..1502df725a9c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLogger.kt
@@ -18,8 +18,8 @@ package com.android.systemui.media.taptotransfer.receiver
import android.app.StatusBarManager
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
import com.android.systemui.media.taptotransfer.common.MediaTttLoggerUtils
-import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.temporarydisplay.TemporaryViewLogger
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogBuffer.java b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogBuffer.java
index a262e97864f3..edee4a808968 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogBuffer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogBuffer.java
@@ -18,7 +18,7 @@ package com.android.systemui.media.taptotransfer.sender;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogger.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogger.kt
index 964a95b9be9a..03bcfc8113e3 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLogger.kt
@@ -18,9 +18,9 @@ package com.android.systemui.media.taptotransfer.sender
import android.app.StatusBarManager
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.media.taptotransfer.common.MediaTttLoggerUtils
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
import javax.inject.Inject
/** A logger for all events related to the media tap-to-transfer sender experience. */
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
index 166ba9fba166..79167f276576 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt
@@ -15,7 +15,6 @@
package com.android.systemui.privacy
import android.content.Context
-import android.content.res.Configuration
import android.util.AttributeSet
import android.view.Gravity.CENTER_VERTICAL
import android.view.Gravity.END
@@ -103,11 +102,6 @@ class OngoingPrivacyChip @JvmOverloads constructor(
R.string.ongoing_privacy_chip_content_multiple_apps, typesText)
}
- override fun onConfigurationChanged(newConfig: Configuration?) {
- super.onConfigurationChanged(newConfig)
- updateResources()
- }
-
private fun updateResources() {
iconMargin = context.resources
.getDimensionPixelSize(R.dimen.ongoing_appops_chip_icon_margin)
@@ -116,11 +110,8 @@ class OngoingPrivacyChip @JvmOverloads constructor(
iconColor =
Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.colorPrimary)
- val height = context.resources
- .getDimensionPixelSize(R.dimen.ongoing_appops_chip_height)
val padding = context.resources
.getDimensionPixelSize(R.dimen.ongoing_appops_chip_side_padding)
- iconsContainer.layoutParams.height = height
iconsContainer.setPaddingRelative(padding, 0, padding, 0)
iconsContainer.background = context.getDrawable(R.drawable.statusbar_privacy_chip_bg)
}
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt b/packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt
index 03503fd1ff61..f9e1adff012b 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/logging/PrivacyLogger.kt
@@ -18,9 +18,9 @@ package com.android.systemui.privacy.logging
import android.permission.PermissionGroupUsage
import com.android.systemui.log.dagger.PrivacyLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
-import com.android.systemui.plugins.log.LogMessage
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.LogMessage
import com.android.systemui.privacy.PrivacyDialog
import com.android.systemui.privacy.PrivacyItem
import java.text.SimpleDateFormat
diff --git a/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java b/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java
index 80fbf9115065..b6a5ad6f2155 100644
--- a/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java
@@ -16,11 +16,14 @@
package com.android.systemui.process.condition;
+import com.android.systemui.dagger.qualifiers.Application;
import com.android.systemui.process.ProcessWrapper;
import com.android.systemui.shared.condition.Condition;
import javax.inject.Inject;
+import kotlinx.coroutines.CoroutineScope;
+
/**
* {@link SystemProcessCondition} checks to make sure the current process is being ran by the
* System User.
@@ -29,8 +32,9 @@ public class SystemProcessCondition extends Condition {
private final ProcessWrapper mProcessWrapper;
@Inject
- public SystemProcessCondition(ProcessWrapper processWrapper) {
- super();
+ public SystemProcessCondition(@Application CoroutineScope scope,
+ ProcessWrapper processWrapper) {
+ super(scope);
mProcessWrapper = processWrapper;
}
@@ -42,4 +46,9 @@ public class SystemProcessCondition extends Condition {
@Override
protected void stop() {
}
+
+ @Override
+ protected int getStartStrategy() {
+ return START_EAGERLY;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt
index 025fb228b829..cd52ec29177d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt
@@ -1,8 +1,8 @@
package com.android.systemui.qs
import com.android.systemui.log.dagger.QSFragmentDisableLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.statusbar.disableflags.DisableFlagsLogger
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
index 5b461a6d8bad..c00a81cbf12b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
@@ -21,14 +21,14 @@ import android.content.res.Configuration.ORIENTATION_PORTRAIT
import android.content.res.Configuration.Orientation
import android.service.quicksettings.Tile
import android.view.View
+import com.android.systemui.log.ConstantStringsLogger
+import com.android.systemui.log.ConstantStringsLoggerImpl
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogLevel.ERROR
+import com.android.systemui.log.LogLevel.VERBOSE
import com.android.systemui.log.dagger.QSConfigLog
import com.android.systemui.log.dagger.QSLog
-import com.android.systemui.plugins.log.ConstantStringsLogger
-import com.android.systemui.plugins.log.ConstantStringsLoggerImpl
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.DEBUG
-import com.android.systemui.plugins.log.LogLevel.ERROR
-import com.android.systemui.plugins.log.LogLevel.VERBOSE
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.statusbar.StatusBarState
import com.google.errorprone.annotations.CompileTimeConstant
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSPipelineModule.kt
index e85440cad6b0..a066242fd96b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSPipelineModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/dagger/QSPipelineModule.kt
@@ -18,8 +18,8 @@ package com.android.systemui.qs.pipeline.dagger
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogBufferFactory
-import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.qs.pipeline.data.repository.TileSpecRepository
import com.android.systemui.qs.pipeline.data.repository.TileSpecSettingsRepository
import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor
diff --git a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt
index 767ce919d027..b564334b5c52 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/pipeline/shared/logging/QSPipelineLogger.kt
@@ -17,8 +17,8 @@
package com.android.systemui.qs.pipeline.shared.logging
import android.annotation.UserIdInt
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.qs.pipeline.dagger.QSTileListLog
import com.android.systemui.qs.pipeline.shared.TileSpec
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 137a99ef39b8..4b44ac01e60a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -1513,6 +1513,8 @@ public final class NotificationPanelViewController implements ShadeSurface, Dump
mKeyguardStatusViewController.getClockBottom(mStatusBarHeaderHeightKeyguard),
mKeyguardStatusViewController.isClockTopAligned());
mClockPositionAlgorithm.run(mClockPositionResult);
+ mKeyguardStatusViewController.setLockscreenClockY(
+ mClockPositionAlgorithm.getExpandedPreferredClockY());
mKeyguardBottomAreaInteractor.setClockPosition(
mClockPositionResult.clockX, mClockPositionResult.clockY);
boolean animate = mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending();
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
index 1839e13dcdec..25073c1b64db 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
@@ -18,8 +18,8 @@ package com.android.systemui.shade
import android.view.MotionEvent
import com.android.systemui.log.dagger.ShadeLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.shade.ShadeViewController.Companion.FLING_COLLAPSE
import com.android.systemui.shade.ShadeViewController.Companion.FLING_EXPAND
import com.android.systemui.shade.ShadeViewController.Companion.FLING_HIDE
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt
index 9851625b6152..d8d42795be58 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeWindowLogger.kt
@@ -18,12 +18,12 @@ package com.android.systemui.shade
import android.view.WindowManager
import com.android.systemui.log.dagger.ShadeWindowLog
-import com.android.systemui.plugins.log.ConstantStringsLogger
-import com.android.systemui.plugins.log.ConstantStringsLoggerImpl
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
-import com.android.systemui.plugins.log.LogLevel.DEBUG
-import com.android.systemui.plugins.log.LogMessage
+import com.android.systemui.log.ConstantStringsLogger
+import com.android.systemui.log.ConstantStringsLoggerImpl
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogMessage
import javax.inject.Inject
private const val TAG = "systemui.shadewindow"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt
index 90c52bd8c9f4..e008ec0dc75c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActionClickLogger.kt
@@ -18,8 +18,8 @@ package com.android.systemui.statusbar
import android.app.PendingIntent
import com.android.systemui.log.dagger.NotifInteractionLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index ea5a1c0fbe70..0ea257010751 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -41,8 +41,8 @@ import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewCont
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRUST;
import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_USER_LOCKED;
import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_ON;
+import static com.android.systemui.log.LogLevel.ERROR;
import static com.android.systemui.plugins.FalsingManager.LOW_PENALTY;
-import static com.android.systemui.plugins.log.LogLevel.ERROR;
import android.app.AlarmManager;
import android.app.admin.DevicePolicyManager;
@@ -95,8 +95,8 @@ import com.android.systemui.keyguard.KeyguardIndication;
import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
+import com.android.systemui.log.LogLevel;
import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.log.LogLevel;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 129c8594e48e..77550038c94a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -26,7 +26,6 @@ import android.annotation.IntDef;
import android.app.ActivityManager;
import android.app.Notification;
import android.content.Context;
-import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
@@ -76,9 +75,9 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi
*/
private static final float DARK_ALPHA_BOOST = 0.67f;
/**
- * Status icons are currently drawn with the intention of being 17sp tall, but we
- * want to scale them (in a way that doesn't require an asset dump) down 2sp. So
- * 17sp * (15 / 17) = 15sp, the new height. After the first call to {@link #reloadDimens} all
+ * Status icons are currently drawn with the intention of being 17dp tall, but we
+ * want to scale them (in a way that doesn't require an asset dump) down 2dp. So
+ * 17dp * (15 / 17) = 15dp, the new height. After the first call to {@link #reloadDimens} all
* values will be in px.
*/
private float mSystemIconDesiredHeight = 15f;
@@ -145,7 +144,7 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi
private String mNumberText;
private StatusBarNotification mNotification;
private final boolean mBlocked;
- private Configuration mConfiguration;
+ private int mDensity;
private boolean mNightMode;
private float mIconScale = 1.0f;
private final Paint mDotPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
@@ -199,8 +198,9 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi
mNumberPain.setAntiAlias(true);
setNotification(sbn);
setScaleType(ScaleType.CENTER);
- mConfiguration = new Configuration(context.getResources().getConfiguration());
- mNightMode = (mConfiguration.uiMode & Configuration.UI_MODE_NIGHT_MASK)
+ mDensity = context.getResources().getDisplayMetrics().densityDpi;
+ Configuration configuration = context.getResources().getConfiguration();
+ mNightMode = (configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK)
== Configuration.UI_MODE_NIGHT_YES;
initializeDecorColor();
reloadDimens();
@@ -214,7 +214,7 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi
mAlwaysScaleIcon = true;
reloadDimens();
maybeUpdateIconScaleDimens();
- mConfiguration = new Configuration(context.getResources().getConfiguration());
+ mDensity = context.getResources().getDisplayMetrics().densityDpi;
}
/** Should always be preceded by {@link #reloadDimens()} */
@@ -231,17 +231,12 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi
private void updateIconScaleForNotifications() {
final float imageBounds = mIncreasedSize ?
mStatusBarIconDrawingSizeIncreased : mStatusBarIconDrawingSize;
- float iconHeight = getIconHeight();
- if (iconHeight != 0) {
- mIconScale = imageBounds / iconHeight;
- } else {
- final int outerBounds = mStatusBarIconSize;
- mIconScale = imageBounds / (float) outerBounds;
- }
+ final int outerBounds = mStatusBarIconSize;
+ mIconScale = imageBounds / (float)outerBounds;
updatePivot();
}
- // Makes sure that all icons are scaled to the same height (15sp). If we cannot get a height
+ // Makes sure that all icons are scaled to the same height (15dp). If we cannot get a height
// for the icon, it uses the default SCALE (15f / 17f) which is the old behavior
private void updateIconScaleForSystemIcons() {
float iconHeight = getIconHeight();
@@ -272,10 +267,12 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- final int configDiff = newConfig.diff(mConfiguration);
- mConfiguration.setTo(newConfig);
- if ((configDiff & (ActivityInfo.CONFIG_DENSITY | ActivityInfo.CONFIG_FONT_SCALE)) != 0) {
- updateIconDimens();
+ int density = newConfig.densityDpi;
+ if (density != mDensity) {
+ mDensity = density;
+ reloadDimens();
+ updateDrawable();
+ maybeUpdateIconScaleDimens();
}
boolean nightMode = (newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK)
== Configuration.UI_MODE_NIGHT_YES;
@@ -285,15 +282,6 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi
}
}
- /**
- * Update the icon dimens and drawable with current resources
- */
- public void updateIconDimens() {
- reloadDimens();
- updateDrawable();
- maybeUpdateIconScaleDimens();
- }
-
private void reloadDimens() {
boolean applyRadius = mDotRadius == mStaticDotRadius;
Resources res = getResources();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
index 6e74542691a5..2465c21c956f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
@@ -73,9 +73,9 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.log.LogBuffer;
+import com.android.systemui.log.LogLevel;
import com.android.systemui.log.dagger.StatusBarNetworkControllerLog;
-import com.android.systemui.plugins.log.LogBuffer;
-import com.android.systemui.plugins.log.LogLevel;
import com.android.systemui.qs.tiles.dialog.InternetDialogFactory;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
@@ -87,6 +87,8 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceP
import com.android.systemui.telephony.TelephonyListenerManager;
import com.android.systemui.util.CarrierConfigTracker;
+import kotlin.Unit;
+
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -101,8 +103,6 @@ import java.util.stream.Collectors;
import javax.inject.Inject;
-import kotlin.Unit;
-
/** Platform implementation of the network controller. **/
@SysUISingleton
public class NetworkControllerImpl extends BroadcastReceiver
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureLogger.kt
index 9ce6b02e55d9..a67c26c06cb9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/gesture/SwipeUpGestureLogger.kt
@@ -18,8 +18,8 @@ package com.android.systemui.statusbar.gesture
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.dagger.SwipeUpLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import javax.inject.Inject
/** Log messages for [SwipeUpGestureHandler]. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt
index 3058fbbc1031..a3a72d92c2e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationClickerLogger.kt
@@ -17,8 +17,8 @@
package com.android.systemui.statusbar.notification
import com.android.systemui.log.dagger.NotifInteractionLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
index dd3c2a9df3e5..f7679ed058c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLogger.kt
@@ -13,9 +13,9 @@
package com.android.systemui.statusbar.notification
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
import com.android.systemui.log.dagger.NotificationLockscreenLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.DEBUG
import com.android.systemui.statusbar.StatusBarState
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/RemoteInputControllerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/RemoteInputControllerLogger.kt
index 9582dfad35cd..487a5f87d0bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/RemoteInputControllerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/RemoteInputControllerLogger.kt
@@ -17,9 +17,9 @@
package com.android.systemui.statusbar.notification
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
import com.android.systemui.log.dagger.NotificationRemoteInputLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.DEBUG
import javax.inject.Inject
/** Logger class for [RemoteInputController]. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerLogger.kt
index 68d1319699d4..39d0833c57d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coalescer/GroupCoalescerLogger.kt
@@ -17,8 +17,8 @@
package com.android.systemui.statusbar.notification.collection.coalescer
import com.android.systemui.log.dagger.NotificationLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import javax.inject.Inject
class GroupCoalescerLogger @Inject constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt
index 2919def16304..79c63e6b0db1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt
@@ -1,8 +1,8 @@
package com.android.systemui.statusbar.notification.collection.coordinator
import com.android.systemui.log.dagger.NotificationLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.statusbar.notification.row.NotificationGuts
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt
index 32c3c6665b6f..e17ce5cff37d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorLogger.kt
@@ -3,8 +3,8 @@ package com.android.systemui.statusbar.notification.collection.coordinator
import android.util.Log
import com.android.systemui.log.dagger.NotificationHeadsUpLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import javax.inject.Inject
private const val TAG = "HeadsUpCoordinator"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorLogger.kt
index 6503a6403eaa..1f8ec3411bcd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorLogger.kt
@@ -16,9 +16,9 @@
package com.android.systemui.statusbar.notification.collection.coordinator
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.log.dagger.UnseenNotificationLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
import javax.inject.Inject
private const val TAG = "KeyguardCoordinator"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt
index 9558f47af795..6271d38f1efa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorLogger.kt
@@ -17,8 +17,8 @@
package com.android.systemui.statusbar.notification.collection.coordinator
import com.android.systemui.log.dagger.NotificationLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorLogger.kt
index d80445491bda..1f4861a10e75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorLogger.kt
@@ -17,8 +17,8 @@
package com.android.systemui.statusbar.notification.collection.coordinator
import com.android.systemui.log.dagger.NotificationLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import javax.inject.Inject
private const val TAG = "ShadeEventCoordinator"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
index 4adc90aec0fb..f13ff6814df8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt
@@ -17,10 +17,10 @@
package com.android.systemui.statusbar.notification.collection.listbuilder
import com.android.systemui.log.dagger.NotificationLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.DEBUG
-import com.android.systemui.plugins.log.LogLevel.INFO
-import com.android.systemui.plugins.log.LogLevel.WARNING
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogLevel.INFO
+import com.android.systemui.log.LogLevel.WARNING
import com.android.systemui.statusbar.notification.NotifPipelineFlags
import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.ListEntry
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
index 911a2d0c2b36..20de785bc9bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
@@ -21,12 +21,12 @@ import android.service.notification.NotificationListenerService
import android.service.notification.NotificationListenerService.RankingMap
import android.service.notification.StatusBarNotification
import com.android.systemui.log.dagger.NotificationLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.DEBUG
-import com.android.systemui.plugins.log.LogLevel.ERROR
-import com.android.systemui.plugins.log.LogLevel.INFO
-import com.android.systemui.plugins.log.LogLevel.WARNING
-import com.android.systemui.plugins.log.LogLevel.WTF
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogLevel.ERROR
+import com.android.systemui.log.LogLevel.INFO
+import com.android.systemui.log.LogLevel.WARNING
+import com.android.systemui.log.LogLevel.WTF
import com.android.systemui.statusbar.notification.collection.NotifCollection
import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason
import com.android.systemui.statusbar.notification.collection.NotifCollection.FutureDismissal
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderLogger.kt
index 9c71e5c1054c..07fd349d3786 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderLogger.kt
@@ -17,8 +17,8 @@
package com.android.systemui.statusbar.notification.collection.render
import com.android.systemui.log.dagger.NotificationLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.statusbar.notification.NotifPipelineFlags
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
import com.android.systemui.util.Compile
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferLogger.kt
index 1e22c2cd7c0e..a880b7157708 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/ShadeViewDifferLogger.kt
@@ -17,8 +17,8 @@
package com.android.systemui.statusbar.notification.collection.render
import com.android.systemui.log.dagger.NotificationLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import java.lang.RuntimeException
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt
index d4f11fc141f0..0b31265963ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/HeadsUpViewBinderLogger.kt
@@ -1,8 +1,8 @@
package com.android.systemui.statusbar.notification.interruption
import com.android.systemui.log.dagger.NotificationHeadsUpLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.INFO
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.INFO
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
index 115e050258c3..5bac2a9350a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/NotificationInterruptLogger.kt
@@ -19,10 +19,10 @@ package com.android.systemui.statusbar.notification.interruption
import android.util.Log
import com.android.systemui.log.dagger.NotificationInterruptLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.DEBUG
-import com.android.systemui.plugins.log.LogLevel.INFO
-import com.android.systemui.plugins.log.LogLevel.WARNING
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogLevel.INFO
+import com.android.systemui.log.LogLevel.WARNING
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
import com.android.systemui.util.Compile
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationRoundnessLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationRoundnessLogger.kt
index 10197a38527e..fe03b2ad6a32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationRoundnessLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationRoundnessLogger.kt
@@ -16,9 +16,9 @@
package com.android.systemui.statusbar.notification.logging
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.INFO
import com.android.systemui.log.dagger.NotificationRenderLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.INFO
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.notification.stack.NotificationSection
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt
index 46fef3f973a7..45be0b151870 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotifBindPipelineLogger.kt
@@ -17,8 +17,8 @@
package com.android.systemui.statusbar.notification.row
import com.android.systemui.log.dagger.NotificationLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.INFO
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.INFO
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index 4522e41daf91..b4bfded58e4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -966,7 +966,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
@Override
public ApplicationInfo getApplicationInfo() {
- ApplicationInfo applicationInfo = super.getApplicationInfo();
+ ApplicationInfo applicationInfo = new ApplicationInfo(super.getApplicationInfo());
applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_RTL;
return applicationInfo;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowLogger.kt
index ce11be36acf3..c3dd92a51a91 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowLogger.kt
@@ -17,9 +17,9 @@
package com.android.systemui.statusbar.notification.row
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.log.dagger.NotificationLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt
index 8a5d29a1ae2d..684a276ed635 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/RowContentBindStageLogger.kt
@@ -17,8 +17,8 @@
package com.android.systemui.statusbar.notification.row
import com.android.systemui.log.dagger.NotificationLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.INFO
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.INFO
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt
index b61c55edadcd..f9531876e30d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt
@@ -18,8 +18,8 @@ package com.android.systemui.statusbar.notification.stack
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.dagger.NotificationSectionLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import javax.inject.Inject
private const val TAG = "NotifSections"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLogger.kt
index 64dd6dcd3008..5b0ec1d14edc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLogger.kt
@@ -1,9 +1,9 @@
package com.android.systemui.statusbar.notification.stack
import com.android.systemui.log.dagger.NotificationHeadsUpLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.DEBUG
-import com.android.systemui.plugins.log.LogLevel.INFO
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogLevel.INFO
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.AnimationEvent.ANIMATION_TYPE_ADD
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateLogger.kt
index f5de678a8536..cca84b3330a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateLogger.kt
@@ -1,8 +1,8 @@
package com.android.systemui.statusbar.notification.stack
import com.android.systemui.log.dagger.NotificationHeadsUpLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.statusbar.notification.logKey
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 90a6d0fac7ca..eba04f13ac4b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -239,7 +239,11 @@ public class KeyguardClockPositionAlgorithm {
}
}
- private int getExpandedPreferredClockY() {
+ /**
+ * give the static topMargin, used for lockscreen clocks to get the initial translationY
+ * to do counter translation
+ */
+ public int getExpandedPreferredClockY() {
if (mIsSplitShade) {
return mSplitShadeTargetTopMargin;
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
index e835c5cebbc3..12ed71bf14d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java
@@ -45,7 +45,7 @@ import com.android.systemui.R;
import com.android.systemui.animation.InterpolatorsAndroidX;
import com.android.systemui.battery.BatteryMeterViewController;
import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.plugins.log.LogLevel;
+import com.android.systemui.log.LogLevel;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.ShadeViewStateProvider;
import com.android.systemui.statusbar.CommandQueue;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt
index 4839fe6a7bef..5c357d7cd3ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LSShadeTransitionLogger.kt
@@ -20,8 +20,8 @@ import android.util.DisplayMetrics
import android.view.View
import com.android.internal.logging.nano.MetricsProto.MetricsEvent
import com.android.systemui.log.dagger.LSShadeTransitionLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index b9a12e28b8ca..006a029de8e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -306,7 +306,7 @@ public class NotificationIconContainer extends ViewGroup {
public void applyIconStates() {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
- IconState childState = mIconStates.get(child);
+ ViewState childState = mIconStates.get(child);
if (childState != null) {
childState.applyToView(child);
}
@@ -339,7 +339,6 @@ public class NotificationIconContainer extends ViewGroup {
}
}
if (child instanceof StatusBarIconView) {
- ((StatusBarIconView) child).updateIconDimens();
((StatusBarIconView) child).setDozing(mDozing, false, 0);
}
}
@@ -448,14 +447,9 @@ public class NotificationIconContainer extends ViewGroup {
@VisibleForTesting
boolean isOverflowing(boolean isLastChild, float translationX, float layoutEnd,
float iconSize) {
- if (isLastChild) {
- return translationX + iconSize > layoutEnd;
- } else {
- // If the child is not the last child, we need to ensure that we have room for the next
- // icon and the dot. The dot could be as large as an icon, so verify that we have room
- // for 2 icons.
- return translationX + iconSize * 2f > layoutEnd;
- }
+ // Layout end, as used here, does not include padding end.
+ final float overflowX = isLastChild ? layoutEnd : layoutEnd - iconSize;
+ return translationX >= overflowX;
}
/**
@@ -495,7 +489,10 @@ public class NotificationIconContainer extends ViewGroup {
// First icon to overflow.
if (firstOverflowIndex == -1 && isOverflowing) {
firstOverflowIndex = i;
- mVisualOverflowStart = translationX;
+ mVisualOverflowStart = layoutEnd - mIconSize;
+ if (forceOverflow || mIsStaticLayout) {
+ mVisualOverflowStart = Math.min(translationX, mVisualOverflowStart);
+ }
}
final float drawingScale = mOnLockScreen && view instanceof StatusBarIconView
? ((StatusBarIconView) view).getIconScaleIncreased()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index 678873c0165c..a8a834f1e8f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -203,7 +203,8 @@ public interface StatusBarIconController {
@Override
protected LayoutParams onCreateLayoutParams() {
- LinearLayout.LayoutParams lp = super.onCreateLayoutParams();
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
lp.setMargins(mIconHPadding, 0, mIconHPadding, 0);
return lp;
}
@@ -369,7 +370,7 @@ public interface StatusBarIconController {
private final MobileIconsViewModel mMobileIconsViewModel;
protected final Context mContext;
- protected int mIconSize;
+ protected final int mIconSize;
// Whether or not these icons show up in dumpsys
protected boolean mShouldLog = false;
private StatusBarIconController mController;
@@ -394,10 +395,10 @@ public interface StatusBarIconController {
mStatusBarPipelineFlags = statusBarPipelineFlags;
mMobileContextProvider = mobileContextProvider;
mContext = group.getContext();
+ mIconSize = mContext.getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_icon_size);
mLocation = location;
- reloadDimens();
-
if (statusBarPipelineFlags.runNewMobileIconsBackend()) {
// This starts the flow for the new pipeline, and will notify us of changes if
// {@link StatusBarPipelineFlags#useNewMobileIcons} is also true.
@@ -608,9 +609,13 @@ public interface StatusBarIconController {
mGroup.removeAllViews();
}
- protected void reloadDimens() {
- mIconSize = mContext.getResources().getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_icon_size);
+ protected void onDensityOrFontScaleChanged() {
+ for (int i = 0; i < mGroup.getChildCount(); i++) {
+ View child = mGroup.getChildAt(i);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
+ child.setLayoutParams(lp);
+ }
}
private void setHeightAndCenter(ImageView imageView, int height) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 80d5651a65dc..3a184239ac43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -109,7 +109,6 @@ public class StatusBarIconControllerImpl implements Tunable,
}
group.setController(this);
- group.reloadDimens();
mIconGroups.add(group);
List<Slot> allSlots = mStatusBarIconList.getSlots();
for (int i = 0; i < allSlots.size(); i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
index 1f0b96a58da6..12f023b21701 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarterLogger.kt
@@ -18,11 +18,11 @@ package com.android.systemui.statusbar.phone
import android.app.PendingIntent
import com.android.systemui.log.dagger.NotifInteractionLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.DEBUG
-import com.android.systemui.plugins.log.LogLevel.ERROR
-import com.android.systemui.plugins.log.LogLevel.INFO
-import com.android.systemui.plugins.log.LogLevel.WARNING
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogLevel.ERROR
+import com.android.systemui.log.LogLevel.INFO
+import com.android.systemui.log.LogLevel.WARNING
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
index ddbfd43f9bf6..26c17674ab10 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusIconContainer.java
@@ -22,8 +22,6 @@ import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
import android.annotation.Nullable;
import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
@@ -74,16 +72,13 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
// Any ignored icon will never be added as a child
private ArrayList<String> mIgnoredSlots = new ArrayList<>();
- private Configuration mConfiguration;
-
public StatusIconContainer(Context context) {
this(context, null);
}
public StatusIconContainer(Context context, AttributeSet attrs) {
super(context, attrs);
- mConfiguration = new Configuration(context.getResources().getConfiguration());
- reloadDimens();
+ initDimens();
setWillNotDraw(!DEBUG_OVERFLOW);
}
@@ -100,7 +95,7 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
return mShouldRestrictIcons;
}
- private void reloadDimens() {
+ private void initDimens() {
// This is the same value that StatusBarIconView uses
mIconDotFrameWidth = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_icon_size);
@@ -216,16 +211,6 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
child.setTag(R.id.status_bar_view_state_tag, null);
}
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- final int configDiff = newConfig.diff(mConfiguration);
- mConfiguration.setTo(newConfig);
- if ((configDiff & (ActivityInfo.CONFIG_DENSITY | ActivityInfo.CONFIG_FONT_SCALE)) != 0) {
- reloadDimens();
- }
- }
-
/**
* Add a name of an icon slot to be ignored. It will not show up nor be measured
* @param slotName name of the icon as it exists in
@@ -363,17 +348,13 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
int totalVisible = mLayoutStates.size();
int maxVisible = totalVisible <= MAX_ICONS ? MAX_ICONS : MAX_ICONS - 1;
- // Init mUnderflowStart value with the offset to let the dot be placed next to battery icon.
- // It to prevent if the underflow happens at rightest(totalVisible - 1) child then break the
- // for loop with mUnderflowStart staying 0(initial value), causing the dot be placed at the
- // leftest side.
- mUnderflowStart = (int) Math.max(contentStart, width - getPaddingEnd() - mUnderflowWidth);
+ mUnderflowStart = 0;
int visible = 0;
int firstUnderflowIndex = -1;
for (int i = totalVisible - 1; i >= 0; i--) {
StatusIconState state = mLayoutStates.get(i);
// Allow room for underflow if we found we need it in onMeasure
- if ((mNeedsUnderflow && (state.getXTranslation() < (contentStart + mUnderflowWidth)))
+ if (mNeedsUnderflow && (state.getXTranslation() < (contentStart + mUnderflowWidth))
|| (mShouldRestrictIcons && (visible >= maxVisible))) {
firstUnderflowIndex = i;
break;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt
index 59f74ec453a6..8c19fb4f43c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt
@@ -17,8 +17,8 @@
package com.android.systemui.statusbar.phone.fragment
import com.android.systemui.log.dagger.CollapsedSbFragmentLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.statusbar.disableflags.DisableFlagsLogger
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
index b3d246164e87..19c77e0b0de3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt
@@ -22,7 +22,7 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.LogBufferFactory
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.TableLogBufferFactory
-import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.log.LogBuffer
import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepositoryImpl
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt
index 68cbbceb056d..b3a1c4075d87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/data/MobileInputLogger.kt
@@ -22,8 +22,8 @@ import android.telephony.TelephonyDisplayInfo
import com.android.settingslib.SignalIcon
import com.android.settingslib.mobile.MobileMappings
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.statusbar.pipeline.dagger.MobileInputLog
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt
index f2f91430eba6..7e0c145696c9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/MobileViewLogger.kt
@@ -20,8 +20,8 @@ import android.view.View
import com.android.systemui.Dumpable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.statusbar.pipeline.dagger.MobileViewLog
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
import java.io.PrintWriter
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/VerboseMobileViewLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/VerboseMobileViewLogger.kt
index f67bc8f14447..507549b1e234 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/VerboseMobileViewLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/VerboseMobileViewLogger.kt
@@ -19,8 +19,8 @@ package com.android.systemui.statusbar.pipeline.mobile.ui
import android.view.View
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.statusbar.pipeline.dagger.VerboseMobileViewLog
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger.Companion.getIdForLogging
import com.android.systemui.statusbar.pipeline.mobile.ui.model.SignalIconModel
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt
index 82492babba46..051f43f1059c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityInputLogger.kt
@@ -19,8 +19,8 @@ package com.android.systemui.statusbar.pipeline.shared
import android.net.Network
import android.net.NetworkCapabilities
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.statusbar.pipeline.dagger.SharedConnectivityInputLog
import com.android.systemui.statusbar.pipeline.shared.data.model.DefaultConnectionModel
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt
index a96e8ff20dd4..328d901b541d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/LoggerHelper.kt
@@ -18,8 +18,8 @@ package com.android.systemui.statusbar.pipeline.shared
import android.net.Network
import android.net.NetworkCapabilities
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
/** Helper object for logs that are shared between wifi and mobile. */
object LoggerHelper {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModel.kt
index 2a02687f0761..058eda4400df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModel.kt
@@ -17,7 +17,7 @@
package com.android.systemui.statusbar.pipeline.shared.data.model
import android.net.NetworkCapabilities
-import com.android.systemui.plugins.log.LogMessage
+import com.android.systemui.log.LogMessage
/**
* A model for all of the current default connections(s).
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt
index bb0b166f7aba..4a9ceacb0bd1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/WifiInputLogger.kt
@@ -19,8 +19,8 @@ package com.android.systemui.statusbar.pipeline.wifi.shared
import android.net.Network
import android.net.NetworkCapabilities
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.statusbar.pipeline.dagger.WifiInputLog
import com.android.systemui.statusbar.pipeline.shared.LoggerHelper
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt
index f61f3b7a70f0..6ba2a81b4b13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceStateRotationLockSettingControllerLogger.kt
@@ -21,9 +21,9 @@ import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_IGNORED
import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_LOCKED
import android.provider.Settings.Secure.DEVICE_STATE_ROTATION_LOCK_UNLOCKED
import com.android.internal.R
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.VERBOSE
import com.android.systemui.log.dagger.DeviceStateAutoRotationLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.VERBOSE
import javax.inject.Inject
class DeviceStateRotationLockSettingControllerLogger
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
index df1e80b78c9b..06ed1fd279b5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManagerLogger.kt
@@ -17,9 +17,9 @@
package com.android.systemui.statusbar.policy
import com.android.systemui.log.dagger.NotificationHeadsUpLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel.INFO
-import com.android.systemui.plugins.log.LogLevel.VERBOSE
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel.INFO
+import com.android.systemui.log.LogLevel.VERBOSE
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.logKey
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt
index b563d86f65b1..21d03386b9e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyStateInflater.kt
@@ -311,7 +311,7 @@ interface SmartActionInflater {
setBounds(0, 0, newIconSize, newIconSize)
}
// Add the action icon to the Smart Action button.
- setCompoundDrawables(iconDrawable, null, null, null)
+ setCompoundDrawablesRelative(iconDrawable, null, null, null)
val onClickListener = View.OnClickListener {
onSmartActionClick(entry, smartActions, actionIndex, action)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index 9e88ceb3a0d1..fb6ba8542a3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -588,15 +588,15 @@ public class SmartReplyView extends ViewGroup {
}
/**
- * Returns the combined width of the left drawable (the action icon) and the padding between the
- * drawable and the button text.
+ * Returns the combined width of the start drawable (the action icon) and the padding between
+ * the drawable and the button text.
*/
- private int getLeftCompoundDrawableWidthWithPadding(Button button) {
- Drawable[] drawables = button.getCompoundDrawables();
- Drawable leftDrawable = drawables[0];
- if (leftDrawable == null) return 0;
+ private int getStartCompoundDrawableWidthWithPadding(Button button) {
+ Drawable[] drawables = button.getCompoundDrawablesRelative();
+ Drawable startDrawable = drawables[0];
+ if (startDrawable == null) return 0;
- return leftDrawable.getBounds().width() + button.getCompoundDrawablePadding();
+ return startDrawable.getBounds().width() + button.getCompoundDrawablePadding();
}
private int squeezeButtonToTextWidth(Button button, int heightMeasureSpec, int textWidth) {
@@ -605,8 +605,8 @@ public class SmartReplyView extends ViewGroup {
// Re-measure the squeezed smart reply button.
clearLayoutLineCount(button);
final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(
- button.getPaddingLeft() + button.getPaddingRight() + textWidth
- + getLeftCompoundDrawableWidthWithPadding(button), MeasureSpec.AT_MOST);
+ button.getPaddingStart() + button.getPaddingEnd() + textWidth
+ + getStartCompoundDrawableWidthWithPadding(button), MeasureSpec.AT_MOST);
button.measure(widthMeasureSpec, heightMeasureSpec);
if (button.getLayout() == null) {
Log.wtf(TAG, "Button layout is null after measure.");
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt
index 667e22a82a2a..066ac04c2727 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt
@@ -17,8 +17,8 @@
package com.android.systemui.temporarydisplay
import android.view.View
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
/** A logger for temporary view changes -- see [TemporaryViewDisplayController]. */
open class TemporaryViewLogger<T : TemporaryViewInfo>(
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarLogger.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarLogger.kt
index f23942847e68..d55751b9d8a0 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarLogger.kt
@@ -17,8 +17,8 @@
package com.android.systemui.temporarydisplay.chipbar
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import com.android.systemui.temporarydisplay.TemporaryViewLogger
import com.android.systemui.temporarydisplay.dagger.ChipbarLog
import javax.inject.Inject
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/dagger/TemporaryDisplayModule.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/dagger/TemporaryDisplayModule.kt
index b1be4045eb43..cae13086f592 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/dagger/TemporaryDisplayModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/dagger/TemporaryDisplayModule.kt
@@ -18,9 +18,9 @@ package com.android.systemui.temporarydisplay.dagger
import android.content.Context
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogBufferFactory
import com.android.systemui.media.taptotransfer.MediaTttFlags
-import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.settings.DisplayTracker
import com.android.systemui.statusbar.gesture.SwipeUpGestureLogger
import com.android.systemui.temporarydisplay.chipbar.SwipeChipbarAwayGestureHandler
diff --git a/packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt b/packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt
index fda511433143..dfe748afbd41 100644
--- a/packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt
@@ -17,10 +17,10 @@
package com.android.systemui.toast
import com.android.systemui.log.dagger.ToastLog
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
-import com.android.systemui.plugins.log.LogLevel.DEBUG
-import com.android.systemui.plugins.log.LogMessage
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.LogLevel.DEBUG
+import com.android.systemui.log.LogMessage
import javax.inject.Inject
private const val TAG = "ToastLog"
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLockLog.java b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLockLog.java
index 59cb0525a7e9..9cebc330af12 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLockLog.java
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLockLog.java
@@ -18,7 +18,7 @@ package com.android.systemui.util.wakelock;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
diff --git a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLockLogger.kt b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLockLogger.kt
index 951903dc29bd..09268007dddc 100644
--- a/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLockLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/wakelock/WakeLockLogger.kt
@@ -17,8 +17,8 @@
package com.android.systemui.util.wakelock
import android.os.PowerManager
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
import javax.inject.Inject
class WakeLockLogger @Inject constructor(@WakeLockLog private val buffer: LogBuffer) {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
index 8f4b32006919..19d5278932c2 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/ClockEventControllerTest.kt
@@ -35,7 +35,7 @@ import com.android.systemui.plugins.ClockFaceController
import com.android.systemui.plugins.ClockFaceConfig
import com.android.systemui.plugins.ClockFaceEvents
import com.android.systemui.plugins.ClockTickRate
-import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.log.LogBuffer
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.ConfigurationController
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index 95db0c096faf..fb738454fc71 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -45,6 +45,7 @@ import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.log.LogBuffer;
import com.android.systemui.plugins.ClockAnimations;
import com.android.systemui.plugins.ClockController;
import com.android.systemui.plugins.ClockEvents;
@@ -52,7 +53,6 @@ import com.android.systemui.plugins.ClockFaceConfig;
import com.android.systemui.plugins.ClockFaceController;
import com.android.systemui.plugins.ClockFaceEvents;
import com.android.systemui.plugins.ClockTickRate;
-import com.android.systemui.plugins.log.LogBuffer;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shared.clocks.AnimatableClockView;
import com.android.systemui.shared.clocks.ClockRegistry;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt
index d7aa6e063d1e..14ad3acf7fb0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/TextAnimatorTest.kt
@@ -39,10 +39,6 @@ import org.mockito.Mockito.verify
import kotlin.math.ceil
-private val PAINT = TextPaint().apply {
- textSize = 32f
-}
-
@RunWith(AndroidTestingRunner::class)
@SmallTest
class TextAnimatorTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt
index 063757acc1a1..f6fcd16cfd00 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/TextInterpolatorTest.kt
@@ -49,7 +49,7 @@ private val VF_FONT = Font.Builder(File("/system/fonts/Roboto-Regular.ttf")).bui
private fun Font.toTypeface() =
Typeface.CustomFallbackBuilder(FontFamily.Builder(this).build()).build()
-private val PAINT = TextPaint().apply {
+internal val PAINT = TextPaint().apply {
typeface = Font.Builder(VF_FONT).setFontVariationSettings("'wght' 400").build().toTypeface()
textSize = 32f
}
@@ -79,7 +79,7 @@ class TextInterpolatorTest : SysuiTestCase() {
@Before
fun setup() {
- typefaceCache = TypefaceVariantCacheImpl()
+ typefaceCache = TypefaceVariantCacheImpl(PAINT.typeface)
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
index 2747e83acb23..8a62ea0d669e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt
@@ -25,7 +25,6 @@ import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_ENROL
import android.hardware.biometrics.BiometricOverlayConstants.ShowReason
import android.hardware.fingerprint.FingerprintManager
import android.hardware.fingerprint.IUdfpsOverlayControllerCallback
-import androidx.test.ext.junit.runners.AndroidJUnit4
import android.testing.TestableLooper.RunWithLooper
import android.view.LayoutInflater
import android.view.MotionEvent
@@ -35,6 +34,7 @@ import android.view.Surface.Rotation
import android.view.View
import android.view.WindowManager
import android.view.accessibility.AccessibilityManager
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.settingslib.udfps.UdfpsOverlayParams
@@ -69,8 +69,8 @@ import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit
+import org.mockito.Mockito.`when` as whenever
private const val REQUEST_ID = 2L
@@ -340,4 +340,22 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
assertThat(lp.height).isEqualTo(overlayParams.sensorBounds.height())
}
}
+
+ @Test
+ fun fullScreenOverlayWithNewTouchDetectionEnabled() = withRotation(ROTATION_0) {
+ withReason(REASON_AUTH_KEYGUARD) {
+ whenever(featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)).thenReturn(true)
+
+ controllerOverlay.show(udfpsController, overlayParams)
+ verify(windowManager).addView(
+ eq(controllerOverlay.overlayView),
+ layoutParamsCaptor.capture()
+ )
+
+ // Layout params should use natural display width and height
+ val lp = layoutParamsCaptor.value
+ assertThat(lp.width).isEqualTo(overlayParams.naturalDisplayWidth)
+ assertThat(lp.height).isEqualTo(overlayParams.naturalDisplayHeight)
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java
index ef1061faeed9..07cb5d88a515 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/AssistantAttentionConditionTest.java
@@ -42,6 +42,8 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import kotlinx.coroutines.CoroutineScope;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class AssistantAttentionConditionTest extends SysuiTestCase {
@@ -51,6 +53,8 @@ public class AssistantAttentionConditionTest extends SysuiTestCase {
AssistUtils mAssistUtils;
@Mock
DreamOverlayStateController mDreamOverlayStateController;
+ @Mock
+ CoroutineScope mScope;
private AssistantAttentionCondition mAssistantAttentionCondition;
@@ -59,7 +63,7 @@ public class AssistantAttentionConditionTest extends SysuiTestCase {
MockitoAnnotations.initMocks(this);
mAssistantAttentionCondition =
- new AssistantAttentionCondition(mDreamOverlayStateController, mAssistUtils);
+ new AssistantAttentionCondition(mScope, mDreamOverlayStateController, mAssistUtils);
// Adding a callback also starts the condition.
mAssistantAttentionCondition.addCallback(mCallback);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java
index e1c54976d734..68c79652ac00 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/conditions/DreamConditionTest.java
@@ -25,7 +25,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.DreamManager;
-import android.content.Context;
import android.testing.AndroidTestingRunner;
import androidx.test.filters.SmallTest;
@@ -42,13 +41,12 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import kotlinx.coroutines.CoroutineScope;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class DreamConditionTest extends SysuiTestCase {
@Mock
- Context mContext;
-
- @Mock
Condition.Callback mCallback;
@Mock
@@ -57,6 +55,9 @@ public class DreamConditionTest extends SysuiTestCase {
@Mock
KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+ @Mock
+ CoroutineScope mScope;
+
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
@@ -68,7 +69,8 @@ public class DreamConditionTest extends SysuiTestCase {
@Test
public void testInitialDreamingState() {
when(mDreamManager.isDreaming()).thenReturn(true);
- final DreamCondition condition = new DreamCondition(mDreamManager, mKeyguardUpdateMonitor);
+ final DreamCondition condition = new DreamCondition(mScope, mDreamManager,
+ mKeyguardUpdateMonitor);
condition.addCallback(mCallback);
verify(mCallback).onConditionChanged(eq(condition));
@@ -81,7 +83,8 @@ public class DreamConditionTest extends SysuiTestCase {
@Test
public void testInitialNonDreamingState() {
when(mDreamManager.isDreaming()).thenReturn(false);
- final DreamCondition condition = new DreamCondition(mDreamManager, mKeyguardUpdateMonitor);
+ final DreamCondition condition = new DreamCondition(mScope, mDreamManager,
+ mKeyguardUpdateMonitor);
condition.addCallback(mCallback);
verify(mCallback, never()).onConditionChanged(eq(condition));
@@ -96,7 +99,8 @@ public class DreamConditionTest extends SysuiTestCase {
final ArgumentCaptor<KeyguardUpdateMonitorCallback> callbackCaptor =
ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
when(mDreamManager.isDreaming()).thenReturn(true);
- final DreamCondition condition = new DreamCondition(mDreamManager, mKeyguardUpdateMonitor);
+ final DreamCondition condition = new DreamCondition(mScope, mDreamManager,
+ mKeyguardUpdateMonitor);
condition.addCallback(mCallback);
verify(mKeyguardUpdateMonitor).registerCallback(callbackCaptor.capture());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt
index 19135d0cc800..e8cbdf3db327 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpHandlerTest.kt
@@ -21,7 +21,7 @@ import com.android.systemui.CoreStartable
import com.android.systemui.Dumpable
import com.android.systemui.ProtoDumpable
import com.android.systemui.SysuiTestCase
-import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.log.LogBuffer
import com.android.systemui.shared.system.UncaughtExceptionPreHandlerManager
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt
index 55826141739f..02555cfa783a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt
@@ -19,7 +19,7 @@ package com.android.systemui.dump
import androidx.test.filters.SmallTest
import com.android.systemui.Dumpable
import com.android.systemui.SysuiTestCase
-import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.log.LogBuffer
import com.android.systemui.util.mockito.any
import java.io.PrintWriter
import org.junit.Before
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt
index 64547f4463d1..bd029a727ee3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/dump/LogBufferHelper.kt
@@ -16,9 +16,9 @@
package com.android.systemui.dump
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
-import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.LogcatEchoTracker
/**
* Creates a LogBuffer that will echo everything to logcat, which is useful for debugging tests.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt
index bf3c73a2c94e..c2195c7bc2c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/TrustRepositoryTest.kt
@@ -24,8 +24,8 @@ import com.android.keyguard.logging.TrustRepositoryLogger
import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogcatEchoTracker
import com.android.systemui.user.data.repository.FakeUserRepository
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
diff --git a/packages/SystemUI/plugin/tests/log/LogBufferTest.kt b/packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
index a39b856f0f49..0cf6d3da7e9c 100644
--- a/packages/SystemUI/plugin/tests/log/LogBufferTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/log/LogBufferTest.kt
@@ -2,7 +2,6 @@ package com.android.systemui.log
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.plugins.log.LogBuffer
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
import java.io.StringWriter
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 f867fc7bf84a..12f46898ab8d 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
@@ -18,10 +18,10 @@ package com.android.systemui.log.table
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.LogcatEchoTracker
import com.android.systemui.log.table.TableChange.Companion.IS_INITIAL_PREFIX
import com.android.systemui.log.table.TableChange.Companion.MAX_STRING_LENGTH
-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
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtilsTest.kt
index 8da1c646109d..b322bb7d6b46 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtilsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerUtilsTest.kt
@@ -19,9 +19,9 @@ package com.android.systemui.media.taptotransfer.common
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
+import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogBufferFactory
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.log.LogcatEchoTracker
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
import java.io.StringWriter
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLoggerTest.kt
index 95df484cddc2..64f3fd304ca6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttReceiverLoggerTest.kt
@@ -19,9 +19,9 @@ package com.android.systemui.media.taptotransfer.receiver
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
+import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogBufferFactory
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.log.LogcatEchoTracker
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
import java.io.StringWriter
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLoggerTest.kt
index 003375709a16..2287da572795 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttSenderLoggerTest.kt
@@ -19,9 +19,9 @@ package com.android.systemui.media.taptotransfer.sender
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
+import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogBufferFactory
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.log.LogcatEchoTracker
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
import java.io.StringWriter
diff --git a/packages/SystemUI/tests/src/com/android/systemui/process/condition/SystemProcessConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/process/condition/SystemProcessConditionTest.java
index fb7197706ddc..ff60fcda53e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/process/condition/SystemProcessConditionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/process/condition/SystemProcessConditionTest.java
@@ -37,6 +37,8 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import kotlinx.coroutines.CoroutineScope;
+
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@SmallTest
@@ -47,6 +49,9 @@ public class SystemProcessConditionTest extends SysuiTestCase {
@Mock
Monitor.Callback mCallback;
+ @Mock
+ CoroutineScope mScope;
+
private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
@Before
@@ -61,7 +66,7 @@ public class SystemProcessConditionTest extends SysuiTestCase {
@Test
public void testConditionFailsWithNonSystemProcess() {
- final Condition condition = new SystemProcessCondition(mProcessWrapper);
+ final Condition condition = new SystemProcessCondition(mScope, mProcessWrapper);
when(mProcessWrapper.isSystemUser()).thenReturn(false);
final Monitor monitor = new Monitor(mExecutor);
@@ -82,7 +87,7 @@ public class SystemProcessConditionTest extends SysuiTestCase {
@Test
public void testConditionSucceedsWithSystemProcess() {
- final Condition condition = new SystemProcessCondition(mProcessWrapper);
+ final Condition condition = new SystemProcessCondition(mScope, mProcessWrapper);
when(mProcessWrapper.isSystemUser()).thenReturn(true);
final Monitor monitor = new Monitor(mExecutor);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentDisableFlagsLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentDisableFlagsLoggerTest.kt
index 68c10f20f6f7..aacc695ef301 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentDisableFlagsLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentDisableFlagsLoggerTest.kt
@@ -20,7 +20,7 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.log.LogBufferFactory
-import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.log.LogcatEchoTracker
import com.android.systemui.statusbar.disableflags.DisableFlagsLogger
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java
index 31a33d4ff908..cbd9dba3cdbf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsTrampolineActivityTest.java
@@ -30,6 +30,7 @@ import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivit
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assume.assumeFalse;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -127,6 +128,9 @@ public final class AppClipsTrampolineActivityTest extends SysuiTestCase {
@Before
public void setUp() {
+ assumeFalse("Skip test: does not apply to watches",
+ mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH));
+
MockitoAnnotations.initMocks(this);
mMainHandler = mContext.getMainThreadHandler();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt
new file mode 100644
index 000000000000..1a0e932d7e8a
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/CombinedConditionTest.kt
@@ -0,0 +1,450 @@
+/*
+ * 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.shared.condition
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.shared.condition.Condition.START_EAGERLY
+import com.android.systemui.shared.condition.Condition.START_LAZILY
+import com.android.systemui.shared.condition.Condition.START_WHEN_NEEDED
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class CombinedConditionTest : SysuiTestCase() {
+
+ class FakeCondition
+ constructor(
+ scope: CoroutineScope,
+ initialValue: Boolean?,
+ overriding: Boolean = false,
+ @StartStrategy private val startStrategy: Int = START_WHEN_NEEDED,
+ ) : Condition(scope, initialValue, overriding) {
+ private var _started = false
+ val started: Boolean
+ get() = _started
+
+ override fun start() {
+ _started = true
+ }
+
+ override fun stop() {
+ _started = false
+ }
+
+ override fun getStartStrategy(): Int {
+ return startStrategy
+ }
+
+ fun setValue(value: Boolean?) {
+ value?.also { updateCondition(value) } ?: clearCondition()
+ }
+ }
+
+ @Test
+ fun testOrOperatorWithMixedConditions() = runSelfCancelingTest {
+ val startWhenNeededCondition =
+ FakeCondition(scope = this, initialValue = false, startStrategy = START_WHEN_NEEDED)
+ val eagerCondition =
+ FakeCondition(scope = this, initialValue = false, startStrategy = START_EAGERLY)
+ val lazyCondition =
+ FakeCondition(scope = this, initialValue = false, startStrategy = START_LAZILY)
+
+ val combinedCondition =
+ CombinedCondition(
+ scope = this,
+ conditions =
+ listOf(
+ eagerCondition,
+ lazyCondition,
+ startWhenNeededCondition,
+ ),
+ operand = Evaluator.OP_OR
+ )
+
+ val callback = Condition.Callback {}
+ combinedCondition.addCallback(callback)
+
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(eagerCondition.started).isTrue()
+ assertThat(lazyCondition.started).isTrue()
+ assertThat(startWhenNeededCondition.started).isTrue()
+
+ eagerCondition.setValue(true)
+ assertThat(combinedCondition.isConditionMet).isTrue()
+ assertThat(eagerCondition.started).isTrue()
+ assertThat(lazyCondition.started).isTrue()
+ assertThat(startWhenNeededCondition.started).isFalse()
+
+ startWhenNeededCondition.setValue(true)
+ assertThat(combinedCondition.isConditionMet).isTrue()
+ assertThat(eagerCondition.started).isTrue()
+ assertThat(lazyCondition.started).isTrue()
+ assertThat(startWhenNeededCondition.started).isFalse()
+
+ startWhenNeededCondition.setValue(false)
+ eagerCondition.setValue(false)
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(eagerCondition.started).isTrue()
+ assertThat(lazyCondition.started).isTrue()
+ assertThat(startWhenNeededCondition.started).isTrue()
+ }
+
+ @Test
+ fun testAndOperatorWithMixedConditions() = runSelfCancelingTest {
+ val startWhenNeededCondition =
+ FakeCondition(scope = this, initialValue = false, startStrategy = START_WHEN_NEEDED)
+ val eagerCondition =
+ FakeCondition(scope = this, initialValue = false, startStrategy = START_EAGERLY)
+ val lazyCondition =
+ FakeCondition(scope = this, initialValue = false, startStrategy = START_LAZILY)
+
+ val combinedCondition =
+ CombinedCondition(
+ scope = this,
+ conditions =
+ listOf(
+ startWhenNeededCondition,
+ lazyCondition,
+ eagerCondition,
+ ),
+ operand = Evaluator.OP_AND
+ )
+
+ val callback = Condition.Callback {}
+ combinedCondition.addCallback(callback)
+
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(eagerCondition.started).isTrue()
+ assertThat(lazyCondition.started).isFalse()
+ assertThat(startWhenNeededCondition.started).isFalse()
+
+ eagerCondition.setValue(true)
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(eagerCondition.started).isTrue()
+ assertThat(startWhenNeededCondition.started).isTrue()
+ assertThat(lazyCondition.started).isFalse()
+
+ startWhenNeededCondition.setValue(true)
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(eagerCondition.started).isTrue()
+ assertThat(startWhenNeededCondition.started).isFalse()
+ assertThat(lazyCondition.started).isTrue()
+
+ startWhenNeededCondition.setValue(false)
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(eagerCondition.started).isTrue()
+ assertThat(startWhenNeededCondition.started).isFalse()
+ assertThat(lazyCondition.started).isTrue()
+
+ startWhenNeededCondition.setValue(true)
+ lazyCondition.setValue(true)
+ assertThat(combinedCondition.isConditionMet).isTrue()
+ assertThat(eagerCondition.started).isTrue()
+ assertThat(startWhenNeededCondition.started).isTrue()
+ assertThat(lazyCondition.started).isTrue()
+ }
+
+ @Test
+ fun testAndOperatorWithStartWhenNeededConditions() = runSelfCancelingTest {
+ val conditions =
+ 0.rangeTo(2)
+ .map {
+ FakeCondition(
+ scope = this,
+ initialValue = false,
+ startStrategy = START_WHEN_NEEDED
+ )
+ }
+ .toList()
+
+ val combinedCondition =
+ CombinedCondition(scope = this, conditions = conditions, operand = Evaluator.OP_AND)
+
+ val callback = Condition.Callback {}
+ combinedCondition.addCallback(callback)
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ // Only the first condition should be started
+ assertThat(areStarted(conditions)).containsExactly(true, false, false).inOrder()
+
+ conditions[0].setValue(true)
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(areStarted(conditions)).containsExactly(false, true, false).inOrder()
+
+ conditions[1].setValue(true)
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(areStarted(conditions)).containsExactly(false, false, true).inOrder()
+
+ conditions[2].setValue(true)
+ assertThat(combinedCondition.isConditionMet).isTrue()
+ assertThat(areStarted(conditions)).containsExactly(true, true, true).inOrder()
+
+ conditions[0].setValue(false)
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(areStarted(conditions)).containsExactly(true, false, false).inOrder()
+ }
+
+ @Test
+ fun testOrOperatorWithStartWhenNeededConditions() = runSelfCancelingTest {
+ val conditions =
+ 0.rangeTo(2)
+ .map {
+ FakeCondition(
+ scope = this,
+ initialValue = false,
+ startStrategy = START_WHEN_NEEDED
+ )
+ }
+ .toList()
+
+ val combinedCondition =
+ CombinedCondition(scope = this, conditions = conditions, operand = Evaluator.OP_OR)
+
+ val callback = Condition.Callback {}
+ combinedCondition.addCallback(callback)
+ // Default is to monitor all conditions when false
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(areStarted(conditions)).containsExactly(true, true, true).inOrder()
+
+ // Condition 2 is true, so we should only monitor condition 2
+ conditions[1].setValue(true)
+ assertThat(combinedCondition.isConditionMet).isTrue()
+ assertThat(areStarted(conditions)).containsExactly(false, true, false).inOrder()
+
+ // Condition 2 becomes false, so we go back to monitoring all conditions
+ conditions[1].setValue(false)
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(areStarted(conditions)).containsExactly(true, true, true).inOrder()
+
+ // Condition 3 becomes true, so we only monitor condition 3
+ conditions[2].setValue(true)
+ assertThat(combinedCondition.isConditionMet).isTrue()
+ assertThat(areStarted(conditions)).containsExactly(false, false, true).inOrder()
+
+ // Condition 2 becomes true, but we are still only monitoring condition 3
+ conditions[1].setValue(true)
+ assertThat(combinedCondition.isConditionMet).isTrue()
+ assertThat(areStarted(conditions)).containsExactly(false, false, true).inOrder()
+
+ // Condition 3 becomes false, so we should now only be monitoring condition 2
+ conditions[2].setValue(false)
+ assertThat(combinedCondition.isConditionMet).isTrue()
+ assertThat(areStarted(conditions)).containsExactly(false, true, false).inOrder()
+ }
+
+ @Test
+ fun testRemovingCallbackWillStopMonitoringAllConditions() = runSelfCancelingTest {
+ val conditions =
+ 0.rangeTo(2)
+ .map {
+ FakeCondition(
+ scope = this,
+ initialValue = false,
+ startStrategy = START_WHEN_NEEDED
+ )
+ }
+ .toList()
+
+ val combinedCondition =
+ CombinedCondition(scope = this, conditions = conditions, operand = Evaluator.OP_OR)
+
+ val callback = Condition.Callback {}
+ combinedCondition.addCallback(callback)
+ assertThat(areStarted(conditions)).containsExactly(true, true, true)
+
+ combinedCondition.removeCallback(callback)
+ assertThat(areStarted(conditions)).containsExactly(false, false, false)
+ }
+
+ @Test
+ fun testOverridingConditionSkipsOtherConditions() = runSelfCancelingTest {
+ val startWhenNeededCondition =
+ FakeCondition(scope = this, initialValue = false, startStrategy = START_WHEN_NEEDED)
+ val eagerCondition =
+ FakeCondition(scope = this, initialValue = false, startStrategy = START_EAGERLY)
+ val lazyCondition =
+ FakeCondition(scope = this, initialValue = false, startStrategy = START_LAZILY)
+ val overridingCondition1 =
+ FakeCondition(scope = this, initialValue = null, overriding = true)
+ val overridingCondition2 =
+ FakeCondition(scope = this, initialValue = null, overriding = true)
+
+ val combinedCondition =
+ CombinedCondition(
+ scope = this,
+ conditions =
+ listOf(
+ eagerCondition,
+ overridingCondition1,
+ lazyCondition,
+ startWhenNeededCondition,
+ overridingCondition2
+ ),
+ operand = Evaluator.OP_OR
+ )
+
+ val callback = Condition.Callback {}
+ combinedCondition.addCallback(callback)
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(eagerCondition.started).isTrue()
+ assertThat(lazyCondition.started).isTrue()
+ assertThat(startWhenNeededCondition.started).isTrue()
+ assertThat(overridingCondition1.started).isTrue()
+
+ // Overriding condition is true, so we should stop monitoring all other conditions
+ overridingCondition1.setValue(true)
+ assertThat(combinedCondition.isConditionMet).isTrue()
+ assertThat(eagerCondition.started).isFalse()
+ assertThat(lazyCondition.started).isFalse()
+ assertThat(startWhenNeededCondition.started).isFalse()
+ assertThat(overridingCondition1.started).isTrue()
+ assertThat(overridingCondition2.started).isFalse()
+
+ // Overriding condition is false, so we should only monitor other overriding conditions
+ overridingCondition1.setValue(false)
+ eagerCondition.setValue(true)
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(eagerCondition.started).isFalse()
+ assertThat(lazyCondition.started).isFalse()
+ assertThat(startWhenNeededCondition.started).isFalse()
+ assertThat(overridingCondition1.started).isTrue()
+ assertThat(overridingCondition2.started).isTrue()
+
+ // Second overriding condition is true, condition 1 is still true
+ overridingCondition2.setValue(true)
+ assertThat(combinedCondition.isConditionMet).isTrue()
+ assertThat(eagerCondition.started).isFalse()
+ assertThat(lazyCondition.started).isFalse()
+ assertThat(startWhenNeededCondition.started).isFalse()
+ assertThat(overridingCondition1.started).isFalse()
+ assertThat(overridingCondition2.started).isTrue()
+
+ // Overriding condition is cleared, condition 1 is still true
+ overridingCondition1.setValue(null)
+ overridingCondition2.setValue(null)
+ assertThat(combinedCondition.isConditionMet).isTrue()
+ assertThat(eagerCondition.started).isTrue()
+ assertThat(lazyCondition.started).isFalse()
+ assertThat(startWhenNeededCondition.started).isFalse()
+ assertThat(overridingCondition1.started).isTrue()
+ assertThat(overridingCondition2.started).isTrue()
+ }
+
+ @Test
+ fun testAndOperatorCorrectlyHandlesUnknownValues() = runSelfCancelingTest {
+ val conditions =
+ 0.rangeTo(2)
+ .map {
+ FakeCondition(scope = this, initialValue = false, startStrategy = START_EAGERLY)
+ }
+ .toList()
+
+ val combinedCondition =
+ CombinedCondition(scope = this, conditions = conditions, operand = Evaluator.OP_AND)
+
+ val callback = Condition.Callback {}
+ combinedCondition.addCallback(callback)
+
+ conditions[0].setValue(null)
+ conditions[1].setValue(true)
+ conditions[2].setValue(false)
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(combinedCondition.isConditionSet).isTrue()
+
+ // The condition should not be set since the value is unknown
+ conditions[2].setValue(true)
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(combinedCondition.isConditionSet).isFalse()
+
+ conditions[0].setValue(true)
+ assertThat(combinedCondition.isConditionMet).isTrue()
+ assertThat(combinedCondition.isConditionSet).isTrue()
+ }
+
+ @Test
+ fun testOrOperatorCorrectlyHandlesUnknownValues() = runSelfCancelingTest {
+ val conditions =
+ 0.rangeTo(2)
+ .map {
+ FakeCondition(scope = this, initialValue = false, startStrategy = START_EAGERLY)
+ }
+ .toList()
+
+ val combinedCondition =
+ CombinedCondition(scope = this, conditions = conditions, operand = Evaluator.OP_OR)
+
+ val callback = Condition.Callback {}
+ combinedCondition.addCallback(callback)
+
+ conditions[0].setValue(null)
+ conditions[1].setValue(true)
+ conditions[2].setValue(false)
+ assertThat(combinedCondition.isConditionMet).isTrue()
+ assertThat(combinedCondition.isConditionSet).isTrue()
+
+ conditions[1].setValue(false)
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ // The condition should not be set since the value is unknown
+ assertThat(combinedCondition.isConditionSet).isFalse()
+ }
+
+ @Test
+ fun testEmptyConditions() = runSelfCancelingTest {
+ for (operand in intArrayOf(Evaluator.OP_OR, Evaluator.OP_AND)) {
+ val combinedCondition =
+ CombinedCondition(
+ scope = this,
+ conditions = emptyList(),
+ operand = operand,
+ )
+
+ val callback = Condition.Callback {}
+ combinedCondition.addCallback(callback)
+ assertThat(combinedCondition.isConditionMet).isFalse()
+ assertThat(combinedCondition.isConditionSet).isFalse()
+ }
+ }
+
+ private fun areStarted(conditions: List<FakeCondition>): List<Boolean> {
+ return conditions.map { it.started }
+ }
+
+ /**
+ * Executes the given block of execution within the scope of a dedicated [CoroutineScope] which
+ * is then automatically canceled and cleaned-up.
+ */
+ private fun runSelfCancelingTest(
+ block: suspend CoroutineScope.() -> Unit,
+ ) =
+ runBlocking(IMMEDIATE) {
+ val scope = CoroutineScope(coroutineContext + Job())
+ block(scope)
+ scope.cancel()
+ }
+
+ companion object {
+ private val IMMEDIATE = Dispatchers.Main.immediate
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt
index 2b4a7fb4803b..0a8210d6b319 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionExtensionsTest.kt
@@ -32,7 +32,7 @@ class ConditionExtensionsTest : SysuiTestCase() {
fun flowInitiallyTrue() =
testScope.runTest {
val flow = flowOf(true)
- val condition = flow.toCondition(this)
+ val condition = flow.toCondition(scope = this, Condition.START_EAGERLY)
runCurrent()
assertThat(condition.isConditionSet).isFalse()
@@ -47,7 +47,7 @@ class ConditionExtensionsTest : SysuiTestCase() {
fun flowInitiallyFalse() =
testScope.runTest {
val flow = flowOf(false)
- val condition = flow.toCondition(this)
+ val condition = flow.toCondition(scope = this, Condition.START_EAGERLY)
runCurrent()
assertThat(condition.isConditionSet).isFalse()
@@ -62,7 +62,7 @@ class ConditionExtensionsTest : SysuiTestCase() {
fun emptyFlowWithNoInitialValue() =
testScope.runTest {
val flow = emptyFlow<Boolean>()
- val condition = flow.toCondition(this)
+ val condition = flow.toCondition(scope = this, Condition.START_EAGERLY)
condition.start()
runCurrent()
@@ -74,7 +74,12 @@ class ConditionExtensionsTest : SysuiTestCase() {
fun emptyFlowWithInitialValueOfTrue() =
testScope.runTest {
val flow = emptyFlow<Boolean>()
- val condition = flow.toCondition(scope = this, initialValue = true)
+ val condition =
+ flow.toCondition(
+ scope = this,
+ strategy = Condition.START_EAGERLY,
+ initialValue = true
+ )
condition.start()
runCurrent()
@@ -86,7 +91,12 @@ class ConditionExtensionsTest : SysuiTestCase() {
fun emptyFlowWithInitialValueOfFalse() =
testScope.runTest {
val flow = emptyFlow<Boolean>()
- val condition = flow.toCondition(scope = this, initialValue = false)
+ val condition =
+ flow.toCondition(
+ scope = this,
+ strategy = Condition.START_EAGERLY,
+ initialValue = false
+ )
condition.start()
runCurrent()
@@ -98,7 +108,7 @@ class ConditionExtensionsTest : SysuiTestCase() {
fun conditionUpdatesWhenFlowEmitsNewValue() =
testScope.runTest {
val flow = MutableStateFlow(false)
- val condition = flow.toCondition(this)
+ val condition = flow.toCondition(scope = this, strategy = Condition.START_EAGERLY)
condition.start()
runCurrent()
@@ -120,7 +130,7 @@ class ConditionExtensionsTest : SysuiTestCase() {
fun stoppingConditionUnsubscribesFromFlow() =
testScope.runTest {
val flow = MutableSharedFlow<Boolean>()
- val condition = flow.toCondition(this)
+ val condition = flow.toCondition(scope = this, strategy = Condition.START_EAGERLY)
runCurrent()
assertThat(flow.subscriptionCount.value).isEqualTo(0)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
index aa1636d8a030..de5824d1f463 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionMonitorTest.java
@@ -39,12 +39,15 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import java.util.HashSet;
+import kotlinx.coroutines.CoroutineScope;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class ConditionMonitorTest extends SysuiTestCase {
@@ -54,15 +57,18 @@ public class ConditionMonitorTest extends SysuiTestCase {
private HashSet<Condition> mConditions;
private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
+ @Mock
+ private CoroutineScope mScope;
+
private Monitor mConditionMonitor;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- mCondition1 = spy(new FakeCondition());
- mCondition2 = spy(new FakeCondition());
- mCondition3 = spy(new FakeCondition());
+ mCondition1 = spy(new FakeCondition(mScope));
+ mCondition2 = spy(new FakeCondition(mScope));
+ mCondition3 = spy(new FakeCondition(mScope));
mConditions = new HashSet<>(Arrays.asList(mCondition1, mCondition2, mCondition3));
mConditionMonitor = new Monitor(mExecutor);
@@ -396,7 +402,7 @@ public class ConditionMonitorTest extends SysuiTestCase {
@Test
public void unsetCondition_shouldNotAffectValue() {
- final FakeCondition settableCondition = new FakeCondition(null, false);
+ final FakeCondition settableCondition = new FakeCondition(mScope, null, false);
mCondition1.fakeUpdateCondition(true);
mCondition2.fakeUpdateCondition(true);
mCondition3.fakeUpdateCondition(true);
@@ -414,7 +420,7 @@ public class ConditionMonitorTest extends SysuiTestCase {
@Test
public void setUnsetCondition_shouldAffectValue() {
- final FakeCondition settableCondition = new FakeCondition(null, false);
+ final FakeCondition settableCondition = new FakeCondition(mScope, null, false);
mCondition1.fakeUpdateCondition(true);
mCondition2.fakeUpdateCondition(true);
mCondition3.fakeUpdateCondition(true);
@@ -443,7 +449,7 @@ public class ConditionMonitorTest extends SysuiTestCase {
@Test
public void clearingOverridingCondition_shouldBeExcluded() {
- final FakeCondition overridingCondition = new FakeCondition(true, true);
+ final FakeCondition overridingCondition = new FakeCondition(mScope, true, true);
mCondition1.fakeUpdateCondition(false);
mCondition2.fakeUpdateCondition(false);
mCondition3.fakeUpdateCondition(false);
@@ -466,7 +472,7 @@ public class ConditionMonitorTest extends SysuiTestCase {
@Test
public void settingUnsetOverridingCondition_shouldBeIncluded() {
- final FakeCondition overridingCondition = new FakeCondition(null, true);
+ final FakeCondition overridingCondition = new FakeCondition(mScope, null, true);
mCondition1.fakeUpdateCondition(false);
mCondition2.fakeUpdateCondition(false);
mCondition3.fakeUpdateCondition(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java
index 8443221e8b7a..6efade9c9361 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/ConditionTest.java
@@ -34,15 +34,23 @@ import com.android.systemui.SysuiTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import kotlinx.coroutines.CoroutineScope;
@SmallTest
@RunWith(AndroidTestingRunner.class)
public class ConditionTest extends SysuiTestCase {
+ @Mock
+ CoroutineScope mScope;
+
private FakeCondition mCondition;
@Before
public void setup() {
- mCondition = spy(new FakeCondition());
+ MockitoAnnotations.initMocks(this);
+ mCondition = spy(new FakeCondition(mScope));
}
@Test
@@ -152,168 +160,4 @@ public class ConditionTest extends SysuiTestCase {
mCondition.clearCondition();
assertThat(mCondition.isConditionSet()).isFalse();
}
-
- @Test
- public void combineConditionsWithOr_allFalse_reportsNotMet() {
- mCondition.fakeUpdateCondition(false);
-
- final Condition combinedCondition = mCondition.or(
- new FakeCondition(/* initialValue= */ false));
-
- final Condition.Callback callback = mock(
- Condition.Callback.class);
- combinedCondition.addCallback(callback);
-
- assertThat(combinedCondition.isConditionSet()).isTrue();
- assertThat(combinedCondition.isConditionMet()).isFalse();
- verify(callback, times(1)).onConditionChanged(combinedCondition);
- }
-
- @Test
- public void combineConditionsWithOr_allTrue_reportsMet() {
- mCondition.fakeUpdateCondition(true);
-
- final Condition combinedCondition = mCondition.or(
- new FakeCondition(/* initialValue= */ true));
-
- final Condition.Callback callback = mock(
- Condition.Callback.class);
- combinedCondition.addCallback(callback);
-
- assertThat(combinedCondition.isConditionSet()).isTrue();
- assertThat(combinedCondition.isConditionMet()).isTrue();
- verify(callback, times(1)).onConditionChanged(combinedCondition);
- }
-
- @Test
- public void combineConditionsWithOr_singleTrue_reportsMet() {
- mCondition.fakeUpdateCondition(false);
-
- final Condition combinedCondition = mCondition.or(
- new FakeCondition(/* initialValue= */ true));
-
- final Condition.Callback callback = mock(
- Condition.Callback.class);
- combinedCondition.addCallback(callback);
-
- assertThat(combinedCondition.isConditionSet()).isTrue();
- assertThat(combinedCondition.isConditionMet()).isTrue();
- verify(callback, times(1)).onConditionChanged(combinedCondition);
- }
-
- @Test
- public void combineConditionsWithOr_unknownAndTrue_reportsMet() {
- mCondition.fakeUpdateCondition(true);
-
- // Combine with an unset condition.
- final Condition combinedCondition = mCondition.or(
- new FakeCondition(/* initialValue= */ null));
-
- final Condition.Callback callback = mock(
- Condition.Callback.class);
- combinedCondition.addCallback(callback);
-
- assertThat(combinedCondition.isConditionSet()).isTrue();
- assertThat(combinedCondition.isConditionMet()).isTrue();
- verify(callback, times(1)).onConditionChanged(combinedCondition);
- }
-
- @Test
- public void combineConditionsWithOr_unknownAndFalse_reportsNotMet() {
- mCondition.fakeUpdateCondition(false);
-
- // Combine with an unset condition.
- final Condition combinedCondition = mCondition.or(
- new FakeCondition(/* initialValue= */ null));
-
- final Condition.Callback callback = mock(
- Condition.Callback.class);
- combinedCondition.addCallback(callback);
-
- assertThat(combinedCondition.isConditionSet()).isFalse();
- assertThat(combinedCondition.isConditionMet()).isFalse();
- verify(callback, never()).onConditionChanged(combinedCondition);
- }
-
- @Test
- public void combineConditionsWithAnd_allFalse_reportsNotMet() {
- mCondition.fakeUpdateCondition(false);
-
- final Condition combinedCondition = mCondition.and(
- new FakeCondition(/* initialValue= */ false));
-
- final Condition.Callback callback = mock(
- Condition.Callback.class);
- combinedCondition.addCallback(callback);
-
- assertThat(combinedCondition.isConditionSet()).isTrue();
- assertThat(combinedCondition.isConditionMet()).isFalse();
- verify(callback, times(1)).onConditionChanged(combinedCondition);
- }
-
- @Test
- public void combineConditionsWithAnd_allTrue_reportsMet() {
- mCondition.fakeUpdateCondition(true);
-
- final Condition combinedCondition = mCondition.and(
- new FakeCondition(/* initialValue= */ true));
-
- final Condition.Callback callback = mock(
- Condition.Callback.class);
- combinedCondition.addCallback(callback);
-
- assertThat(combinedCondition.isConditionSet()).isTrue();
- assertThat(combinedCondition.isConditionMet()).isTrue();
- verify(callback, times(1)).onConditionChanged(combinedCondition);
- }
-
- @Test
- public void combineConditionsWithAnd_singleTrue_reportsNotMet() {
- mCondition.fakeUpdateCondition(true);
-
- final Condition combinedCondition = mCondition.and(
- new FakeCondition(/* initialValue= */ false));
-
- final Condition.Callback callback = mock(
- Condition.Callback.class);
- combinedCondition.addCallback(callback);
-
- assertThat(combinedCondition.isConditionSet()).isTrue();
- assertThat(combinedCondition.isConditionMet()).isFalse();
- verify(callback, times(1)).onConditionChanged(combinedCondition);
- }
-
- @Test
- public void combineConditionsWithAnd_unknownAndTrue_reportsNotMet() {
- mCondition.fakeUpdateCondition(true);
-
- // Combine with an unset condition.
- final Condition combinedCondition = mCondition.and(
- new FakeCondition(/* initialValue= */ null));
-
- final Condition.Callback callback = mock(
- Condition.Callback.class);
- combinedCondition.addCallback(callback);
-
- assertThat(combinedCondition.isConditionSet()).isFalse();
- assertThat(combinedCondition.isConditionMet()).isFalse();
- verify(callback, never()).onConditionChanged(combinedCondition);
- }
-
- @Test
- public void combineConditionsWithAnd_unknownAndFalse_reportsMet() {
- mCondition.fakeUpdateCondition(false);
-
- // Combine with an unset condition.
- final Condition combinedCondition = mCondition.and(
- new FakeCondition(/* initialValue= */ null));
-
- final Condition.Callback callback = mock(
- Condition.Callback.class);
- combinedCondition.addCallback(callback);
-
- assertThat(combinedCondition.isConditionSet()).isTrue();
- assertThat(combinedCondition.isConditionMet()).isFalse();
- verify(callback, times(1)).onConditionChanged(combinedCondition);
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/FakeCondition.java b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/FakeCondition.java
index 55a6d39d4644..a325cbf25ffe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/condition/FakeCondition.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/condition/FakeCondition.java
@@ -16,21 +16,19 @@
package com.android.systemui.shared.condition;
+import kotlinx.coroutines.CoroutineScope;
+
/**
* Fake implementation of {@link Condition}, and provides a way for tests to update
* condition fulfillment.
*/
public class FakeCondition extends Condition {
- FakeCondition() {
- super();
- }
-
- FakeCondition(Boolean initialValue) {
- super(initialValue, false);
+ FakeCondition(CoroutineScope scope) {
+ super(scope);
}
- FakeCondition(Boolean initialValue, boolean overriding) {
- super(initialValue, overriding);
+ FakeCondition(CoroutineScope scope, Boolean initialValue, boolean overriding) {
+ super(scope, initialValue, overriding);
}
@Override
@@ -41,6 +39,11 @@ public class FakeCondition extends Condition {
public void stop() {
}
+ @Override
+ protected int getStartStrategy() {
+ return START_EAGERLY;
+ }
+
public void fakeUpdateCondition(boolean isConditionMet) {
updateCondition(isConditionMet);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
index 5fc0ffe42f55..8cb530c355bd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LSShadeTransitionLoggerTest.kt
@@ -4,7 +4,7 @@ import android.testing.AndroidTestingRunner
import android.util.DisplayMetrics
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.plugins.log.LogBuffer
+import com.android.systemui.log.LogBuffer
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.phone.LSShadeTransitionLogger
import com.android.systemui.statusbar.phone.LockscreenGestureLogger
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
index 5431eba8441c..c7ea09cb519d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
@@ -70,7 +70,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java
index 9441d49d454a..d5689dcb3173 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java
@@ -48,7 +48,7 @@ import com.android.settingslib.SignalIcon.MobileIconGroup;
import com.android.settingslib.mobile.TelephonyIcons;
import com.android.settingslib.net.DataUsageController;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.util.CarrierConfigTracker;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java
index 4c1f0a8a1066..35b9814cd81d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java
@@ -43,7 +43,7 @@ import com.android.settingslib.mobile.TelephonyIcons;
import com.android.settingslib.net.DataUsageController;
import com.android.systemui.R;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.plugins.log.LogBuffer;
+import com.android.systemui.log.LogBuffer;
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.util.CarrierConfigTracker;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
index bef9fcb5697c..a37c38669bfd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinatorLoggerTest.kt
@@ -19,9 +19,9 @@ package com.android.systemui.statusbar.notification
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
-import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.LogcatEchoTracker
import com.android.systemui.statusbar.StatusBarState
import com.google.common.truth.Truth.assertThat
import org.junit.Before
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt
index c282c1ef0cf6..b80b825d87dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationIconContainerTest.kt
@@ -21,8 +21,6 @@ import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.StatusBarIconView
-import com.android.systemui.statusbar.StatusBarIconView.STATE_DOT
-import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
@@ -51,7 +49,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
fun calculateWidthFor_oneIcon_widthForOneIcon() {
iconContainer.setActualPaddingStart(10f)
iconContainer.setActualPaddingEnd(10f)
- iconContainer.setIconSize(10)
+ iconContainer.setIconSize(10);
assertEquals(/* expected= */ iconContainer.calculateWidthFor(/* numIcons= */ 1f),
/* actual= */ 30f)
@@ -61,7 +59,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
fun calculateWidthFor_fourIcons_widthForFourIcons() {
iconContainer.setActualPaddingStart(10f)
iconContainer.setActualPaddingEnd(10f)
- iconContainer.setIconSize(10)
+ iconContainer.setIconSize(10);
assertEquals(/* expected= */ iconContainer.calculateWidthFor(/* numIcons= */ 4f),
/* actual= */ 60f)
@@ -71,7 +69,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
fun calculateWidthFor_fiveIcons_widthForFourIcons() {
iconContainer.setActualPaddingStart(10f)
iconContainer.setActualPaddingEnd(10f)
- iconContainer.setIconSize(10)
+ iconContainer.setIconSize(10);
assertEquals(/* expected= */ iconContainer.calculateWidthFor(/* numIcons= */ 5f),
/* actual= */ 60f)
}
@@ -80,7 +78,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
fun calculateIconXTranslations_shortShelfOneIcon_atCorrectXWithoutOverflowDot() {
iconContainer.setActualPaddingStart(10f)
iconContainer.setActualPaddingEnd(10f)
- iconContainer.setIconSize(10)
+ iconContainer.setIconSize(10);
val icon = mockStatusBarIcon()
iconContainer.addView(icon)
@@ -101,7 +99,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
fun calculateIconXTranslations_shortShelfFourIcons_atCorrectXWithoutOverflowDot() {
iconContainer.setActualPaddingStart(10f)
iconContainer.setActualPaddingEnd(10f)
- iconContainer.setIconSize(10)
+ iconContainer.setIconSize(10);
val iconOne = mockStatusBarIcon()
val iconTwo = mockStatusBarIcon()
@@ -130,7 +128,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
fun calculateIconXTranslations_shortShelfFiveIcons_atCorrectXWithOverflowDot() {
iconContainer.setActualPaddingStart(10f)
iconContainer.setActualPaddingEnd(10f)
- iconContainer.setIconSize(10)
+ iconContainer.setIconSize(10);
val iconOne = mockStatusBarIcon()
val iconTwo = mockStatusBarIcon()
@@ -156,55 +154,6 @@ class NotificationIconContainerTest : SysuiTestCase() {
}
@Test
- fun calculateIconXTranslations_givenWidthEnoughForThreeIcons_atCorrectXWithoutOverflowDot() {
- iconContainer.setActualPaddingStart(0f)
- iconContainer.setActualPaddingEnd(0f)
- iconContainer.setActualLayoutWidth(30)
- iconContainer.setIconSize(10)
-
- val iconOne = mockStatusBarIcon()
- val iconTwo = mockStatusBarIcon()
- val iconThree = mockStatusBarIcon()
-
- iconContainer.addView(iconOne)
- iconContainer.addView(iconTwo)
- iconContainer.addView(iconThree)
- assertEquals(3, iconContainer.childCount)
-
- iconContainer.calculateIconXTranslations()
- assertEquals(0f, iconContainer.getIconState(iconOne).xTranslation)
- assertEquals(10f, iconContainer.getIconState(iconTwo).xTranslation)
- assertEquals(20f, iconContainer.getIconState(iconThree).xTranslation)
- assertFalse(iconContainer.areIconsOverflowing())
- }
-
- @Test
- fun calculateIconXTranslations_givenWidthNotEnoughForFourIcons_atCorrectXWithOverflowDot() {
- iconContainer.setActualPaddingStart(0f)
- iconContainer.setActualPaddingEnd(0f)
- iconContainer.setActualLayoutWidth(35)
- iconContainer.setIconSize(10)
-
- val iconOne = mockStatusBarIcon()
- val iconTwo = mockStatusBarIcon()
- val iconThree = mockStatusBarIcon()
- val iconFour = mockStatusBarIcon()
-
- iconContainer.addView(iconOne)
- iconContainer.addView(iconTwo)
- iconContainer.addView(iconThree)
- iconContainer.addView(iconFour)
- assertEquals(4, iconContainer.childCount)
-
- iconContainer.calculateIconXTranslations()
- assertEquals(0f, iconContainer.getIconState(iconOne).xTranslation)
- assertEquals(10f, iconContainer.getIconState(iconTwo).xTranslation)
- assertEquals(STATE_DOT, iconContainer.getIconState(iconThree).visibleState)
- assertEquals(STATE_HIDDEN, iconContainer.getIconState(iconFour).visibleState)
- assertTrue(iconContainer.areIconsOverflowing())
- }
-
- @Test
fun shouldForceOverflow_appearingAboveSpeedBump_true() {
val forceOverflow = iconContainer.shouldForceOverflow(
/* i= */ 1,
@@ -212,7 +161,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
/* iconAppearAmount= */ 1f,
/* maxVisibleIcons= */ 5
)
- assertTrue(forceOverflow)
+ assertTrue(forceOverflow);
}
@Test
@@ -223,7 +172,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
/* iconAppearAmount= */ 0f,
/* maxVisibleIcons= */ 5
)
- assertTrue(forceOverflow)
+ assertTrue(forceOverflow);
}
@Test
@@ -234,7 +183,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
/* iconAppearAmount= */ 0f,
/* maxVisibleIcons= */ 5
)
- assertFalse(forceOverflow)
+ assertFalse(forceOverflow);
}
@Test
@@ -261,17 +210,6 @@ class NotificationIconContainerTest : SysuiTestCase() {
}
@Test
- fun isOverflowing_lastChildXGreaterThanDotX_true() {
- val isOverflowing = iconContainer.isOverflowing(
- /* isLastChild= */ true,
- /* translationX= */ 9f,
- /* layoutEnd= */ 10f,
- /* iconSize= */ 2f,
- )
- assertTrue(isOverflowing)
- }
-
- @Test
fun isOverflowing_lastChildXGreaterThanLayoutEnd_true() {
val isOverflowing = iconContainer.isOverflowing(
/* isLastChild= */ true,
@@ -315,7 +253,7 @@ class NotificationIconContainerTest : SysuiTestCase() {
assertTrue(isOverflowing)
}
- private fun mockStatusBarIcon(): StatusBarIconView {
+ private fun mockStatusBarIcon() : StatusBarIconView {
val iconView = mock(StatusBarIconView::class.java)
whenever(iconView.width).thenReturn(10)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt
index ac3b28c72fa2..9bc49ae02436 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt
@@ -20,7 +20,7 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.log.LogBufferFactory
-import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.log.LogcatEchoTracker
import com.android.systemui.statusbar.disableflags.DisableFlagsLogger
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
index 03fafcb85325..21769922c899 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
@@ -54,9 +54,9 @@ import com.android.systemui.R;
import com.android.systemui.SysuiBaseFragmentTest;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.log.LogBuffer;
+import com.android.systemui.log.LogcatEchoTracker;
import com.android.systemui.plugins.DarkIconDispatcher;
-import com.android.systemui.plugins.log.LogBuffer;
-import com.android.systemui.plugins.log.LogcatEchoTracker;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.shade.ShadeViewController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt
index 03cd94fa9d70..c43778a4ae51 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/model/DefaultConnectionModelTest.kt
@@ -18,7 +18,7 @@ package com.android.systemui.statusbar.pipeline.shared.data.model
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.plugins.log.LogMessageImpl
+import com.android.systemui.log.LogMessageImpl
import com.google.common.truth.Truth.assertThat
import org.junit.Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
index d9d8b6345fcb..3b0d5120cca3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SmartReplyViewTest.java
@@ -585,8 +585,6 @@ public class SmartReplyViewTest extends SysuiTestCase {
// devices.
layout.setBaselineAligned(false);
- final boolean isRtl = mView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
-
// Add smart replies
Button previous = null;
SmartReplyView.SmartReplies smartReplies =
@@ -606,11 +604,7 @@ public class SmartReplyViewTest extends SysuiTestCase {
if (previous != null) {
ViewGroup.MarginLayoutParams lp =
(ViewGroup.MarginLayoutParams) previous.getLayoutParams();
- if (isRtl) {
- lp.leftMargin = mSpacing;
- } else {
- lp.rightMargin = mSpacing;
- }
+ lp.setMarginEnd(mSpacing);
}
layout.addView(current);
previous = current;
@@ -634,11 +628,7 @@ public class SmartReplyViewTest extends SysuiTestCase {
if (previous != null) {
ViewGroup.MarginLayoutParams lp =
(ViewGroup.MarginLayoutParams) previous.getLayoutParams();
- if (isRtl) {
- lp.leftMargin = mSpacing;
- } else {
- lp.rightMargin = mSpacing;
- }
+ lp.setMarginEnd(mSpacing);
}
layout.addView(current);
previous = current;
@@ -937,8 +927,8 @@ public class SmartReplyViewTest extends SysuiTestCase {
.collect(Collectors.toList());
Button singleLineButton = buttons.get(0);
Button doubleLineButton = buttons.get(1);
- Drawable singleLineDrawable = singleLineButton.getCompoundDrawables()[0]; // left drawable
- Drawable doubleLineDrawable = doubleLineButton.getCompoundDrawables()[0]; // left drawable
+ Drawable singleLineDrawable = singleLineButton.getCompoundDrawablesRelative()[0]; // start
+ Drawable doubleLineDrawable = doubleLineButton.getCompoundDrawablesRelative()[0]; // start
assertEquals(singleLineDrawable.getBounds().width(),
doubleLineDrawable.getBounds().width());
assertEquals(singleLineDrawable.getBounds().height(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt
index 2e66b205bfd5..451424927b23 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt
@@ -19,9 +19,9 @@ package com.android.systemui.temporarydisplay
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
+import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogBufferFactory
-import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogcatEchoTracker
+import com.android.systemui.log.LogcatEchoTracker
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
import java.io.StringWriter
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 0172eaf03fa7..c8db662a7f49 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -54,6 +54,7 @@ import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.bluetooth.BluetoothDevice;
import android.companion.AssociationInfo;
import android.companion.AssociationRequest;
import android.companion.DeviceNotAssociatedException;
@@ -234,7 +235,7 @@ public class CompanionDeviceManagerService extends SystemService {
loadAssociationsFromDisk();
mAssociationStore.registerListener(mAssociationStoreChangeListener);
- mDevicePresenceMonitor = new CompanionDevicePresenceMonitor(
+ mDevicePresenceMonitor = new CompanionDevicePresenceMonitor(mUserManager,
mAssociationStore, mDevicePresenceCallback);
mAssociationRequestsProcessor = new AssociationRequestsProcessor(
@@ -322,6 +323,23 @@ public class CompanionDeviceManagerService extends SystemService {
MINUTES.toMillis(10));
}
+ @Override
+ public void onUserUnlocked(@NonNull TargetUser user) {
+ // Notify and bind the app after the phone is unlocked.
+ final int userId = user.getUserIdentifier();
+ final Set<BluetoothDevice> blueToothDevices =
+ mDevicePresenceMonitor.getPendingConnectedDevices().get(userId);
+ if (blueToothDevices != null) {
+ for (BluetoothDevice bluetoothDevice : blueToothDevices) {
+ for (AssociationInfo ai:
+ mAssociationStore.getAssociationsByAddress(bluetoothDevice.getAddress())) {
+ Slog.i(TAG, "onUserUnlocked, device id( " + ai.getId() + " ) is connected");
+ mDevicePresenceMonitor.onBluetoothCompanionDeviceConnected(ai.getId());
+ }
+ }
+ }
+ }
+
@NonNull
AssociationInfo getAssociationWithCallerChecks(
@UserIdInt int userId, @NonNull String packageName, @NonNull String macAddress) {
diff --git a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncConnectionService.java b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncConnectionService.java
index 6f99d8677646..e436e9300fb5 100644
--- a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncConnectionService.java
+++ b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncConnectionService.java
@@ -128,9 +128,9 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
private static final class CallMetadataSyncConnectionIdentifier {
private final int mAssociationId;
- private final long mCallId;
+ private final String mCallId;
- CallMetadataSyncConnectionIdentifier(int associationId, long callId) {
+ CallMetadataSyncConnectionIdentifier(int associationId, String callId) {
mAssociationId = associationId;
mCallId = callId;
}
@@ -139,7 +139,7 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
return mAssociationId;
}
- public long getCallId() {
+ public String getCallId() {
return mCallId;
}
@@ -161,9 +161,7 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
private abstract static class CallMetadataSyncConnectionCallback {
- abstract void sendCallAction(int associationId, long callId, int action);
-
- abstract void sendStateChange(int associationId, long callId, int newState);
+ abstract void sendCallAction(int associationId, String callId, int action);
}
private static class CallMetadataSyncConnection extends Connection {
@@ -184,7 +182,7 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
mCallback = callback;
}
- public long getCallId() {
+ public String getCallId() {
return mCall.getId();
}
@@ -205,22 +203,22 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
}
final Bundle extras = new Bundle();
- extras.putLong(CrossDeviceCall.EXTRA_CALL_ID, mCall.getId());
+ extras.putString(CrossDeviceCall.EXTRA_CALL_ID, mCall.getId());
putExtras(extras);
int capabilities = getConnectionCapabilities();
- if (mCall.hasControl(android.companion.Telecom.Call.PUT_ON_HOLD)) {
+ if (mCall.hasControl(android.companion.Telecom.PUT_ON_HOLD)) {
capabilities |= CAPABILITY_HOLD;
} else {
capabilities &= ~CAPABILITY_HOLD;
}
- if (mCall.hasControl(android.companion.Telecom.Call.MUTE)) {
+ if (mCall.hasControl(android.companion.Telecom.MUTE)) {
capabilities |= CAPABILITY_MUTE;
} else {
capabilities &= ~CAPABILITY_MUTE;
}
mAudioManager.setMicrophoneMute(
- mCall.hasControl(android.companion.Telecom.Call.UNMUTE));
+ mCall.hasControl(android.companion.Telecom.UNMUTE));
if (capabilities != getConnectionCapabilities()) {
setConnectionCapabilities(capabilities);
}
@@ -248,8 +246,8 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
int capabilities = getConnectionCapabilities();
final boolean hasHoldControl = mCall.hasControl(
- android.companion.Telecom.Call.PUT_ON_HOLD)
- || mCall.hasControl(android.companion.Telecom.Call.TAKE_OFF_HOLD);
+ android.companion.Telecom.PUT_ON_HOLD)
+ || mCall.hasControl(android.companion.Telecom.TAKE_OFF_HOLD);
if (hasHoldControl != ((getConnectionCapabilities() & CAPABILITY_HOLD)
== CAPABILITY_HOLD)) {
if (hasHoldControl) {
@@ -258,7 +256,7 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
capabilities &= ~CAPABILITY_HOLD;
}
}
- final boolean hasMuteControl = mCall.hasControl(android.companion.Telecom.Call.MUTE);
+ final boolean hasMuteControl = mCall.hasControl(android.companion.Telecom.MUTE);
if (hasMuteControl != ((getConnectionCapabilities() & CAPABILITY_MUTE)
== CAPABILITY_MUTE)) {
if (hasMuteControl) {
@@ -268,7 +266,7 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
}
}
mAudioManager.setMicrophoneMute(
- mCall.hasControl(android.companion.Telecom.Call.UNMUTE));
+ mCall.hasControl(android.companion.Telecom.UNMUTE));
if (capabilities != getConnectionCapabilities()) {
setConnectionCapabilities(capabilities);
}
@@ -276,12 +274,12 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
@Override
public void onAnswer(int videoState) {
- sendCallAction(android.companion.Telecom.Call.ACCEPT);
+ sendCallAction(android.companion.Telecom.ACCEPT);
}
@Override
public void onReject() {
- sendCallAction(android.companion.Telecom.Call.REJECT);
+ sendCallAction(android.companion.Telecom.REJECT);
}
@Override
@@ -296,33 +294,28 @@ public class CallMetadataSyncConnectionService extends ConnectionService {
@Override
public void onSilence() {
- sendCallAction(android.companion.Telecom.Call.SILENCE);
+ sendCallAction(android.companion.Telecom.SILENCE);
}
@Override
public void onHold() {
- sendCallAction(android.companion.Telecom.Call.PUT_ON_HOLD);
+ sendCallAction(android.companion.Telecom.PUT_ON_HOLD);
}
@Override
public void onUnhold() {
- sendCallAction(android.companion.Telecom.Call.TAKE_OFF_HOLD);
+ sendCallAction(android.companion.Telecom.TAKE_OFF_HOLD);
}
@Override
public void onMuteStateChanged(boolean isMuted) {
- sendCallAction(isMuted ? android.companion.Telecom.Call.MUTE
- : android.companion.Telecom.Call.UNMUTE);
+ sendCallAction(isMuted ? android.companion.Telecom.MUTE
+ : android.companion.Telecom.UNMUTE);
}
@Override
public void onDisconnect() {
- sendCallAction(android.companion.Telecom.Call.END);
- }
-
- @Override
- public void onStateChanged(int state) {
- mCallback.sendStateChange(mAssociationId, mCall.getId(), state);
+ sendCallAction(android.companion.Telecom.END);
}
private void sendCallAction(int action) {
diff --git a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncData.java b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncData.java
index 1e4bb9a504ba..5b0c745a7173 100644
--- a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncData.java
+++ b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncData.java
@@ -33,14 +33,14 @@ import java.util.Set;
/** A read-only snapshot of an {@link ContextSyncMessage}. */
class CallMetadataSyncData {
- final Map<Long, CallMetadataSyncData.Call> mCalls = new HashMap<>();
+ final Map<String, CallMetadataSyncData.Call> mCalls = new HashMap<>();
final List<CallMetadataSyncData.Call> mRequests = new ArrayList<>();
public void addCall(CallMetadataSyncData.Call call) {
mCalls.put(call.getId(), call);
}
- public boolean hasCall(long id) {
+ public boolean hasCall(String id) {
return mCalls.containsKey(id);
}
@@ -57,7 +57,7 @@ class CallMetadataSyncData {
}
public static class Call implements Parcelable {
- private long mId;
+ private String mId;
private String mCallerId;
private byte[] mAppIcon;
private String mAppName;
@@ -67,7 +67,7 @@ class CallMetadataSyncData {
public static Call fromParcel(Parcel parcel) {
final Call call = new Call();
- call.setId(parcel.readLong());
+ call.setId(parcel.readString());
call.setCallerId(parcel.readString());
call.setAppIcon(parcel.readBlob());
call.setAppName(parcel.readString());
@@ -82,7 +82,7 @@ class CallMetadataSyncData {
@Override
public void writeToParcel(Parcel parcel, int parcelableFlags) {
- parcel.writeLong(mId);
+ parcel.writeString(mId);
parcel.writeString(mCallerId);
parcel.writeBlob(mAppIcon);
parcel.writeString(mAppName);
@@ -94,7 +94,7 @@ class CallMetadataSyncData {
}
}
- void setId(long id) {
+ void setId(String id) {
mId = id;
}
@@ -122,7 +122,7 @@ class CallMetadataSyncData {
mControls.add(control);
}
- long getId() {
+ String getId() {
return mId;
}
@@ -157,7 +157,7 @@ class CallMetadataSyncData {
@Override
public boolean equals(Object other) {
if (other instanceof CallMetadataSyncData.Call) {
- return ((Call) other).getId() == getId();
+ return mId != null && mId.equals(((Call) other).getId());
}
return false;
}
diff --git a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncInCallService.java b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncInCallService.java
index 443a732eb6f1..0c2373023177 100644
--- a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncInCallService.java
+++ b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncInCallService.java
@@ -41,7 +41,6 @@ import java.util.stream.Collectors;
public class CallMetadataSyncInCallService extends InCallService {
private static final String TAG = "CallMetadataIcs";
- private static final long NOT_VALID = -1L;
private CompanionDeviceManagerServiceInternal mCdmsi;
@@ -71,7 +70,7 @@ public class CallMetadataSyncInCallService extends InCallService {
callMetadataSyncData.getRequests().iterator();
while (iterator.hasNext()) {
final CallMetadataSyncData.Call call = iterator.next();
- if (call.getId() != 0) {
+ if (call.getId() != null) {
// The call is already assigned an id; treat as control invocations.
for (int control : call.getControls()) {
processCallControlAction(call.getId(), control);
@@ -81,41 +80,41 @@ public class CallMetadataSyncInCallService extends InCallService {
}
}
- private void processCallControlAction(long crossDeviceCallId,
+ private void processCallControlAction(String crossDeviceCallId,
int callControlAction) {
final CrossDeviceCall crossDeviceCall = getCallForId(crossDeviceCallId,
mCurrentCalls.values());
switch (callControlAction) {
- case android.companion.Telecom.Call.ACCEPT:
+ case android.companion.Telecom.ACCEPT:
if (crossDeviceCall != null) {
crossDeviceCall.doAccept();
}
break;
- case android.companion.Telecom.Call.REJECT:
+ case android.companion.Telecom.REJECT:
if (crossDeviceCall != null) {
crossDeviceCall.doReject();
}
break;
- case android.companion.Telecom.Call.SILENCE:
+ case android.companion.Telecom.SILENCE:
doSilence();
break;
- case android.companion.Telecom.Call.MUTE:
+ case android.companion.Telecom.MUTE:
doMute();
break;
- case android.companion.Telecom.Call.UNMUTE:
+ case android.companion.Telecom.UNMUTE:
doUnmute();
break;
- case android.companion.Telecom.Call.END:
+ case android.companion.Telecom.END:
if (crossDeviceCall != null) {
crossDeviceCall.doEnd();
}
break;
- case android.companion.Telecom.Call.PUT_ON_HOLD:
+ case android.companion.Telecom.PUT_ON_HOLD:
if (crossDeviceCall != null) {
crossDeviceCall.doPutOnHold();
}
break;
- case android.companion.Telecom.Call.TAKE_OFF_HOLD:
+ case android.companion.Telecom.TAKE_OFF_HOLD:
if (crossDeviceCall != null) {
crossDeviceCall.doTakeOffHold();
}
@@ -171,12 +170,12 @@ public class CallMetadataSyncInCallService extends InCallService {
@Nullable
@VisibleForTesting
- CrossDeviceCall getCallForId(long crossDeviceCallId, Collection<CrossDeviceCall> calls) {
- if (crossDeviceCallId == NOT_VALID) {
+ CrossDeviceCall getCallForId(String crossDeviceCallId, Collection<CrossDeviceCall> calls) {
+ if (crossDeviceCallId == null) {
return null;
}
for (CrossDeviceCall crossDeviceCall : calls) {
- if (crossDeviceCall.getId() == crossDeviceCallId) {
+ if (crossDeviceCallId.equals(crossDeviceCall.getId())) {
return crossDeviceCall;
}
}
diff --git a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceCall.java b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceCall.java
index ac981d45561b..168068ec6497 100644
--- a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceCall.java
+++ b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceCall.java
@@ -23,7 +23,6 @@ import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.os.Bundle;
import android.telecom.Call;
import android.telecom.CallAudioState;
import android.telecom.VideoProfile;
@@ -34,7 +33,7 @@ import com.android.internal.annotations.VisibleForTesting;
import java.io.ByteArrayOutputStream;
import java.util.HashSet;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicLong;
+import java.util.UUID;
/** Data holder for a telecom call and additional metadata. */
public class CrossDeviceCall {
@@ -45,9 +44,7 @@ public class CrossDeviceCall {
"com.android.companion.datatransfer.contextsync.extra.CALL_ID";
private static final int APP_ICON_BITMAP_DIMENSION = 256;
- private static final AtomicLong sNextId = new AtomicLong(1);
-
- private final long mId;
+ private final String mId;
private Call mCall;
@VisibleForTesting boolean mIsEnterprise;
@VisibleForTesting boolean mIsOtt;
@@ -64,14 +61,14 @@ public class CrossDeviceCall {
CallAudioState callAudioState) {
this(packageManager, call.getDetails(), callAudioState);
mCall = call;
- final Bundle extras = new Bundle();
- extras.putLong(EXTRA_CALL_ID, mId);
- call.putExtras(extras);
+ call.putExtra(EXTRA_CALL_ID, mId);
}
CrossDeviceCall(PackageManager packageManager, Call.Details callDetails,
CallAudioState callAudioState) {
- mId = sNextId.getAndIncrement();
+ final String predefinedId = callDetails.getIntentExtras() != null
+ ? callDetails.getIntentExtras().getString(EXTRA_CALL_ID) : null;
+ mId = predefinedId != null ? predefinedId : UUID.randomUUID().toString();
mCallingAppPackageName =
callDetails.getAccountHandle().getComponentName().getPackageName();
mIsOtt = (callDetails.getCallCapabilities() & Call.Details.PROPERTY_SELF_MANAGED)
@@ -145,7 +142,7 @@ public class CrossDeviceCall {
if (mStatus == android.companion.Telecom.Call.RINGING) {
mStatus = android.companion.Telecom.Call.RINGING_SILENCED;
}
- mControls.remove(android.companion.Telecom.Call.SILENCE);
+ mControls.remove(android.companion.Telecom.SILENCE);
}
@VisibleForTesting
@@ -156,26 +153,26 @@ public class CrossDeviceCall {
mControls.clear();
if (mStatus == android.companion.Telecom.Call.RINGING
|| mStatus == android.companion.Telecom.Call.RINGING_SILENCED) {
- mControls.add(android.companion.Telecom.Call.ACCEPT);
- mControls.add(android.companion.Telecom.Call.REJECT);
+ mControls.add(android.companion.Telecom.ACCEPT);
+ mControls.add(android.companion.Telecom.REJECT);
if (mStatus == android.companion.Telecom.Call.RINGING) {
- mControls.add(android.companion.Telecom.Call.SILENCE);
+ mControls.add(android.companion.Telecom.SILENCE);
}
}
if (mStatus == android.companion.Telecom.Call.ONGOING
|| mStatus == android.companion.Telecom.Call.ON_HOLD) {
- mControls.add(android.companion.Telecom.Call.END);
+ mControls.add(android.companion.Telecom.END);
if (callDetails.can(Call.Details.CAPABILITY_HOLD)) {
mControls.add(
mStatus == android.companion.Telecom.Call.ON_HOLD
- ? android.companion.Telecom.Call.TAKE_OFF_HOLD
- : android.companion.Telecom.Call.PUT_ON_HOLD);
+ ? android.companion.Telecom.TAKE_OFF_HOLD
+ : android.companion.Telecom.PUT_ON_HOLD);
}
}
if (mStatus == android.companion.Telecom.Call.ONGOING && callDetails.can(
Call.Details.CAPABILITY_MUTE)) {
- mControls.add(mIsMuted ? android.companion.Telecom.Call.UNMUTE
- : android.companion.Telecom.Call.MUTE);
+ mControls.add(mIsMuted ? android.companion.Telecom.UNMUTE
+ : android.companion.Telecom.MUTE);
}
}
@@ -212,7 +209,7 @@ public class CrossDeviceCall {
}
}
- public long getId() {
+ public String getId() {
return mId;
}
diff --git a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceSyncController.java b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceSyncController.java
index adc5faf24f2c..e5ab963b6cbb 100644
--- a/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceSyncController.java
+++ b/services/companion/java/com/android/server/companion/datatransfer/contextsync/CrossDeviceSyncController.java
@@ -270,7 +270,7 @@ public class CrossDeviceSyncController {
while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
switch (pis.getFieldNumber()) {
case (int) Telecom.Call.ID:
- call.setId(pis.readLong(Telecom.Call.ID));
+ call.setId(pis.readString(Telecom.Call.ID));
break;
case (int) Telecom.Call.ORIGIN:
final long originToken = pis.start(Telecom.Call.ORIGIN);
@@ -336,7 +336,7 @@ public class CrossDeviceSyncController {
}
/** Create a call control message. */
- public static byte[] createCallControlMessage(long callId, int control) {
+ public static byte[] createCallControlMessage(String callId, int control) {
final ProtoOutputStream pos = new ProtoOutputStream();
pos.write(ContextSyncMessage.VERSION, CURRENT_VERSION);
final long telecomToken = pos.start(ContextSyncMessage.TELECOM);
diff --git a/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java b/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java
index f6b99b551ecb..a5410e448c7b 100644
--- a/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java
+++ b/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java
@@ -27,17 +27,24 @@ import android.companion.AssociationInfo;
import android.net.MacAddress;
import android.os.Handler;
import android.os.HandlerExecutor;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.server.companion.AssociationStore;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
@SuppressLint("LongLogTag")
-class BluetoothCompanionDeviceConnectionListener
+public class BluetoothCompanionDeviceConnectionListener
extends BluetoothAdapter.BluetoothConnectionCallback
implements AssociationStore.OnChangeListener {
private static final String TAG = "CDM_BluetoothCompanionDeviceConnectionListener";
@@ -48,15 +55,25 @@ class BluetoothCompanionDeviceConnectionListener
void onBluetoothCompanionDeviceDisconnected(int associationId);
}
+ private final UserManager mUserManager;
private final @NonNull AssociationStore mAssociationStore;
private final @NonNull Callback mCallback;
/** A set of ALL connected BT device (not only companion.) */
private final @NonNull Map<MacAddress, BluetoothDevice> mAllConnectedDevices = new HashMap<>();
- BluetoothCompanionDeviceConnectionListener(@NonNull AssociationStore associationStore,
- @NonNull Callback callback) {
+ /**
+ * A structure hold the connected BT devices that are pending to be reported to the companion
+ * app when the user unlocks the local device per userId.
+ */
+ @GuardedBy("mPendingConnectedDevices")
+ @NonNull
+ final SparseArray<Set<BluetoothDevice>> mPendingConnectedDevices = new SparseArray<>();
+
+ BluetoothCompanionDeviceConnectionListener(UserManager userManager,
+ @NonNull AssociationStore associationStore, @NonNull Callback callback) {
mAssociationStore = associationStore;
mCallback = callback;
+ mUserManager = userManager;
}
public void init(@NonNull BluetoothAdapter btAdapter) {
@@ -76,12 +93,26 @@ class BluetoothCompanionDeviceConnectionListener
if (DEBUG) Log.i(TAG, "onDevice_Connected() " + btDeviceToString(device));
final MacAddress macAddress = MacAddress.fromString(device.getAddress());
+ final int userId = UserHandle.myUserId();
+
if (mAllConnectedDevices.put(macAddress, device) != null) {
if (DEBUG) Log.w(TAG, "Device " + btDeviceToString(device) + " is already connected.");
return;
}
+ // Try to bind and notify the app after the phone is unlocked.
+ if (!mUserManager.isUserUnlockingOrUnlocked(UserHandle.myUserId())) {
+ Slog.i(TAG, "Current user is not in unlocking or unlocked stage yet. Notify "
+ + "the application when the phone is unlocked");
+ synchronized (mPendingConnectedDevices) {
+ Set<BluetoothDevice> bluetoothDevices = mPendingConnectedDevices.get(
+ userId, new HashSet<>());
+ bluetoothDevices.add(device);
+ mPendingConnectedDevices.put(userId, bluetoothDevices);
+ }
- onDeviceConnectivityChanged(device, true);
+ } else {
+ onDeviceConnectivityChanged(device, true);
+ }
}
/**
@@ -98,6 +129,8 @@ class BluetoothCompanionDeviceConnectionListener
}
final MacAddress macAddress = MacAddress.fromString(device.getAddress());
+ final int userId = UserHandle.myUserId();
+
if (mAllConnectedDevices.remove(macAddress) == null) {
if (DEBUG) {
Log.w(TAG, "The device wasn't tracked as connected " + btDeviceToString(device));
@@ -105,6 +138,19 @@ class BluetoothCompanionDeviceConnectionListener
return;
}
+ // Do not need to report the connectivity since the user is not unlock the phone so
+ // that cdm is not bind with the app yet.
+ if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
+ synchronized (mPendingConnectedDevices) {
+ Set<BluetoothDevice> bluetoothDevices = mPendingConnectedDevices.get(userId);
+ if (bluetoothDevices != null) {
+ bluetoothDevices.remove(device);
+ }
+ }
+
+ return;
+ }
+
onDeviceConnectivityChanged(device, false);
}
diff --git a/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java b/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java
index 4010be922b2c..f6e9415a2a7e 100644
--- a/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java
+++ b/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java
@@ -23,13 +23,16 @@ import android.annotation.NonNull;
import android.annotation.SuppressLint;
import android.annotation.TestApi;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
import android.companion.AssociationInfo;
import android.content.Context;
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.UserManager;
import android.util.Log;
+import android.util.SparseArray;
import com.android.server.companion.AssociationStore;
@@ -86,13 +89,12 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange
private final SimulatedDevicePresenceSchedulerHelper mSchedulerHelper =
new SimulatedDevicePresenceSchedulerHelper();
- public CompanionDevicePresenceMonitor(@NonNull AssociationStore associationStore,
- @NonNull Callback callback) {
+ public CompanionDevicePresenceMonitor(UserManager userManager,
+ @NonNull AssociationStore associationStore, @NonNull Callback callback) {
mAssociationStore = associationStore;
mCallback = callback;
-
- mBtConnectionListener = new BluetoothCompanionDeviceConnectionListener(associationStore,
- /* BluetoothCompanionDeviceConnectionListener.Callback */ this);
+ mBtConnectionListener = new BluetoothCompanionDeviceConnectionListener(userManager,
+ associationStore, /* BluetoothCompanionDeviceConnectionListener.Callback */ this);
mBleScanner = new BleCompanionDeviceScanner(associationStore,
/* BleCompanionDeviceScanner.Callback */ this);
}
@@ -298,6 +300,15 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange
// what's needed.
}
+ /**
+ * Return a set of devices that pending to report connectivity
+ */
+ public SparseArray<Set<BluetoothDevice>> getPendingConnectedDevices() {
+ synchronized (mBtConnectionListener.mPendingConnectedDevices) {
+ return mBtConnectionListener.mPendingConnectedDevices;
+ }
+ }
+
private static void enforceCallerShellOrRoot() {
final int callingUid = Binder.getCallingUid();
if (callingUid == SHELL_UID || callingUid == ROOT_UID) return;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 1a5d4253b5ba..a992765c0411 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -16060,6 +16060,8 @@ public class ActivityManagerService extends IActivityManager.Stub
final int procState = uidRec != null
? uidRec.getSetProcState() : PROCESS_STATE_NONEXISTENT;
+ final int procAdj = uidRec != null
+ ? uidRec.getMinProcAdj() : ProcessList.INVALID_ADJ;
final long procStateSeq = uidRec != null ? uidRec.curProcStateSeq : 0;
final int capability = uidRec != null ? uidRec.getSetCapability() : 0;
final boolean ephemeral = uidRec != null ? uidRec.isEphemeral() : isEphemeralLocked(uid);
@@ -16075,7 +16077,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
final int enqueuedChange = mUidObserverController.enqueueUidChange(
uidRec == null ? null : uidRec.pendingChange,
- uid, change, procState, procStateSeq, capability, ephemeral);
+ uid, change, procState, procAdj, procStateSeq, capability, ephemeral);
if (uidRec != null) {
uidRec.setLastReportedChange(enqueuedChange);
}
diff --git a/services/core/java/com/android/server/am/BroadcastQueueImpl.java b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
index 5a4d315767ca..4a69f90d9fc0 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueImpl.java
@@ -67,7 +67,6 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
-import android.os.UserManager;
import android.text.TextUtils;
import android.util.EventLog;
import android.util.IndentingPrintWriter;
@@ -78,6 +77,7 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.os.TimeoutRecord;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.LocalServices;
+import com.android.server.pm.UserJourneyLogger;
import com.android.server.pm.UserManagerInternal;
import dalvik.annotation.optimization.NeverCompile;
@@ -1518,7 +1518,7 @@ public class BroadcastQueueImpl extends BroadcastQueue {
final UserInfo userInfo =
(umInternal != null) ? umInternal.getUserInfo(r.userId) : null;
if (userInfo != null) {
- userType = UserManager.getUserTypeForStatsd(userInfo.userType);
+ userType = UserJourneyLogger.getUserTypeForStatsd(userInfo.userType);
}
Slog.i(TAG_BROADCAST,
"BOOT_COMPLETED_BROADCAST_COMPLETION_LATENCY_REPORTED action:"
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index 3bc5de91b2bd..3e82d557c01a 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -1015,6 +1015,12 @@ public final class CachedAppOptimizer {
private static native String getFreezerCheckPath();
/**
+ * Check if task_profiles.json includes valid freezer profiles and actions
+ * @return false if there are invalid profiles or actions
+ */
+ private static native boolean isFreezerProfileValid();
+
+ /**
* Determines whether the freezer is supported by this system
*/
public static boolean isFreezerSupported() {
@@ -1031,16 +1037,19 @@ public final class CachedAppOptimizer {
// Also check freezer binder ioctl
Slog.d(TAG_AM, "Checking binder freezer ioctl");
getBinderFreezeInfo(Process.myPid());
- supported = true;
+
+ // Check if task_profiles.json contains invalid profiles
+ Slog.d(TAG_AM, "Checking freezer profiles");
+ supported = isFreezerProfileValid();
} else {
- Slog.e(TAG_AM, "unexpected value in cgroup.freeze");
+ Slog.e(TAG_AM, "Unexpected value in cgroup.freeze");
}
} catch (java.io.FileNotFoundException e) {
- Slog.w(TAG_AM, "cgroup.freeze not present");
+ Slog.w(TAG_AM, "File cgroup.freeze not present");
} catch (RuntimeException e) {
- Slog.w(TAG_AM, "unable to read freezer info");
+ Slog.w(TAG_AM, "Unable to read freezer info");
} catch (Exception e) {
- Slog.w(TAG_AM, "unable to read cgroup.freeze: " + e.toString());
+ Slog.w(TAG_AM, "Unable to read cgroup.freeze: " + e.toString());
}
if (fr != null) {
diff --git a/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java b/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java
index 490a0232bfaa..79089074dd1c 100644
--- a/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java
+++ b/services/core/java/com/android/server/am/ForegroundServiceTypeLoggerModule.java
@@ -34,7 +34,7 @@ import android.app.ForegroundServiceDelegationOptions;
import android.content.ComponentName;
import android.content.pm.ServiceInfo;
import android.util.ArrayMap;
-import android.util.Log;
+import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -192,13 +192,20 @@ public class ForegroundServiceTypeLoggerModule {
final ArrayList<Integer> apiTypes = convertFgsTypeToApiTypes(record.foregroundServiceType);
final UidState uidState = mUids.get(uid);
if (uidState == null) {
- Log.e(TAG, "FGS stop call being logged with no start call for UID " + uid);
+ Slog.wtfStack(TAG, "FGS stop call being logged with no start call for UID for UID "
+ + uid
+ + " in package " + record.packageName);
return;
}
final ArrayList<Integer> apisFound = new ArrayList<>();
final ArrayList<Long> timestampsFound = new ArrayList<>();
for (int i = 0, size = apiTypes.size(); i < size; i++) {
- int apiType = apiTypes.get(i);
+ final int apiType = apiTypes.get(i);
+ if (!uidState.mOpenWithFgsCount.contains(apiType)) {
+ Slog.wtfStack(TAG, "Logger should be tracking FGS types correctly for UID " + uid
+ + " in package " + record.packageName);
+ continue;
+ }
// retrieve the eligible closed call
// we only want to log if this is the only
// open in flight call. If there are other calls,
@@ -215,7 +222,8 @@ public class ForegroundServiceTypeLoggerModule {
final ArrayMap<ComponentName, ServiceRecord> runningFgsOfType =
uidState.mRunningFgs.get(apiType);
if (runningFgsOfType == null) {
- Log.w(TAG, "Could not find appropriate running FGS for FGS stop");
+ Slog.w(TAG, "Could not find appropriate running FGS for FGS stop for UID " + uid
+ + " in package " + record.packageName);
continue;
}
@@ -322,7 +330,7 @@ public class ForegroundServiceTypeLoggerModule {
// it's not related to any FGS
UidState uidState = mUids.get(uid);
if (uidState == null) {
- Log.w(TAG, "API event end called before start!");
+ Slog.w(TAG, "API event end called before start!");
return -1;
}
if (uidState.mOpenWithFgsCount.contains(apiType)) {
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 438a08c44ef4..0417b8cfa2e2 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -644,6 +644,11 @@ class ProcessRecord implements WindowProcessListener {
}
}
+ @GuardedBy({"mService", "mProcLock"})
+ int getSetAdj() {
+ return mState.getSetAdj();
+ }
+
@GuardedBy(anyOf = {"mService", "mProcLock"})
IApplicationThread getThread() {
return mThread;
diff --git a/services/core/java/com/android/server/am/UidObserverController.java b/services/core/java/com/android/server/am/UidObserverController.java
index 51cb9878c0b3..790cc7b87f80 100644
--- a/services/core/java/com/android/server/am/UidObserverController.java
+++ b/services/core/java/com/android/server/am/UidObserverController.java
@@ -96,7 +96,7 @@ public class UidObserverController {
}
int enqueueUidChange(@Nullable ChangeRecord currentRecord, int uid, int change, int procState,
- long procStateSeq, int capability, boolean ephemeral) {
+ int procAdj, long procStateSeq, int capability, boolean ephemeral) {
synchronized (mLock) {
if (mPendingUidChanges.size() == 0) {
if (DEBUG_UID_OBSERVERS) {
@@ -117,6 +117,7 @@ public class UidObserverController {
changeRecord.uid = uid;
changeRecord.change = change;
changeRecord.procState = procState;
+ changeRecord.procAdj = procAdj;
changeRecord.procStateSeq = procStateSeq;
changeRecord.capability = capability;
changeRecord.ephemeral = ephemeral;
@@ -344,7 +345,7 @@ public class UidObserverController {
}
if ((reg.mWhich & ActivityManager.UID_OBSERVER_PROC_OOM_ADJ) != 0
&& (change & UidRecord.CHANGE_PROCADJ) != 0) {
- observer.onUidProcAdjChanged(item.uid);
+ observer.onUidProcAdjChanged(item.uid, item.procAdj);
}
}
final int duration = (int) (SystemClock.uptimeMillis() - start);
@@ -426,6 +427,7 @@ public class UidObserverController {
public int uid;
public int change;
public int procState;
+ public int procAdj;
public int capability;
public boolean ephemeral;
public long procStateSeq;
@@ -435,6 +437,7 @@ public class UidObserverController {
changeRecord.uid = uid;
changeRecord.change = change;
changeRecord.procState = procState;
+ changeRecord.procAdj = procAdj;
changeRecord.capability = capability;
changeRecord.ephemeral = ephemeral;
changeRecord.procStateSeq = procStateSeq;
diff --git a/services/core/java/com/android/server/am/UidRecord.java b/services/core/java/com/android/server/am/UidRecord.java
index e39ac2b08479..993088ef106e 100644
--- a/services/core/java/com/android/server/am/UidRecord.java
+++ b/services/core/java/com/android/server/am/UidRecord.java
@@ -51,6 +51,12 @@ public final class UidRecord {
private boolean mProcAdjChanged;
@CompositeRWLock({"mService", "mProcLock"})
+ private int mCurAdj;
+
+ @CompositeRWLock({"mService", "mProcLock"})
+ private int mSetAdj;
+
+ @CompositeRWLock({"mService", "mProcLock"})
private int mCurCapability;
@CompositeRWLock({"mService", "mProcLock"})
@@ -201,12 +207,24 @@ public final class UidRecord {
mProcAdjChanged = false;
}
- @GuardedBy({"mService", "mProcLock"})
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
boolean getProcAdjChanged() {
return mProcAdjChanged;
}
@GuardedBy(anyOf = {"mService", "mProcLock"})
+ int getMinProcAdj() {
+ int minAdj = ProcessList.UNKNOWN_ADJ;
+ for (int i = mProcRecords.size() - 1; i >= 0; i--) {
+ int adj = mProcRecords.valueAt(i).getSetAdj();
+ if (adj < minAdj) {
+ minAdj = adj;
+ }
+ }
+ return minAdj;
+ }
+
+ @GuardedBy(anyOf = {"mService", "mProcLock"})
int getCurCapability() {
return mCurCapability;
}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index b2fdee7a6f89..06af2ce9d655 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -46,13 +46,24 @@ import static com.android.server.am.UserState.STATE_BOOTING;
import static com.android.server.am.UserState.STATE_RUNNING_LOCKED;
import static com.android.server.am.UserState.STATE_RUNNING_UNLOCKED;
import static com.android.server.am.UserState.STATE_RUNNING_UNLOCKING;
+import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_ABORTED;
+import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_INVALID_SESSION_ID;
+import static com.android.server.pm.UserJourneyLogger.EVENT_STATE_BEGIN;
+import static com.android.server.pm.UserJourneyLogger.EVENT_STATE_FINISH;
+import static com.android.server.pm.UserJourneyLogger.EVENT_STATE_NONE;
+import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_START;
+import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_STOP;
+import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_SWITCH_FG;
+import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_SWITCH_UI;
+import static com.android.server.pm.UserJourneyLogger.USER_LIFECYCLE_EVENT_UNLOCKED_USER;
+import static com.android.server.pm.UserJourneyLogger.USER_LIFECYCLE_EVENT_UNLOCKING_USER;
+import static com.android.server.pm.UserJourneyLogger.USER_LIFECYCLE_EVENT_USER_RUNNING_LOCKED;
import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE;
import static com.android.server.pm.UserManagerInternal.USER_START_MODE_BACKGROUND_VISIBLE;
import static com.android.server.pm.UserManagerInternal.USER_START_MODE_FOREGROUND;
import static com.android.server.pm.UserManagerInternal.userAssignmentResultToString;
import static com.android.server.pm.UserManagerInternal.userStartModeToString;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -123,6 +134,8 @@ import com.android.server.LocalServices;
import com.android.server.SystemService.UserCompletedEventType;
import com.android.server.SystemServiceManager;
import com.android.server.am.UserState.KeyEvictedCallback;
+import com.android.server.pm.UserJourneyLogger;
+import com.android.server.pm.UserJourneyLogger.UserJourneySession;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerInternal.UserLifecycleListener;
import com.android.server.pm.UserManagerInternal.UserStartMode;
@@ -138,7 +151,6 @@ import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
-import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
@@ -221,75 +233,6 @@ class UserController implements Handler.Callback {
// TODO(b/197344658): Increase to 10s or 15s once we have a switch-UX-is-done invocation too.
private static final int USER_COMPLETED_EVENT_DELAY_MS = 5 * 1000;
- // Used for statsd logging with UserLifecycleJourneyReported + UserLifecycleEventOccurred atoms
- private static final long INVALID_SESSION_ID = 0;
-
- // The various user journeys, defined in the UserLifecycleJourneyReported atom for statsd
- private static final int USER_JOURNEY_UNKNOWN =
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__UNKNOWN;
- private static final int USER_JOURNEY_USER_SWITCH_FG =
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_SWITCH_FG;
- private static final int USER_JOURNEY_USER_SWITCH_UI =
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_SWITCH_UI;
- private static final int USER_JOURNEY_USER_START =
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_START;
- private static final int USER_JOURNEY_USER_CREATE =
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_CREATE;
- private static final int USER_JOURNEY_USER_STOP =
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_STOP;
- @IntDef(prefix = { "USER_JOURNEY" }, value = {
- USER_JOURNEY_UNKNOWN,
- USER_JOURNEY_USER_SWITCH_FG,
- USER_JOURNEY_USER_SWITCH_UI,
- USER_JOURNEY_USER_START,
- USER_JOURNEY_USER_CREATE,
- USER_JOURNEY_USER_STOP
- })
- @interface UserJourney {}
-
- // The various user lifecycle events, defined in the UserLifecycleEventOccurred atom for statsd
- private static final int USER_LIFECYCLE_EVENT_UNKNOWN =
- FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__UNKNOWN;
- private static final int USER_LIFECYCLE_EVENT_SWITCH_USER =
- FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__SWITCH_USER;
- private static final int USER_LIFECYCLE_EVENT_START_USER =
- FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__START_USER;
- private static final int USER_LIFECYCLE_EVENT_CREATE_USER =
- FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__CREATE_USER;
- private static final int USER_LIFECYCLE_EVENT_USER_RUNNING_LOCKED =
- FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__USER_RUNNING_LOCKED;
- private static final int USER_LIFECYCLE_EVENT_UNLOCKING_USER =
- FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__UNLOCKING_USER;
- private static final int USER_LIFECYCLE_EVENT_UNLOCKED_USER =
- FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__UNLOCKED_USER;
- private static final int USER_LIFECYCLE_EVENT_STOP_USER =
- FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__STOP_USER;
- @IntDef(prefix = { "USER_LIFECYCLE_EVENT" }, value = {
- USER_LIFECYCLE_EVENT_UNKNOWN,
- USER_LIFECYCLE_EVENT_SWITCH_USER,
- USER_LIFECYCLE_EVENT_START_USER,
- USER_LIFECYCLE_EVENT_CREATE_USER,
- USER_LIFECYCLE_EVENT_USER_RUNNING_LOCKED,
- USER_LIFECYCLE_EVENT_UNLOCKING_USER,
- USER_LIFECYCLE_EVENT_UNLOCKED_USER,
- USER_LIFECYCLE_EVENT_STOP_USER
- })
- @interface UserLifecycleEvent {}
-
- // User lifecyle event state, defined in the UserLifecycleEventOccurred atom for statsd
- private static final int USER_LIFECYCLE_EVENT_STATE_BEGIN =
- FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__BEGIN;
- private static final int USER_LIFECYCLE_EVENT_STATE_FINISH =
- FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__FINISH;
- private static final int USER_LIFECYCLE_EVENT_STATE_NONE =
- FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__NONE;
- @IntDef(prefix = { "USER_LIFECYCLE_EVENT_STATE" }, value = {
- USER_LIFECYCLE_EVENT_STATE_BEGIN,
- USER_LIFECYCLE_EVENT_STATE_FINISH,
- USER_LIFECYCLE_EVENT_STATE_NONE,
- })
- @interface UserLifecycleEventState {}
-
/**
* Maximum number of users we allow to be running at a time, including system user.
*
@@ -420,13 +363,6 @@ class UserController implements Handler.Callback {
private final ArrayList<Integer> mLastActiveUsers = new ArrayList<>();
/**
- * {@link UserIdInt} to {@link UserJourneySession} mapping used for statsd logging for the
- * UserLifecycleJourneyReported and UserLifecycleEventOccurred atoms.
- */
- @GuardedBy("mUserIdToUserJourneyMap")
- private final SparseArray<UserJourneySession> mUserIdToUserJourneyMap = new SparseArray<>();
-
- /**
* Map of userId to {@link UserCompletedEventType} event flags, indicating which as-yet-
* unreported user-starting events have transpired for the given user.
*/
@@ -621,8 +557,9 @@ class UserController implements Handler.Callback {
// but we might immediately step into RUNNING below if the user
// storage is already unlocked.
if (uss.setState(STATE_BOOTING, STATE_RUNNING_LOCKED)) {
- logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_USER_RUNNING_LOCKED,
- USER_LIFECYCLE_EVENT_STATE_NONE);
+ mInjector.getUserJourneyLogger()
+ .logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_USER_RUNNING_LOCKED,
+ EVENT_STATE_NONE);
mInjector.getUserManagerInternal().setUserState(userId, uss.state);
// Do not report secondary users, runtime restarts or first boot/upgrade
if (userId == UserHandle.USER_SYSTEM
@@ -694,8 +631,9 @@ class UserController implements Handler.Callback {
private boolean finishUserUnlocking(final UserState uss) {
final int userId = uss.mHandle.getIdentifier();
EventLog.writeEvent(EventLogTags.UC_FINISH_USER_UNLOCKING, userId);
- logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_UNLOCKING_USER,
- USER_LIFECYCLE_EVENT_STATE_BEGIN);
+ mInjector.getUserJourneyLogger()
+ .logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_UNLOCKING_USER,
+ EVENT_STATE_BEGIN);
// If the user key hasn't been unlocked yet, we cannot proceed.
if (!StorageManager.isUserKeyUnlocked(userId)) return false;
synchronized (mLock) {
@@ -1073,9 +1011,7 @@ class UserController implements Handler.Callback {
return;
}
- logUserJourneyInfo(null, getUserInfo(userId), USER_JOURNEY_USER_STOP);
- logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_STOP_USER,
- USER_LIFECYCLE_EVENT_STATE_BEGIN);
+ logUserJourneyBegin(userId, USER_JOURNEY_USER_STOP);
if (stopUserCallback != null) {
uss.mStopCallbacks.add(stopUserCallback);
@@ -1138,9 +1074,16 @@ class UserController implements Handler.Callback {
synchronized (mLock) {
if (uss.state != UserState.STATE_STOPPING) {
// Whoops, we are being started back up. Abort, abort!
- logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_STOP_USER,
- USER_LIFECYCLE_EVENT_STATE_NONE);
- clearSessionId(userId);
+ UserJourneySession session = mInjector.getUserJourneyLogger()
+ .logUserJourneyFinishWithError(-1, getUserInfo(userId),
+ USER_JOURNEY_USER_STOP, ERROR_CODE_ABORTED);
+ if (session != null) {
+ mHandler.removeMessages(CLEAR_USER_JOURNEY_SESSION_MSG, session);
+ } else {
+ mInjector.getUserJourneyLogger()
+ .logUserJourneyFinishWithError(-1, getUserInfo(userId),
+ USER_JOURNEY_USER_STOP, ERROR_CODE_INVALID_SESSION_ID);
+ }
return;
}
uss.setState(UserState.STATE_SHUTDOWN);
@@ -1247,9 +1190,11 @@ class UserController implements Handler.Callback {
mInjector.getUserManager().removeUserEvenWhenDisallowed(userId);
}
- logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_STOP_USER,
- USER_LIFECYCLE_EVENT_STATE_FINISH);
- clearSessionId(userId);
+ UserJourneySession session = mInjector.getUserJourneyLogger()
+ .logUserJourneyFinish(-1, userInfo, USER_JOURNEY_USER_STOP);
+ if (session != null) {
+ mHandler.removeMessages(CLEAR_USER_JOURNEY_SESSION_MSG, session);
+ }
if (lockUser) {
dispatchUserLocking(userIdToLock, keyEvictedCallbacks);
@@ -1259,9 +1204,11 @@ class UserController implements Handler.Callback {
// which was paused while the SHUTDOWN flow of the user was in progress.
resumePendingUserStarts(userId);
} else {
- logUserLifecycleEvent(userId, USER_LIFECYCLE_EVENT_STOP_USER,
- USER_LIFECYCLE_EVENT_STATE_NONE);
- clearSessionId(userId);
+ UserJourneySession session = mInjector.getUserJourneyLogger()
+ .finishAndClearIncompleteUserJourney(userId, USER_JOURNEY_USER_STOP);
+ if (session != null) {
+ mHandler.removeMessages(CLEAR_USER_JOURNEY_SESSION_MSG, session);
+ }
}
}
@@ -3135,10 +3082,7 @@ class UserController implements Handler.Callback {
public boolean handleMessage(Message msg) {
switch (msg.what) {
case START_USER_SWITCH_FG_MSG:
- logUserJourneyInfo(getUserInfo(getCurrentUserId()), getUserInfo(msg.arg1),
- USER_JOURNEY_USER_SWITCH_FG);
- logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_SWITCH_USER,
- USER_LIFECYCLE_EVENT_STATE_BEGIN);
+ logUserJourneyBegin(msg.arg1, USER_JOURNEY_USER_SWITCH_FG);
startUserInForeground(msg.arg1);
break;
case REPORT_USER_SWITCH_MSG:
@@ -3160,18 +3104,15 @@ class UserController implements Handler.Callback {
mInjector.batteryStatsServiceNoteEvent(
BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
Integer.toString(msg.arg1), msg.arg1);
- logUserJourneyInfo(null, getUserInfo(msg.arg1), USER_JOURNEY_USER_START);
- logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_START_USER,
- USER_LIFECYCLE_EVENT_STATE_BEGIN);
+ logUserJourneyBegin(msg.arg1, USER_JOURNEY_USER_START);
mInjector.onUserStarting(/* userId= */ msg.arg1);
scheduleOnUserCompletedEvent(msg.arg1,
UserCompletedEventType.EVENT_TYPE_USER_STARTING,
USER_COMPLETED_EVENT_DELAY_MS);
- logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_START_USER,
- USER_LIFECYCLE_EVENT_STATE_FINISH);
- clearSessionId(msg.arg1, USER_JOURNEY_USER_START);
+ mInjector.getUserJourneyLogger().logUserJourneyFinish(-1 , getUserInfo(msg.arg1),
+ USER_JOURNEY_USER_START);
break;
case USER_UNLOCK_MSG:
final int userId = msg.arg1;
@@ -3180,10 +3121,11 @@ class UserController implements Handler.Callback {
FgThread.getHandler().post(() -> {
mInjector.loadUserRecents(userId);
});
- logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_UNLOCKING_USER,
- USER_LIFECYCLE_EVENT_STATE_FINISH);
- logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_UNLOCKED_USER,
- USER_LIFECYCLE_EVENT_STATE_BEGIN);
+
+ mInjector.getUserJourneyLogger().logUserLifecycleEvent(msg.arg1,
+ USER_LIFECYCLE_EVENT_UNLOCKING_USER, EVENT_STATE_FINISH);
+ mInjector.getUserJourneyLogger().logUserLifecycleEvent(msg.arg1,
+ USER_LIFECYCLE_EVENT_UNLOCKED_USER, EVENT_STATE_BEGIN);
final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
t.traceBegin("finishUserUnlocked-" + userId);
@@ -3199,9 +3141,9 @@ class UserController implements Handler.Callback {
// (No need to acquire lock to read mCurrentUserId since it is volatile.)
// TODO: Find something to wait for in the case of a profile.
mCurrentUserId == msg.arg1 ? USER_COMPLETED_EVENT_DELAY_MS : 1000);
- logUserLifecycleEvent(msg.arg1, USER_LIFECYCLE_EVENT_UNLOCKED_USER,
- USER_LIFECYCLE_EVENT_STATE_FINISH);
- clearSessionId(msg.arg1);
+ mInjector.getUserJourneyLogger().logUserLifecycleEvent(msg.arg1,
+ USER_LIFECYCLE_EVENT_UNLOCKED_USER, EVENT_STATE_FINISH);
+ // Unlocking user is not a journey no need to clear sessionId
break;
case USER_CURRENT_MSG:
mInjector.batteryStatsServiceNoteEvent(
@@ -3224,22 +3166,24 @@ class UserController implements Handler.Callback {
break;
case REPORT_USER_SWITCH_COMPLETE_MSG:
dispatchUserSwitchComplete(msg.arg1, msg.arg2);
- logUserLifecycleEvent(msg.arg2, USER_LIFECYCLE_EVENT_SWITCH_USER,
- USER_LIFECYCLE_EVENT_STATE_FINISH);
+ UserJourneySession session = mInjector.getUserJourneyLogger()
+ .logUserSwitchJourneyFinish(msg.arg1, getUserInfo(msg.arg2));
+ if (session != null) {
+ mHandler.removeMessages(CLEAR_USER_JOURNEY_SESSION_MSG, session);
+ }
break;
case REPORT_LOCKED_BOOT_COMPLETE_MSG:
dispatchLockedBootComplete(msg.arg1);
break;
case START_USER_SWITCH_UI_MSG:
final Pair<UserInfo, UserInfo> fromToUserPair = (Pair<UserInfo, UserInfo>) msg.obj;
- logUserJourneyInfo(fromToUserPair.first, fromToUserPair.second,
- USER_JOURNEY_USER_SWITCH_UI);
- logUserLifecycleEvent(fromToUserPair.second.id, USER_LIFECYCLE_EVENT_SWITCH_USER,
- USER_LIFECYCLE_EVENT_STATE_BEGIN);
+ logUserJourneyBegin(fromToUserPair.second.id, USER_JOURNEY_USER_SWITCH_UI);
showUserSwitchDialog(fromToUserPair);
break;
case CLEAR_USER_JOURNEY_SESSION_MSG:
- logAndClearSessionId(msg.arg1);
+ mInjector.getUserJourneyLogger()
+ .finishAndClearIncompleteUserJourney(msg.arg1, msg.arg2);
+ mHandler.removeMessages(CLEAR_USER_JOURNEY_SESSION_MSG, msg.obj);
break;
case COMPLETE_USER_SWITCH_MSG:
completeUserSwitch(msg.arg1, msg.arg2);
@@ -3317,123 +3261,29 @@ class UserController implements Handler.Callback {
* statsd helper method for logging the start of a user journey via a UserLifecycleEventOccurred
* atom given the originating and targeting users for the journey.
*/
- private void logUserJourneyInfo(UserInfo origin, UserInfo target, @UserJourney int journey) {
- final long newSessionId = ThreadLocalRandom.current().nextLong(1, Long.MAX_VALUE);
- synchronized (mUserIdToUserJourneyMap) {
- UserJourneySession userJourneySession = mUserIdToUserJourneyMap.get(target.id);
- if (userJourneySession != null) {
- // TODO(b/157007231): Move this logic to a separate class/file.
- if ((userJourneySession.mJourney == USER_JOURNEY_USER_SWITCH_UI
- || userJourneySession.mJourney == USER_JOURNEY_USER_SWITCH_FG)
- && (journey == USER_JOURNEY_USER_START
- || journey == USER_JOURNEY_USER_STOP)) {
- /*
- * There is already a user switch journey, and a user start or stop journey for
- * the same target user received. New journey is most likely a part of user
- * switch journey so no need to create a new journey.
- */
- if (DEBUG_MU) {
- Slogf.d(TAG, journey + " not logged as it is expected to be part of "
- + userJourneySession.mJourney);
- }
- return;
- }
- /*
- * Possible reasons for this condition to be true:
- * - A user switch journey is received while another user switch journey is in
- * process for the same user.
- * - A user switch journey is received while user start journey is in process for
- * the same user.
- * - A user start journey is received while another user start journey is in process
- * for the same user.
- * In all cases potentially an incomplete, timed-out session or multiple
- * simultaneous requests. It is not possible to keep track of multiple sessions for
- * the same user, so previous session is abandoned.
- */
- FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED,
- userJourneySession.mSessionId, target.id, USER_LIFECYCLE_EVENT_UNKNOWN,
- USER_LIFECYCLE_EVENT_STATE_NONE);
- }
-
+ private void logUserJourneyBegin(int targetId,
+ @UserJourneyLogger.UserJourney int journey) {
+ UserJourneySession oldSession = mInjector.getUserJourneyLogger()
+ .finishAndClearIncompleteUserJourney(targetId, journey);
+ if (oldSession != null) {
if (DEBUG_MU) {
Slogf.d(TAG,
- "Starting a new journey: " + journey + " with session id: " + newSessionId);
+ "Starting a new journey: " + journey + " with session id: "
+ + oldSession);
}
-
- userJourneySession = new UserJourneySession(newSessionId, journey);
- mUserIdToUserJourneyMap.put(target.id, userJourneySession);
/*
- * User lifecyle journey would be complete when {@code #clearSessionId} is called after
- * the last expected lifecycle event for the journey. It may be possible that the last
- * event is not called, e.g., user not unlocked after user switching. In such cases user
- * journey is cleared after {@link USER_JOURNEY_TIMEOUT}.
+ * User lifecycle journey would be complete when {@code #clearSessionId} is called
+ * after the last expected lifecycle event for the journey. It may be possible that
+ * the last event is not called, e.g., user not unlocked after user switching. In such
+ * cases user journey is cleared after {@link USER_JOURNEY_TIMEOUT}.
*/
- mHandler.removeMessages(CLEAR_USER_JOURNEY_SESSION_MSG);
- mHandler.sendMessageDelayed(mHandler.obtainMessage(CLEAR_USER_JOURNEY_SESSION_MSG,
- target.id, /* arg2= */ 0), USER_JOURNEY_TIMEOUT_MS);
- }
-
- FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED, newSessionId,
- journey, origin != null ? origin.id : -1,
- target.id, UserManager.getUserTypeForStatsd(target.userType), target.flags);
- }
-
- /**
- * statsd helper method for logging the given event for the UserLifecycleEventOccurred statsd
- * atom.
- */
- private void logUserLifecycleEvent(@UserIdInt int userId, @UserLifecycleEvent int event,
- @UserLifecycleEventState int eventState) {
- final long sessionId;
- synchronized (mUserIdToUserJourneyMap) {
- final UserJourneySession userJourneySession = mUserIdToUserJourneyMap.get(userId);
- if (userJourneySession == null || userJourneySession.mSessionId == INVALID_SESSION_ID) {
- Slogf.w(TAG, "UserLifecycleEvent " + event
- + " received without an active userJourneySession.");
- return;
- }
- sessionId = userJourneySession.mSessionId;
- }
-
- FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED, sessionId, userId,
- event, eventState);
- }
-
- /**
- * Clears the {@link UserJourneySession} for a given {@link UserIdInt} and {@link UserJourney}.
- */
- private void clearSessionId(@UserIdInt int userId, @UserJourney int journey) {
- synchronized (mUserIdToUserJourneyMap) {
- final UserJourneySession userJourneySession = mUserIdToUserJourneyMap.get(userId);
- if (userJourneySession != null && userJourneySession.mJourney == journey) {
- clearSessionId(userId);
- }
+ mHandler.removeMessages(CLEAR_USER_JOURNEY_SESSION_MSG, oldSession);
}
- }
+ UserJourneySession newSession = mInjector.getUserJourneyLogger()
+ .logUserJourneyBegin(targetId, journey);
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(CLEAR_USER_JOURNEY_SESSION_MSG,
+ targetId, /* arg2= */ journey, newSession), USER_JOURNEY_TIMEOUT_MS);
- /**
- * Clears the {@link UserJourneySession} for a given {@link UserIdInt}.
- */
- private void clearSessionId(@UserIdInt int userId) {
- synchronized (mUserIdToUserJourneyMap) {
- mHandler.removeMessages(CLEAR_USER_JOURNEY_SESSION_MSG);
- mUserIdToUserJourneyMap.delete(userId);
- }
- }
-
- /**
- * Log a final event of the {@link UserJourneySession} and clear it.
- */
- private void logAndClearSessionId(@UserIdInt int userId) {
- synchronized (mUserIdToUserJourneyMap) {
- final UserJourneySession userJourneySession = mUserIdToUserJourneyMap.get(userId);
- if (userJourneySession != null) {
- FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED,
- userJourneySession.mSessionId, userId, USER_LIFECYCLE_EVENT_UNKNOWN,
- USER_LIFECYCLE_EVENT_STATE_NONE);
- }
- clearSessionId(userId);
- }
}
private BroadcastOptions getTemporaryAppAllowlistBroadcastOptions(
@@ -3471,23 +3321,6 @@ class UserController implements Handler.Callback {
return mLastUserUnlockingUptime;
}
- /**
- * Helper class to store user journey and session id.
- *
- * <p> User journey tracks a chain of user lifecycle events occurring during different user
- * activities such as user start, user switch, and user creation.
- */
- // TODO(b/157007231): Move this class and user journey tracking logic to a separate file.
- private static class UserJourneySession {
- final long mSessionId;
- @UserJourney final int mJourney;
-
- UserJourneySession(long sessionId, @UserJourney int journey) {
- mJourney = journey;
- mSessionId = sessionId;
- }
- }
-
private static class UserProgressListener extends IProgressListener.Stub {
private volatile long mUnlockStarted;
@Override
@@ -3562,6 +3395,10 @@ class UserController implements Handler.Callback {
return new Handler(mService.mUiHandler.getLooper(), callback);
}
+ protected UserJourneyLogger getUserJourneyLogger() {
+ return getUserManager().getUserJourneyLogger();
+ }
+
protected Context getContext() {
return mService.mContext;
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index ada92f5545c2..bc4e8df2a4ad 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -88,14 +88,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
private final @NonNull AudioSystemAdapter mAudioSystem;
/** ID for Communication strategy retrieved form audio policy manager */
- private int mCommunicationStrategyId = -1;
+ /*package*/ int mCommunicationStrategyId = -1;
/** ID for Accessibility strategy retrieved form audio policy manager */
private int mAccessibilityStrategyId = -1;
/** Active communication device reported by audio policy manager */
- private AudioDeviceInfo mActiveCommunicationDevice;
+ /*package*/ AudioDeviceInfo mActiveCommunicationDevice;
/** Last preferred device set for communication strategy */
private AudioDeviceAttributes mPreferredCommunicationDevice;
@@ -755,6 +755,19 @@ import java.util.concurrent.atomic.AtomicBoolean;
mIsLeOutput = false;
}
+ BtDeviceInfo(@NonNull BtDeviceInfo src, int state) {
+ mDevice = src.mDevice;
+ mState = state;
+ mProfile = src.mProfile;
+ mSupprNoisy = src.mSupprNoisy;
+ mVolume = src.mVolume;
+ mIsLeOutput = src.mIsLeOutput;
+ mEventSource = src.mEventSource;
+ mAudioSystemDevice = src.mAudioSystemDevice;
+ mMusicDevice = src.mMusicDevice;
+ mCodec = src.mCodec;
+ }
+
// redefine equality op so we can match messages intended for this device
@Override
public boolean equals(Object o) {
@@ -821,7 +834,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* @param info struct with the (dis)connection information
*/
/*package*/ void queueOnBluetoothActiveDeviceChanged(@NonNull BtDeviceChangedData data) {
- if (data.mInfo.getProfile() == BluetoothProfile.A2DP && data.mPreviousDevice != null
+ if (data.mPreviousDevice != null
&& data.mPreviousDevice.equals(data.mNewDevice)) {
final String name = TextUtils.emptyIfNull(data.mNewDevice.getName());
new MediaMetrics.Item(MediaMetrics.Name.AUDIO_DEVICE + MediaMetrics.SEPARATOR
@@ -830,7 +843,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
.set(MediaMetrics.Property.STATUS, data.mInfo.getProfile())
.record();
synchronized (mDeviceStateLock) {
- postBluetoothA2dpDeviceConfigChange(data.mNewDevice);
+ postBluetoothDeviceConfigChange(createBtDeviceInfo(data, data.mNewDevice,
+ BluetoothProfile.STATE_CONNECTED));
}
} else {
synchronized (mDeviceStateLock) {
@@ -1064,8 +1078,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
new AudioModeInfo(mode, pid, uid));
}
- /*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) {
- sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, device);
+ /*package*/ void postBluetoothDeviceConfigChange(@NonNull BtDeviceInfo info) {
+ sendLMsgNoDelay(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE, SENDMSG_QUEUE, info);
}
/*package*/ void startBluetoothScoForClient(IBinder cb, int pid, int scoAudioMode,
@@ -1092,21 +1106,21 @@ import java.util.concurrent.atomic.AtomicBoolean;
/*package*/ int setPreferredDevicesForStrategySync(int strategy,
@NonNull List<AudioDeviceAttributes> devices) {
- return mDeviceInventory.setPreferredDevicesForStrategySync(strategy, devices);
+ return mDeviceInventory.setPreferredDevicesForStrategyAndSave(strategy, devices);
}
/*package*/ int removePreferredDevicesForStrategySync(int strategy) {
- return mDeviceInventory.removePreferredDevicesForStrategySync(strategy);
+ return mDeviceInventory.removePreferredDevicesForStrategyAndSave(strategy);
}
/*package*/ int setDeviceAsNonDefaultForStrategySync(int strategy,
@NonNull AudioDeviceAttributes device) {
- return mDeviceInventory.setDeviceAsNonDefaultForStrategySync(strategy, device);
+ return mDeviceInventory.setDeviceAsNonDefaultForStrategyAndSave(strategy, device);
}
/*package*/ int removeDeviceAsNonDefaultForStrategySync(int strategy,
@NonNull AudioDeviceAttributes device) {
- return mDeviceInventory.removeDeviceAsNonDefaultForStrategySync(strategy, device);
+ return mDeviceInventory.removeDeviceAsNonDefaultForStrategyAndSave(strategy, device);
}
/*package*/ void registerStrategyPreferredDevicesDispatcher(
@@ -1131,11 +1145,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
/*package*/ int setPreferredDevicesForCapturePresetSync(int capturePreset,
@NonNull List<AudioDeviceAttributes> devices) {
- return mDeviceInventory.setPreferredDevicesForCapturePresetSync(capturePreset, devices);
+ return mDeviceInventory.setPreferredDevicesForCapturePresetAndSave(capturePreset, devices);
}
/*package*/ int clearPreferredDevicesForCapturePresetSync(int capturePreset) {
- return mDeviceInventory.clearPreferredDevicesForCapturePresetSync(capturePreset);
+ return mDeviceInventory.clearPreferredDevicesForCapturePresetAndSave(capturePreset);
}
/*package*/ void registerCapturePresetDevicesRoleDispatcher(
@@ -1322,6 +1336,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
sendIMsgNoDelay(MSG_I_SCO_AUDIO_STATE_CHANGED, SENDMSG_QUEUE, state);
}
+ /*package*/ void postNotifyPreferredAudioProfileApplied(BluetoothDevice btDevice) {
+ sendLMsgNoDelay(MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED, SENDMSG_QUEUE, btDevice);
+ }
+
/*package*/ static final class CommunicationDeviceInfo {
final @NonNull IBinder mCb; // Identifies the requesting client for death handler
final int mPid; // Requester process ID
@@ -1397,9 +1415,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
}
}
- /*package*/ boolean handleDeviceConnection(AudioDeviceAttributes attributes, boolean connect) {
+ /*package*/ boolean handleDeviceConnection(AudioDeviceAttributes attributes,
+ boolean connect, @Nullable BluetoothDevice btDevice) {
synchronized (mDeviceStateLock) {
- return mDeviceInventory.handleDeviceConnection(attributes, connect, false /*for test*/);
+ return mDeviceInventory.handleDeviceConnection(
+ attributes, connect, false /*for test*/, btDevice);
}
}
@@ -1640,13 +1660,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
(String) msg.obj, msg.arg1);
}
break;
- case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
- final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
+ case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE:
synchronized (mDeviceStateLock) {
- final int a2dpCodec = mBtHelper.getA2dpCodec(btDevice);
- mDeviceInventory.onBluetoothA2dpDeviceConfigChange(
- new BtHelper.BluetoothA2dpDeviceInfo(btDevice, -1, a2dpCodec),
- BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
+ mDeviceInventory.onBluetoothDeviceConfigChange(
+ (BtDeviceInfo) msg.obj, BtHelper.EVENT_DEVICE_CONFIG_CHANGE);
}
break;
case MSG_BROADCAST_AUDIO_BECOMING_NOISY:
@@ -1810,6 +1827,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
case MSG_IL_SET_LEAUDIO_SUSPENDED: {
setLeAudioSuspended((msg.arg1 == 1), false /*internal*/, (String) msg.obj);
} break;
+ case MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED: {
+ final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
+ BtHelper.onNotifyPreferredAudioProfileApplied(btDevice);
+ } break;
default:
Log.wtf(TAG, "Invalid message " + msg.what);
}
@@ -1845,7 +1866,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
private static final int MSG_IL_BTA2DP_TIMEOUT = 10;
// process change of A2DP device configuration, obj is BluetoothDevice
- private static final int MSG_L_A2DP_DEVICE_CONFIG_CHANGE = 11;
+ private static final int MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE = 11;
private static final int MSG_BROADCAST_AUDIO_BECOMING_NOISY = 12;
private static final int MSG_REPORT_NEW_ROUTES = 13;
@@ -1887,13 +1908,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
private static final int MSG_IL_SET_A2DP_SUSPENDED = 50;
private static final int MSG_IL_SET_LEAUDIO_SUSPENDED = 51;
+ private static final int MSG_L_NOTIFY_PREFERRED_AUDIOPROFILE_APPLIED = 52;
+
private static boolean isMessageHandledUnderWakelock(int msgId) {
switch(msgId) {
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
case MSG_L_SET_BT_ACTIVE_DEVICE:
case MSG_IL_BTA2DP_TIMEOUT:
case MSG_IL_BTLEAUDIO_TIMEOUT:
- case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
+ case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE:
case MSG_TOGGLE_HDMI:
case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
@@ -1985,7 +2008,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
case MSG_IL_BTA2DP_TIMEOUT:
case MSG_IL_BTLEAUDIO_TIMEOUT:
- case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
+ case MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE:
if (sLastDeviceConnectMsgTime >= time) {
// add a little delay to make sure messages are ordered as expected
time = sLastDeviceConnectMsgTime + 30;
@@ -2005,7 +2028,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
static {
MESSAGES_MUTE_MUSIC = new HashSet<>();
MESSAGES_MUTE_MUSIC.add(MSG_L_SET_BT_ACTIVE_DEVICE);
- MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONFIG_CHANGE);
+ MESSAGES_MUTE_MUSIC.add(MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE);
MESSAGES_MUTE_MUSIC.add(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT);
MESSAGES_MUTE_MUSIC.add(MSG_IIL_SET_FORCE_BT_A2DP_USE);
}
@@ -2026,7 +2049,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
// Do not mute on bluetooth event if music is playing on a wired headset.
if ((message == MSG_L_SET_BT_ACTIVE_DEVICE
|| message == MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT
- || message == MSG_L_A2DP_DEVICE_CONFIG_CHANGE)
+ || message == MSG_L_BLUETOOTH_DEVICE_CONFIG_CHANGE)
&& AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)
&& hasIntersection(mDeviceInventory.DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG_SET,
mAudioService.getDeviceSetForStream(AudioSystem.STREAM_MUSIC))) {
@@ -2165,18 +2188,19 @@ import java.util.concurrent.atomic.AtomicBoolean;
if (preferredCommunicationDevice == null) {
AudioDeviceAttributes defaultDevice = getDefaultCommunicationDevice();
if (defaultDevice != null) {
- setPreferredDevicesForStrategySync(
+ mDeviceInventory.setPreferredDevicesForStrategy(
mCommunicationStrategyId, Arrays.asList(defaultDevice));
- setPreferredDevicesForStrategySync(
+ mDeviceInventory.setPreferredDevicesForStrategy(
mAccessibilityStrategyId, Arrays.asList(defaultDevice));
} else {
- removePreferredDevicesForStrategySync(mCommunicationStrategyId);
- removePreferredDevicesForStrategySync(mAccessibilityStrategyId);
+ mDeviceInventory.removePreferredDevicesForStrategy(mCommunicationStrategyId);
+ mDeviceInventory.removePreferredDevicesForStrategy(mAccessibilityStrategyId);
}
+ mDeviceInventory.applyConnectedDevicesRoles();
} else {
- setPreferredDevicesForStrategySync(
+ mDeviceInventory.setPreferredDevicesForStrategy(
mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice));
- setPreferredDevicesForStrategySync(
+ mDeviceInventory.setPreferredDevicesForStrategy(
mAccessibilityStrategyId, Arrays.asList(preferredCommunicationDevice));
}
onUpdatePhoneStrategyDevice(preferredCommunicationDevice);
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 228bc87cc20b..773df3720ed3 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -34,26 +34,36 @@ import android.media.ICapturePresetDevicesRoleDispatcher;
import android.media.IStrategyNonDefaultDevicesDispatcher;
import android.media.IStrategyPreferredDevicesDispatcher;
import android.media.MediaMetrics;
+import android.media.MediaRecorder.AudioSource;
+import android.media.audiopolicy.AudioProductStrategy;
import android.media.permission.ClearCallingIdentityContext;
import android.media.permission.SafeCloseable;
import android.os.Binder;
+import android.os.Bundle;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
+import android.util.Pair;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.utils.EventLogger;
+import com.google.android.collect.Sets;
+
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
@@ -175,18 +185,26 @@ public class AudioDeviceInventory {
final RemoteCallbackList<ICapturePresetDevicesRoleDispatcher> mDevRoleCapturePresetDispatchers =
new RemoteCallbackList<ICapturePresetDevicesRoleDispatcher>();
+ final List<AudioProductStrategy> mStrategies;
+
/*package*/ AudioDeviceInventory(@NonNull AudioDeviceBroker broker) {
- mDeviceBroker = broker;
- mAudioSystem = AudioSystemAdapter.getDefaultAdapter();
+ this(broker, AudioSystemAdapter.getDefaultAdapter());
}
//-----------------------------------------------------------
/** for mocking only, allows to inject AudioSystem adapter */
/*package*/ AudioDeviceInventory(@NonNull AudioSystemAdapter audioSystem) {
- mDeviceBroker = null;
- mAudioSystem = audioSystem;
+ this(null, audioSystem);
}
+ private AudioDeviceInventory(@Nullable AudioDeviceBroker broker,
+ @Nullable AudioSystemAdapter audioSystem) {
+ mDeviceBroker = broker;
+ mAudioSystem = audioSystem;
+ mStrategies = AudioProductStrategy.getAudioProductStrategies();
+ mBluetoothDualModeEnabled = SystemProperties.getBoolean(
+ "persist.bluetooth.enable_dual_mode_audio", false);
+ }
/*package*/ void setDeviceBroker(@NonNull AudioDeviceBroker broker) {
mDeviceBroker = broker;
}
@@ -203,8 +221,13 @@ public class AudioDeviceInventory {
int mDeviceCodecFormat;
final UUID mSensorUuid;
+ /** Disabled operating modes for this device. Use a negative logic so that by default
+ * an empty list means all modes are allowed.
+ * See BluetoothAdapter.AUDIO_MODE_DUPLEX and BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY */
+ @NonNull ArraySet<String> mDisabledModes = new ArraySet(0);
+
DeviceInfo(int deviceType, String deviceName, String deviceAddress,
- int deviceCodecFormat, UUID sensorUuid) {
+ int deviceCodecFormat, @Nullable UUID sensorUuid) {
mDeviceType = deviceType;
mDeviceName = deviceName == null ? "" : deviceName;
mDeviceAddress = deviceAddress == null ? "" : deviceAddress;
@@ -212,11 +235,31 @@ public class AudioDeviceInventory {
mSensorUuid = sensorUuid;
}
+ void setModeDisabled(String mode) {
+ mDisabledModes.add(mode);
+ }
+ void setModeEnabled(String mode) {
+ mDisabledModes.remove(mode);
+ }
+ boolean isModeEnabled(String mode) {
+ return !mDisabledModes.contains(mode);
+ }
+ boolean isOutputOnlyModeEnabled() {
+ return isModeEnabled(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY);
+ }
+ boolean isDuplexModeEnabled() {
+ return isModeEnabled(BluetoothAdapter.AUDIO_MODE_DUPLEX);
+ }
+
DeviceInfo(int deviceType, String deviceName, String deviceAddress,
int deviceCodecFormat) {
this(deviceType, deviceName, deviceAddress, deviceCodecFormat, null);
}
+ DeviceInfo(int deviceType, String deviceName, String deviceAddress) {
+ this(deviceType, deviceName, deviceAddress, AudioSystem.AUDIO_FORMAT_DEFAULT);
+ }
+
@Override
public String toString() {
return "[DeviceInfo: type:0x" + Integer.toHexString(mDeviceType)
@@ -224,7 +267,8 @@ public class AudioDeviceInventory {
+ ") name:" + mDeviceName
+ " addr:" + mDeviceAddress
+ " codec: " + Integer.toHexString(mDeviceCodecFormat)
- + " sensorUuid: " + Objects.toString(mSensorUuid) + "]";
+ + " sensorUuid: " + Objects.toString(mSensorUuid)
+ + " disabled modes: " + mDisabledModes + "]";
}
@NonNull String getKey() {
@@ -276,9 +320,18 @@ public class AudioDeviceInventory {
pw.println(" " + prefix + " type:0x" + Integer.toHexString(keyType)
+ " (" + AudioSystem.getDeviceName(keyType)
+ ") addr:" + valueAddress); });
+ pw.println("\n" + prefix + "Preferred devices for capture preset:");
mPreferredDevicesForCapturePreset.forEach((capturePreset, devices) -> {
pw.println(" " + prefix + "capturePreset:" + capturePreset
+ " devices:" + devices); });
+ pw.println("\n" + prefix + "Applied devices roles for strategies:");
+ mAppliedStrategyRoles.forEach((key, devices) -> {
+ pw.println(" " + prefix + "strategy: " + key.first
+ + " role:" + key.second + " devices:" + devices); });
+ pw.println("\n" + prefix + "Applied devices roles for presets:");
+ mAppliedPresetRoles.forEach((key, devices) -> {
+ pw.println(" " + prefix + "preset: " + key.first
+ + " role:" + key.second + " devices:" + devices); });
}
//------------------------------------------------------------
@@ -299,15 +352,16 @@ public class AudioDeviceInventory {
AudioSystem.DEVICE_STATE_AVAILABLE,
di.mDeviceCodecFormat);
}
+ mAppliedStrategyRoles.clear();
+ applyConnectedDevicesRoles_l();
}
synchronized (mPreferredDevices) {
mPreferredDevices.forEach((strategy, devices) -> {
- mAudioSystem.setDevicesRoleForStrategy(
- strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices); });
+ setPreferredDevicesForStrategy(strategy, devices); });
}
synchronized (mNonDefaultDevices) {
mNonDefaultDevices.forEach((strategy, devices) -> {
- mAudioSystem.setDevicesRoleForStrategy(
+ addDevicesRoleForStrategy(
strategy, AudioSystem.DEVICE_ROLE_DISABLED, devices); });
}
synchronized (mPreferredDevicesForCapturePreset) {
@@ -380,8 +434,7 @@ public class AudioDeviceInventory {
btInfo.mVolume * 10, btInfo.mAudioSystemDevice,
"onSetBtActiveDevice");
}
- makeA2dpDeviceAvailable(address, BtHelper.getName(btInfo.mDevice),
- "onSetBtActiveDevice", btInfo.mCodec);
+ makeA2dpDeviceAvailable(btInfo, "onSetBtActiveDevice");
}
break;
case BluetoothProfile.HEARING_AID:
@@ -397,10 +450,7 @@ public class AudioDeviceInventory {
if (switchToUnavailable) {
makeLeAudioDeviceUnavailableNow(address, btInfo.mAudioSystemDevice);
} else if (switchToAvailable) {
- makeLeAudioDeviceAvailable(address, BtHelper.getName(btInfo.mDevice),
- streamType, btInfo.mVolume == -1 ? -1 : btInfo.mVolume * 10,
- btInfo.mAudioSystemDevice,
- "onSetBtActiveDevice");
+ makeLeAudioDeviceAvailable(btInfo, streamType, "onSetBtActiveDevice");
}
break;
default: throw new IllegalArgumentException("Invalid profile "
@@ -411,30 +461,30 @@ public class AudioDeviceInventory {
@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
- /*package*/ void onBluetoothA2dpDeviceConfigChange(
- @NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, int event) {
+ /*package*/ void onBluetoothDeviceConfigChange(
+ @NonNull AudioDeviceBroker.BtDeviceInfo btInfo, int event) {
MediaMetrics.Item mmi = new MediaMetrics.Item(mMetricsId
- + "onBluetoothA2dpDeviceConfigChange")
- .set(MediaMetrics.Property.EVENT, BtHelper.a2dpDeviceEventToString(event));
+ + "onBluetoothDeviceConfigChange")
+ .set(MediaMetrics.Property.EVENT, BtHelper.deviceEventToString(event));
- final BluetoothDevice btDevice = btInfo.getBtDevice();
+ final BluetoothDevice btDevice = btInfo.mDevice;
if (btDevice == null) {
mmi.set(MediaMetrics.Property.EARLY_RETURN, "btDevice null").record();
return;
}
if (AudioService.DEBUG_DEVICES) {
- Log.d(TAG, "onBluetoothA2dpDeviceConfigChange btDevice=" + btDevice);
+ Log.d(TAG, "onBluetoothDeviceConfigChange btDevice=" + btDevice);
}
- int a2dpVolume = btInfo.getVolume();
- @AudioSystem.AudioFormatNativeEnumForBtCodec final int a2dpCodec = btInfo.getCodec();
+ int volume = btInfo.mVolume;
+ @AudioSystem.AudioFormatNativeEnumForBtCodec final int audioCodec = btInfo.mCodec;
String address = btDevice.getAddress();
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
address = "";
}
AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
- "onBluetoothA2dpDeviceConfigChange addr=" + address
- + " event=" + BtHelper.a2dpDeviceEventToString(event)));
+ "onBluetoothDeviceConfigChange addr=" + address
+ + " event=" + BtHelper.deviceEventToString(event)));
synchronized (mDevicesLock) {
if (mDeviceBroker.hasScheduledA2dpConnection(btDevice)) {
@@ -449,53 +499,53 @@ public class AudioDeviceInventory {
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
final DeviceInfo di = mConnectedDevices.get(key);
if (di == null) {
- Log.e(TAG, "invalid null DeviceInfo in onBluetoothA2dpDeviceConfigChange");
+ Log.e(TAG, "invalid null DeviceInfo in onBluetoothDeviceConfigChange");
mmi.set(MediaMetrics.Property.EARLY_RETURN, "null DeviceInfo").record();
return;
}
mmi.set(MediaMetrics.Property.ADDRESS, address)
.set(MediaMetrics.Property.ENCODING,
- AudioSystem.audioFormatToString(a2dpCodec))
- .set(MediaMetrics.Property.INDEX, a2dpVolume)
+ AudioSystem.audioFormatToString(audioCodec))
+ .set(MediaMetrics.Property.INDEX, volume)
.set(MediaMetrics.Property.NAME, di.mDeviceName);
- if (event == BtHelper.EVENT_ACTIVE_DEVICE_CHANGE) {
- // Device is connected
- if (a2dpVolume != -1) {
- mDeviceBroker.postSetVolumeIndexOnDevice(AudioSystem.STREAM_MUSIC,
- // convert index to internal representation in VolumeStreamState
- a2dpVolume * 10,
- AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
- "onBluetoothA2dpDeviceConfigChange");
- }
- } else if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) {
- if (di.mDeviceCodecFormat != a2dpCodec) {
- di.mDeviceCodecFormat = a2dpCodec;
- mConnectedDevices.replace(key, di);
- }
- }
- final int res = mAudioSystem.handleDeviceConfigChange(
- AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address,
- BtHelper.getName(btDevice), a2dpCodec);
- if (res != AudioSystem.AUDIO_STATUS_OK) {
- AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
- "APM handleDeviceConfigChange failed for A2DP device addr=" + address
- + " codec=" + AudioSystem.audioFormatToString(a2dpCodec))
- .printLog(TAG));
+ if (event == BtHelper.EVENT_DEVICE_CONFIG_CHANGE) {
+ boolean a2dpCodecChange = false;
+ if (btInfo.mProfile == BluetoothProfile.A2DP) {
+ if (di.mDeviceCodecFormat != audioCodec) {
+ di.mDeviceCodecFormat = audioCodec;
+ mConnectedDevices.replace(key, di);
+ a2dpCodecChange = true;
+ }
+ final int res = mAudioSystem.handleDeviceConfigChange(
+ btInfo.mAudioSystemDevice, address,
+ BtHelper.getName(btDevice), audioCodec);
+
+ if (res != AudioSystem.AUDIO_STATUS_OK) {
+ AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
+ "APM handleDeviceConfigChange failed for A2DP device addr="
+ + address + " codec="
+ + AudioSystem.audioFormatToString(audioCodec))
+ .printLog(TAG));
+
+ // force A2DP device disconnection in case of error so that AudioService
+ // state is consistent with audio policy manager state
+ setBluetoothActiveDevice(new AudioDeviceBroker.BtDeviceInfo(btInfo,
+ BluetoothProfile.STATE_DISCONNECTED));
+ } else {
+ AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
+ "APM handleDeviceConfigChange success for A2DP device addr="
+ + address
+ + " codec=" + AudioSystem.audioFormatToString(audioCodec))
+ .printLog(TAG));
- int musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC);
- // force A2DP device disconnection in case of error so that AudioService state is
- // consistent with audio policy manager state
- setBluetoothActiveDevice(new AudioDeviceBroker.BtDeviceInfo(btDevice,
- BluetoothProfile.A2DP, BluetoothProfile.STATE_DISCONNECTED,
- musicDevice, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP));
- } else {
- AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
- "APM handleDeviceConfigChange success for A2DP device addr=" + address
- + " codec=" + AudioSystem.audioFormatToString(a2dpCodec))
- .printLog(TAG));
+ }
+ }
+ if (!a2dpCodecChange) {
+ updateBluetoothPreferredModes_l(btDevice /*connectedDevice*/);
+ }
}
}
mmi.record();
@@ -578,7 +628,7 @@ public class AudioDeviceInventory {
}
if (!handleDeviceConnection(wdcs.mAttributes,
- wdcs.mState == AudioService.CONNECTION_STATE_CONNECTED, wdcs.mForTest)) {
+ wdcs.mState == AudioService.CONNECTION_STATE_CONNECTED, wdcs.mForTest, null)) {
// change of connection state failed, bailout
mmi.set(MediaMetrics.Property.EARLY_RETURN, "change of connection state failed")
.record();
@@ -710,43 +760,51 @@ public class AudioDeviceInventory {
//------------------------------------------------------------
// preferred/non-default device(s)
- /*package*/ int setPreferredDevicesForStrategySync(int strategy,
+ /*package*/ int setPreferredDevicesForStrategyAndSave(int strategy,
@NonNull List<AudioDeviceAttributes> devices) {
- int status = AudioSystem.ERROR;
+ final int status = setPreferredDevicesForStrategy(strategy, devices);
+ if (status == AudioSystem.SUCCESS) {
+ mDeviceBroker.postSaveSetPreferredDevicesForStrategy(strategy, devices);
+ }
+ return status;
+ }
+ /*package*/ int setPreferredDevicesForStrategy(int strategy,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ int status = AudioSystem.ERROR;
try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
- "setPreferredDevicesForStrategySync, strategy: " + strategy
+ "setPreferredDevicesForStrategy, strategy: " + strategy
+ " devices: " + devices)).printLog(TAG));
- status = mAudioSystem.setDevicesRoleForStrategy(
+ status = setDevicesRoleForStrategy(
strategy, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
}
+ return status;
+ }
+ /*package*/ int removePreferredDevicesForStrategyAndSave(int strategy) {
+ final int status = removePreferredDevicesForStrategy(strategy);
if (status == AudioSystem.SUCCESS) {
- mDeviceBroker.postSaveSetPreferredDevicesForStrategy(strategy, devices);
+ mDeviceBroker.postSaveRemovePreferredDevicesForStrategy(strategy);
}
return status;
}
- /*package*/ int removePreferredDevicesForStrategySync(int strategy) {
+ /*package*/ int removePreferredDevicesForStrategy(int strategy) {
int status = AudioSystem.ERROR;
try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
- "removePreferredDevicesForStrategySync, strategy: "
+ "removePreferredDevicesForStrategy, strategy: "
+ strategy)).printLog(TAG));
- status = mAudioSystem.clearDevicesRoleForStrategy(
+ status = clearDevicesRoleForStrategy(
strategy, AudioSystem.DEVICE_ROLE_PREFERRED);
}
-
- if (status == AudioSystem.SUCCESS) {
- mDeviceBroker.postSaveRemovePreferredDevicesForStrategy(strategy);
- }
return status;
}
- /*package*/ int setDeviceAsNonDefaultForStrategySync(int strategy,
+ /*package*/ int setDeviceAsNonDefaultForStrategyAndSave(int strategy,
@NonNull AudioDeviceAttributes device) {
int status = AudioSystem.ERROR;
@@ -755,9 +813,9 @@ public class AudioDeviceInventory {
devices.add(device);
AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
- "setDeviceAsNonDefaultForStrategySync, strategy: " + strategy
+ "setDeviceAsNonDefaultForStrategyAndSave, strategy: " + strategy
+ " device: " + device)).printLog(TAG));
- status = mAudioSystem.setDevicesRoleForStrategy(
+ status = addDevicesRoleForStrategy(
strategy, AudioSystem.DEVICE_ROLE_DISABLED, devices);
}
@@ -767,7 +825,7 @@ public class AudioDeviceInventory {
return status;
}
- /*package*/ int removeDeviceAsNonDefaultForStrategySync(int strategy,
+ /*package*/ int removeDeviceAsNonDefaultForStrategyAndSave(int strategy,
@NonNull AudioDeviceAttributes device) {
int status = AudioSystem.ERROR;
@@ -776,10 +834,10 @@ public class AudioDeviceInventory {
devices.add(device);
AudioService.sDeviceLogger.enqueue((new EventLogger.StringEvent(
- "removeDeviceAsNonDefaultForStrategySync, strategy: "
+ "removeDeviceAsNonDefaultForStrategyAndSave, strategy: "
+ strategy + " devices: " + device)).printLog(TAG));
- status = mAudioSystem.removeDevicesRoleForStrategy(
+ status = removeDevicesRoleForStrategy(
strategy, AudioSystem.DEVICE_ROLE_DISABLED, devices);
}
@@ -810,35 +868,72 @@ public class AudioDeviceInventory {
mNonDefDevDispatchers.unregister(dispatcher);
}
- /*package*/ int setPreferredDevicesForCapturePresetSync(
+ /*package*/ int setPreferredDevicesForCapturePresetAndSave(
int capturePreset, @NonNull List<AudioDeviceAttributes> devices) {
- int status = AudioSystem.ERROR;
+ final int status = setPreferredDevicesForCapturePreset(capturePreset, devices);
+ if (status == AudioSystem.SUCCESS) {
+ mDeviceBroker.postSaveSetPreferredDevicesForCapturePreset(capturePreset, devices);
+ }
+ return status;
+ }
+ private int setPreferredDevicesForCapturePreset(
+ int capturePreset, @NonNull List<AudioDeviceAttributes> devices) {
+ int status = AudioSystem.ERROR;
try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
- status = mAudioSystem.setDevicesRoleForCapturePreset(
+ status = setDevicesRoleForCapturePreset(
capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED, devices);
}
+ return status;
+ }
+ /*package*/ int clearPreferredDevicesForCapturePresetAndSave(int capturePreset) {
+ final int status = clearPreferredDevicesForCapturePreset(capturePreset);
if (status == AudioSystem.SUCCESS) {
- mDeviceBroker.postSaveSetPreferredDevicesForCapturePreset(capturePreset, devices);
+ mDeviceBroker.postSaveClearPreferredDevicesForCapturePreset(capturePreset);
}
return status;
}
- /*package*/ int clearPreferredDevicesForCapturePresetSync(int capturePreset) {
+ private int clearPreferredDevicesForCapturePreset(int capturePreset) {
int status = AudioSystem.ERROR;
try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
- status = mAudioSystem.clearDevicesRoleForCapturePreset(
+ status = clearDevicesRoleForCapturePreset(
capturePreset, AudioSystem.DEVICE_ROLE_PREFERRED);
}
-
- if (status == AudioSystem.SUCCESS) {
- mDeviceBroker.postSaveClearPreferredDevicesForCapturePreset(capturePreset);
- }
return status;
}
+ private int addDevicesRoleForCapturePreset(int capturePreset, int role,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ return addDevicesRole(mAppliedPresetRoles, (p, r, d) -> {
+ return mAudioSystem.addDevicesRoleForCapturePreset(p, r, d);
+ }, capturePreset, role, devices);
+ }
+
+ private int removeDevicesRoleForCapturePreset(int capturePreset, int role,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ return removeDevicesRole(mAppliedPresetRoles, (p, r, d) -> {
+ return mAudioSystem.removeDevicesRoleForCapturePreset(p, r, d);
+ }, capturePreset, role, devices);
+ }
+
+ private int setDevicesRoleForCapturePreset(int capturePreset, int role,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ return setDevicesRole(mAppliedPresetRoles, (p, r, d) -> {
+ return mAudioSystem.addDevicesRoleForCapturePreset(p, r, d);
+ }, (p, r, d) -> {
+ return mAudioSystem.clearDevicesRoleForCapturePreset(p, r);
+ }, capturePreset, role, devices);
+ }
+
+ private int clearDevicesRoleForCapturePreset(int capturePreset, int role) {
+ return clearDevicesRole(mAppliedPresetRoles, (p, r, d) -> {
+ return mAudioSystem.clearDevicesRoleForCapturePreset(p, r);
+ }, capturePreset, role);
+ }
+
/*package*/ void registerCapturePresetDevicesRoleDispatcher(
@NonNull ICapturePresetDevicesRoleDispatcher dispatcher) {
mDevRoleCapturePresetDispatchers.register(dispatcher);
@@ -849,7 +944,208 @@ public class AudioDeviceInventory {
mDevRoleCapturePresetDispatchers.unregister(dispatcher);
}
- //-----------------------------------------------------------------------
+ private int addDevicesRoleForStrategy(int strategy, int role,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ return addDevicesRole(mAppliedStrategyRoles, (s, r, d) -> {
+ return mAudioSystem.setDevicesRoleForStrategy(s, r, d);
+ }, strategy, role, devices);
+ }
+
+ private int removeDevicesRoleForStrategy(int strategy, int role,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ return removeDevicesRole(mAppliedStrategyRoles, (s, r, d) -> {
+ return mAudioSystem.removeDevicesRoleForStrategy(s, r, d);
+ }, strategy, role, devices);
+ }
+
+ private int setDevicesRoleForStrategy(int strategy, int role,
+ @NonNull List<AudioDeviceAttributes> devices) {
+ return setDevicesRole(mAppliedStrategyRoles, (s, r, d) -> {
+ return mAudioSystem.setDevicesRoleForStrategy(s, r, d);
+ }, (s, r, d) -> {
+ return mAudioSystem.clearDevicesRoleForStrategy(s, r);
+ }, strategy, role, devices);
+ }
+
+ private int clearDevicesRoleForStrategy(int strategy, int role) {
+ return clearDevicesRole(mAppliedStrategyRoles, (s, r, d) -> {
+ return mAudioSystem.clearDevicesRoleForStrategy(s, r);
+ }, strategy, role);
+ }
+
+ //------------------------------------------------------------
+ // Cache for applied roles for strategies and devices. The cache avoids reapplying the
+ // same list of devices for a given role and strategy and the corresponding systematic
+ // redundant work in audio policy manager and audio flinger.
+ // The key is the pair <Strategy , Role> and the value is the current list of devices.
+
+ private final ArrayMap<Pair<Integer, Integer>, List<AudioDeviceAttributes>>
+ mAppliedStrategyRoles = new ArrayMap<>();
+
+ // Cache for applied roles for capture presets and devices. The cache avoids reapplying the
+ // same list of devices for a given role and capture preset and the corresponding systematic
+ // redundant work in audio policy manager and audio flinger.
+ // The key is the pair <Preset , Role> and the value is the current list of devices.
+ private final ArrayMap<Pair<Integer, Integer>, List<AudioDeviceAttributes>>
+ mAppliedPresetRoles = new ArrayMap<>();
+
+ interface AudioSystemInterface {
+ int deviceRoleAction(int usecase, int role, @Nullable List<AudioDeviceAttributes> devices);
+ }
+
+ private int addDevicesRole(
+ ArrayMap<Pair<Integer, Integer>, List<AudioDeviceAttributes>> rolesMap,
+ AudioSystemInterface asi,
+ int useCase, int role, @NonNull List<AudioDeviceAttributes> devices) {
+ synchronized (rolesMap) {
+ Pair<Integer, Integer> key = new Pair<>(useCase, role);
+ List<AudioDeviceAttributes> roleDevices = new ArrayList<>();
+ List<AudioDeviceAttributes> appliedDevices = new ArrayList<>();
+
+ if (rolesMap.containsKey(key)) {
+ roleDevices = rolesMap.get(key);
+ for (AudioDeviceAttributes device : devices) {
+ if (!roleDevices.contains(device)) {
+ appliedDevices.add(device);
+ }
+ }
+ } else {
+ appliedDevices.addAll(devices);
+ }
+ if (appliedDevices.isEmpty()) {
+ return AudioSystem.SUCCESS;
+ }
+ final int status = asi.deviceRoleAction(useCase, role, appliedDevices);
+ if (status == AudioSystem.SUCCESS) {
+ roleDevices.addAll(appliedDevices);
+ rolesMap.put(key, roleDevices);
+ }
+ return status;
+ }
+ }
+
+ private int removeDevicesRole(
+ ArrayMap<Pair<Integer, Integer>, List<AudioDeviceAttributes>> rolesMap,
+ AudioSystemInterface asi,
+ int useCase, int role, @NonNull List<AudioDeviceAttributes> devices) {
+ synchronized (rolesMap) {
+ Pair<Integer, Integer> key = new Pair<>(useCase, role);
+ if (!rolesMap.containsKey(key)) {
+ return AudioSystem.SUCCESS;
+ }
+ List<AudioDeviceAttributes> roleDevices = rolesMap.get(key);
+ List<AudioDeviceAttributes> appliedDevices = new ArrayList<>();
+ for (AudioDeviceAttributes device : devices) {
+ if (roleDevices.contains(device)) {
+ appliedDevices.add(device);
+ }
+ }
+ if (appliedDevices.isEmpty()) {
+ return AudioSystem.SUCCESS;
+ }
+ final int status = asi.deviceRoleAction(useCase, role, appliedDevices);
+ if (status == AudioSystem.SUCCESS) {
+ roleDevices.removeAll(appliedDevices);
+ if (roleDevices.isEmpty()) {
+ rolesMap.remove(key);
+ } else {
+ rolesMap.put(key, roleDevices);
+ }
+ }
+ return status;
+ }
+ }
+
+ private int setDevicesRole(
+ ArrayMap<Pair<Integer, Integer>, List<AudioDeviceAttributes>> rolesMap,
+ AudioSystemInterface addOp,
+ AudioSystemInterface clearOp,
+ int useCase, int role, @NonNull List<AudioDeviceAttributes> devices) {
+ synchronized (rolesMap) {
+ Pair<Integer, Integer> key = new Pair<>(useCase, role);
+ List<AudioDeviceAttributes> roleDevices = new ArrayList<>();
+ List<AudioDeviceAttributes> appliedDevices = new ArrayList<>();
+
+ if (rolesMap.containsKey(key)) {
+ roleDevices = rolesMap.get(key);
+ boolean equal = false;
+ if (roleDevices.size() == devices.size()) {
+ roleDevices.retainAll(devices);
+ equal = roleDevices.size() == devices.size();
+ }
+ if (!equal) {
+ clearOp.deviceRoleAction(useCase, role, null);
+ roleDevices.clear();
+ appliedDevices.addAll(devices);
+ }
+ } else {
+ appliedDevices.addAll(devices);
+ }
+ if (appliedDevices.isEmpty()) {
+ return AudioSystem.SUCCESS;
+ }
+ final int status = addOp.deviceRoleAction(useCase, role, appliedDevices);
+ if (status == AudioSystem.SUCCESS) {
+ roleDevices.addAll(appliedDevices);
+ rolesMap.put(key, roleDevices);
+ }
+ return status;
+ }
+ }
+
+ private int clearDevicesRole(
+ ArrayMap<Pair<Integer, Integer>, List<AudioDeviceAttributes>> rolesMap,
+ AudioSystemInterface asi, int useCase, int role) {
+ synchronized (rolesMap) {
+ Pair<Integer, Integer> key = new Pair<>(useCase, role);
+ if (!rolesMap.containsKey(key)) {
+ return AudioSystem.SUCCESS;
+ }
+ final int status = asi.deviceRoleAction(useCase, role, null);
+ if (status == AudioSystem.SUCCESS) {
+ rolesMap.remove(key);
+ }
+ return status;
+ }
+ }
+
+ @GuardedBy("mDevicesLock")
+ private void purgeDevicesRoles_l() {
+ purgeRoles(mAppliedStrategyRoles, (s, r, d) -> {
+ return mAudioSystem.removeDevicesRoleForStrategy(s, r, d); });
+ purgeRoles(mAppliedPresetRoles, (p, r, d) -> {
+ return mAudioSystem.removeDevicesRoleForCapturePreset(p, r, d); });
+ }
+
+ @GuardedBy("mDevicesLock")
+ private void purgeRoles(
+ ArrayMap<Pair<Integer, Integer>, List<AudioDeviceAttributes>> rolesMap,
+ AudioSystemInterface asi) {
+ synchronized (rolesMap) {
+ Iterator<Map.Entry<Pair<Integer, Integer>, List<AudioDeviceAttributes>>> itRole =
+ rolesMap.entrySet().iterator();
+ while (itRole.hasNext()) {
+ Map.Entry<Pair<Integer, Integer>, List<AudioDeviceAttributes>> entry =
+ itRole.next();
+ Pair<Integer, Integer> keyRole = entry.getKey();
+ Iterator<AudioDeviceAttributes> itDev = rolesMap.get(keyRole).iterator();
+ while (itDev.hasNext()) {
+ AudioDeviceAttributes ada = itDev.next();
+ final String devKey = DeviceInfo.makeDeviceListKey(ada.getInternalType(),
+ ada.getAddress());
+ if (mConnectedDevices.get(devKey) == null) {
+ asi.deviceRoleAction(keyRole.first, keyRole.second, Arrays.asList(ada));
+ itDev.remove();
+ }
+ }
+ if (rolesMap.get(keyRole).isEmpty()) {
+ itRole.remove();
+ }
+ }
+ }
+ }
+
+//-----------------------------------------------------------------------
/**
* Check if a device is in the list of connected devices
@@ -871,10 +1167,11 @@ public class AudioDeviceInventory {
* @param connect true if connection
* @param isForTesting if true, not calling AudioSystem for the connection as this is
* just for testing
+ * @param btDevice the corresponding Bluetooth device when relevant.
* @return false if an error was reported by AudioSystem
*/
/*package*/ boolean handleDeviceConnection(AudioDeviceAttributes attributes, boolean connect,
- boolean isForTesting) {
+ boolean isForTesting, @Nullable BluetoothDevice btDevice) {
int device = attributes.getInternalType();
String address = attributes.getAddress();
String deviceName = attributes.getName();
@@ -889,6 +1186,7 @@ public class AudioDeviceInventory {
.set(MediaMetrics.Property.MODE, connect
? MediaMetrics.Value.CONNECT : MediaMetrics.Value.DISCONNECT)
.set(MediaMetrics.Property.NAME, deviceName);
+ boolean status = false;
synchronized (mDevicesLock) {
final String deviceKey = DeviceInfo.makeDeviceListKey(device, address);
if (AudioService.DEBUG_DEVICES) {
@@ -916,24 +1214,31 @@ public class AudioDeviceInventory {
.record();
return false;
}
- mConnectedDevices.put(deviceKey, new DeviceInfo(
- device, deviceName, address, AudioSystem.AUDIO_FORMAT_DEFAULT));
+ mConnectedDevices.put(deviceKey, new DeviceInfo(device, deviceName, address));
mDeviceBroker.postAccessoryPlugMediaUnmute(device);
- mmi.set(MediaMetrics.Property.STATE, MediaMetrics.Value.CONNECTED).record();
- return true;
+ status = true;
} else if (!connect && isConnected) {
mAudioSystem.setDeviceConnectionState(attributes,
AudioSystem.DEVICE_STATE_UNAVAILABLE, AudioSystem.AUDIO_FORMAT_DEFAULT);
// always remove even if disconnection failed
mConnectedDevices.remove(deviceKey);
+ status = true;
+ }
+ if (status) {
+ if (AudioSystem.isBluetoothScoDevice(device)) {
+ updateBluetoothPreferredModes_l(connect ? btDevice : null /*connectedDevice*/);
+ if (!connect) {
+ purgeDevicesRoles_l();
+ }
+ }
mmi.set(MediaMetrics.Property.STATE, MediaMetrics.Value.CONNECTED).record();
- return true;
+ } else {
+ Log.w(TAG, "handleDeviceConnection() failed, deviceKey=" + deviceKey
+ + ", deviceSpec=" + di + ", connect=" + connect);
+ mmi.set(MediaMetrics.Property.STATE, MediaMetrics.Value.DISCONNECTED).record();
}
- Log.w(TAG, "handleDeviceConnection() failed, deviceKey=" + deviceKey
- + ", deviceSpec=" + di + ", connect=" + connect);
}
- mmi.set(MediaMetrics.Property.STATE, MediaMetrics.Value.DISCONNECTED).record();
- return false;
+ return status;
}
@@ -1142,15 +1447,20 @@ public class AudioDeviceInventory {
// Internal utilities
@GuardedBy("mDevicesLock")
- private void makeA2dpDeviceAvailable(String address, String name, String eventSource,
- int a2dpCodec) {
+ private void makeA2dpDeviceAvailable(AudioDeviceBroker.BtDeviceInfo btInfo,
+ String eventSource) {
+ final String address = btInfo.mDevice.getAddress();
+ final String name = BtHelper.getName(btInfo.mDevice);
+ final int a2dpCodec = btInfo.mCodec;
+
// enable A2DP before notifying A2DP connection to avoid unnecessary processing in
// audio policy manager
mDeviceBroker.setBluetoothA2dpOnInt(true, true /*fromA2dp*/, eventSource);
// at this point there could be another A2DP device already connected in APM, but it
// doesn't matter as this new one will overwrite the previous one
- final int res = mAudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
- AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address, name),
+ AudioDeviceAttributes ada = new AudioDeviceAttributes(
+ AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address, name);
+ final int res = mAudioSystem.setDeviceConnectionState(ada,
AudioSystem.DEVICE_STATE_AVAILABLE, a2dpCodec);
// TODO: log in MediaMetrics once distinction between connection failure and
@@ -1172,8 +1482,7 @@ public class AudioDeviceInventory {
// The convention for head tracking sensors associated with A2DP devices is to
// use a UUID derived from the MAC address as follows:
// time_low = 0, time_mid = 0, time_hi = 0, clock_seq = 0, node = MAC Address
- UUID sensorUuid = UuidUtils.uuidFromAudioDeviceAttributes(
- new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address));
+ UUID sensorUuid = UuidUtils.uuidFromAudioDeviceAttributes(ada);
final DeviceInfo di = new DeviceInfo(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, name,
address, a2dpCodec, sensorUuid);
final String diKey = di.getKey();
@@ -1184,6 +1493,208 @@ public class AudioDeviceInventory {
mDeviceBroker.postAccessoryPlugMediaUnmute(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
setCurrentAudioRouteNameIfPossible(name, true /*fromA2dp*/);
+
+ updateBluetoothPreferredModes_l(btInfo.mDevice /*connectedDevice*/);
+ }
+
+ static final int[] CAPTURE_PRESETS = new int[] {AudioSource.MIC, AudioSource.CAMCORDER,
+ AudioSource.VOICE_RECOGNITION, AudioSource.VOICE_COMMUNICATION,
+ AudioSource.UNPROCESSED, AudioSource.VOICE_PERFORMANCE, AudioSource.HOTWORD};
+
+ // reflects system property persist.bluetooth.enable_dual_mode_audio
+ final boolean mBluetoothDualModeEnabled;
+ /**
+ * Goes over all connected Bluetooth devices and set the audio policy device role to DISABLED
+ * or not according to their own and other devices modes.
+ * The top priority is given to LE devices, then SCO ,then A2DP.
+ */
+ @GuardedBy("mDevicesLock")
+ private void applyConnectedDevicesRoles_l() {
+ if (!mBluetoothDualModeEnabled) {
+ return;
+ }
+ DeviceInfo leOutDevice =
+ getFirstConnectedDeviceOfTypes(AudioSystem.DEVICE_OUT_ALL_BLE_SET);
+ DeviceInfo leInDevice =
+ getFirstConnectedDeviceOfTypes(AudioSystem.DEVICE_IN_ALL_BLE_SET);
+ DeviceInfo a2dpDevice =
+ getFirstConnectedDeviceOfTypes(AudioSystem.DEVICE_OUT_ALL_A2DP_SET);
+ DeviceInfo scoOutDevice =
+ getFirstConnectedDeviceOfTypes(AudioSystem.DEVICE_OUT_ALL_SCO_SET);
+ DeviceInfo scoInDevice =
+ getFirstConnectedDeviceOfTypes(AudioSystem.DEVICE_IN_ALL_SCO_SET);
+ boolean disableA2dp = (leOutDevice != null && leOutDevice.isOutputOnlyModeEnabled());
+ boolean disableSco = (leOutDevice != null && leOutDevice.isDuplexModeEnabled())
+ || (leInDevice != null && leInDevice.isDuplexModeEnabled());
+ AudioDeviceAttributes communicationDevice =
+ mDeviceBroker.mActiveCommunicationDevice == null
+ ? null : ((mDeviceBroker.isInCommunication()
+ && mDeviceBroker.mActiveCommunicationDevice != null)
+ ? new AudioDeviceAttributes(mDeviceBroker.mActiveCommunicationDevice)
+ : null);
+
+ if (AudioService.DEBUG_DEVICES) {
+ Log.i(TAG, "applyConnectedDevicesRoles_l\n - leOutDevice: " + leOutDevice
+ + "\n - leInDevice: " + leInDevice
+ + "\n - a2dpDevice: " + a2dpDevice
+ + "\n - scoOutDevice: " + scoOutDevice
+ + "\n - scoInDevice: " + scoInDevice
+ + "\n - disableA2dp: " + disableA2dp
+ + ", disableSco: " + disableSco);
+ }
+
+ for (DeviceInfo di : mConnectedDevices.values()) {
+ if (!AudioSystem.isBluetoothDevice(di.mDeviceType)) {
+ continue;
+ }
+ AudioDeviceAttributes ada =
+ new AudioDeviceAttributes(di.mDeviceType, di.mDeviceAddress, di.mDeviceName);
+ if (AudioService.DEBUG_DEVICES) {
+ Log.i(TAG, " + checking Device: " + ada);
+ }
+ if (ada.equalTypeAddress(communicationDevice)) {
+ continue;
+ }
+
+ if (AudioSystem.isBluetoothOutDevice(di.mDeviceType)) {
+ for (AudioProductStrategy strategy : mStrategies) {
+ boolean disable = false;
+ if (strategy.getId() == mDeviceBroker.mCommunicationStrategyId) {
+ if (AudioSystem.isBluetoothScoDevice(di.mDeviceType)) {
+ disable = disableSco || !di.isDuplexModeEnabled();
+ } else if (AudioSystem.isBluetoothLeDevice(di.mDeviceType)) {
+ disable = !di.isDuplexModeEnabled();
+ }
+ } else {
+ if (AudioSystem.isBluetoothA2dpOutDevice(di.mDeviceType)) {
+ disable = disableA2dp || !di.isOutputOnlyModeEnabled();
+ } else if (AudioSystem.isBluetoothScoDevice(di.mDeviceType)) {
+ disable = disableSco || !di.isOutputOnlyModeEnabled();
+ } else if (AudioSystem.isBluetoothLeDevice(di.mDeviceType)) {
+ disable = !di.isOutputOnlyModeEnabled();
+ }
+ }
+ if (AudioService.DEBUG_DEVICES) {
+ Log.i(TAG, " - strategy: " + strategy.getId()
+ + ", disable: " + disable);
+ }
+ if (disable) {
+ addDevicesRoleForStrategy(strategy.getId(),
+ AudioSystem.DEVICE_ROLE_DISABLED, Arrays.asList(ada));
+ } else {
+ removeDevicesRoleForStrategy(strategy.getId(),
+ AudioSystem.DEVICE_ROLE_DISABLED, Arrays.asList(ada));
+ }
+ }
+ }
+ if (AudioSystem.isBluetoothInDevice(di.mDeviceType)) {
+ for (int capturePreset : CAPTURE_PRESETS) {
+ boolean disable = false;
+ if (AudioSystem.isBluetoothScoDevice(di.mDeviceType)) {
+ disable = disableSco || !di.isDuplexModeEnabled();
+ } else if (AudioSystem.isBluetoothLeDevice(di.mDeviceType)) {
+ disable = !di.isDuplexModeEnabled();
+ }
+ if (AudioService.DEBUG_DEVICES) {
+ Log.i(TAG, " - capturePreset: " + capturePreset
+ + ", disable: " + disable);
+ }
+ if (disable) {
+ addDevicesRoleForCapturePreset(capturePreset,
+ AudioSystem.DEVICE_ROLE_DISABLED, Arrays.asList(ada));
+ } else {
+ removeDevicesRoleForCapturePreset(capturePreset,
+ AudioSystem.DEVICE_ROLE_DISABLED, Arrays.asList(ada));
+ }
+ }
+ }
+ }
+ }
+
+ /* package */ void applyConnectedDevicesRoles() {
+ synchronized (mDevicesLock) {
+ applyConnectedDevicesRoles_l();
+ }
+ }
+
+ @GuardedBy("mDevicesLock")
+ int checkProfileIsConnected(int profile) {
+ switch (profile) {
+ case BluetoothProfile.HEADSET:
+ if (getFirstConnectedDeviceOfTypes(
+ AudioSystem.DEVICE_OUT_ALL_SCO_SET) != null
+ || getFirstConnectedDeviceOfTypes(
+ AudioSystem.DEVICE_IN_ALL_SCO_SET) != null) {
+ return profile;
+ }
+ break;
+ case BluetoothProfile.A2DP:
+ if (getFirstConnectedDeviceOfTypes(
+ AudioSystem.DEVICE_OUT_ALL_A2DP_SET) != null) {
+ return profile;
+ }
+ break;
+ case BluetoothProfile.LE_AUDIO:
+ case BluetoothProfile.LE_AUDIO_BROADCAST:
+ if (getFirstConnectedDeviceOfTypes(
+ AudioSystem.DEVICE_OUT_ALL_BLE_SET) != null
+ || getFirstConnectedDeviceOfTypes(
+ AudioSystem.DEVICE_IN_ALL_BLE_SET) != null) {
+ return profile;
+ }
+ break;
+ default:
+ break;
+ }
+ return 0;
+ }
+
+ @GuardedBy("mDevicesLock")
+ private void updateBluetoothPreferredModes_l(BluetoothDevice connectedDevice) {
+ if (!mBluetoothDualModeEnabled) {
+ return;
+ }
+ HashSet<String> processedAddresses = new HashSet<>(0);
+ for (DeviceInfo di : mConnectedDevices.values()) {
+ if (!AudioSystem.isBluetoothDevice(di.mDeviceType)
+ || processedAddresses.contains(di.mDeviceAddress)) {
+ continue;
+ }
+ Bundle preferredProfiles = BtHelper.getPreferredAudioProfiles(di.mDeviceAddress);
+ if (AudioService.DEBUG_DEVICES) {
+ Log.i(TAG, "updateBluetoothPreferredModes_l processing device address: "
+ + di.mDeviceAddress + ", preferredProfiles: " + preferredProfiles);
+ }
+ for (DeviceInfo di2 : mConnectedDevices.values()) {
+ if (!AudioSystem.isBluetoothDevice(di2.mDeviceType)
+ || !di.mDeviceAddress.equals(di2.mDeviceAddress)) {
+ continue;
+ }
+ int profile = BtHelper.getProfileFromType(di2.mDeviceType);
+ if (profile == 0) {
+ continue;
+ }
+ int preferredProfile = checkProfileIsConnected(
+ preferredProfiles.getInt(BluetoothAdapter.AUDIO_MODE_DUPLEX));
+ if (preferredProfile == profile || preferredProfile == 0) {
+ di2.setModeEnabled(BluetoothAdapter.AUDIO_MODE_DUPLEX);
+ } else {
+ di2.setModeDisabled(BluetoothAdapter.AUDIO_MODE_DUPLEX);
+ }
+ preferredProfile = checkProfileIsConnected(
+ preferredProfiles.getInt(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY));
+ if (preferredProfile == profile || preferredProfile == 0) {
+ di2.setModeEnabled(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY);
+ } else {
+ di2.setModeDisabled(BluetoothAdapter.AUDIO_MODE_OUTPUT_ONLY);
+ }
+ }
+ processedAddresses.add(di.mDeviceAddress);
+ }
+ applyConnectedDevicesRoles_l();
+ if (connectedDevice != null) {
+ mDeviceBroker.postNotifyPreferredAudioProfileApplied(connectedDevice);
+ }
}
@GuardedBy("mDevicesLock")
@@ -1231,6 +1742,8 @@ public class AudioDeviceInventory {
// Remove A2DP routes as well
setCurrentAudioRouteNameIfPossible(null, true /*fromA2dp*/);
mmi.record();
+ updateBluetoothPreferredModes_l(null /*connectedDevice*/);
+ purgeDevicesRoles_l();
}
@GuardedBy("mDevicesLock")
@@ -1260,8 +1773,7 @@ public class AudioDeviceInventory {
AudioSystem.AUDIO_FORMAT_DEFAULT);
mConnectedDevices.put(
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, address),
- new DeviceInfo(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, "",
- address, AudioSystem.AUDIO_FORMAT_DEFAULT));
+ new DeviceInfo(AudioSystem.DEVICE_IN_BLUETOOTH_A2DP, "", address));
}
@GuardedBy("mDevicesLock")
@@ -1287,8 +1799,7 @@ public class AudioDeviceInventory {
AudioSystem.AUDIO_FORMAT_DEFAULT);
mConnectedDevices.put(
DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_HEARING_AID, address),
- new DeviceInfo(AudioSystem.DEVICE_OUT_HEARING_AID, name,
- address, AudioSystem.AUDIO_FORMAT_DEFAULT));
+ new DeviceInfo(AudioSystem.DEVICE_OUT_HEARING_AID, name, address));
mDeviceBroker.postAccessoryPlugMediaUnmute(AudioSystem.DEVICE_OUT_HEARING_AID);
mDeviceBroker.postApplyVolumeOnDevice(streamType,
AudioSystem.DEVICE_OUT_HEARING_AID, "makeHearingAidDeviceAvailable");
@@ -1326,29 +1837,56 @@ public class AudioDeviceInventory {
* @return true if a DEVICE_OUT_HEARING_AID is connected, false otherwise.
*/
boolean isHearingAidConnected() {
+ return getFirstConnectedDeviceOfTypes(
+ Sets.newHashSet(AudioSystem.DEVICE_OUT_HEARING_AID)) != null;
+ }
+
+ /**
+ * Returns a DeviceInfo for the first connected device matching one of the supplied types
+ */
+ private DeviceInfo getFirstConnectedDeviceOfTypes(Set<Integer> internalTypes) {
+ List<DeviceInfo> devices = getConnectedDevicesOfTypes(internalTypes);
+ return devices.isEmpty() ? null : devices.get(0);
+ }
+
+ /**
+ * Returns a list of connected devices matching one of the supplied types
+ */
+ private List<DeviceInfo> getConnectedDevicesOfTypes(Set<Integer> internalTypes) {
+ ArrayList<DeviceInfo> devices = new ArrayList<>();
synchronized (mDevicesLock) {
for (DeviceInfo di : mConnectedDevices.values()) {
- if (di.mDeviceType == AudioSystem.DEVICE_OUT_HEARING_AID) {
- return true;
+ if (internalTypes.contains(di.mDeviceType)) {
+ devices.add(di);
}
}
- return false;
}
+ return devices;
+ }
+
+ /* package */ AudioDeviceAttributes getDeviceOfType(int type) {
+ DeviceInfo di = getFirstConnectedDeviceOfTypes(Sets.newHashSet(type));
+ return di == null ? null : new AudioDeviceAttributes(
+ di.mDeviceType, di.mDeviceAddress, di.mDeviceName);
}
@GuardedBy("mDevicesLock")
- private void makeLeAudioDeviceAvailable(String address, String name, int streamType,
- int volumeIndex, int device, String eventSource) {
+ private void makeLeAudioDeviceAvailable(
+ AudioDeviceBroker.BtDeviceInfo btInfo, int streamType, String eventSource) {
+ final String address = btInfo.mDevice.getAddress();
+ final String name = BtHelper.getName(btInfo.mDevice);
+ final int volumeIndex = btInfo.mVolume == -1 ? -1 : btInfo.mVolume * 10;
+ final int device = btInfo.mAudioSystemDevice;
+
if (device != AudioSystem.DEVICE_NONE) {
/* Audio Policy sees Le Audio similar to A2DP. Let's make sure
* AUDIO_POLICY_FORCE_NO_BT_A2DP is not set
*/
mDeviceBroker.setBluetoothA2dpOnInt(true, false /*fromA2dp*/, eventSource);
- final int res = AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
- device, address, name),
- AudioSystem.DEVICE_STATE_AVAILABLE,
- AudioSystem.AUDIO_FORMAT_DEFAULT);
+ AudioDeviceAttributes ada = new AudioDeviceAttributes(device, address, name);
+ final int res = AudioSystem.setDeviceConnectionState(ada,
+ AudioSystem.DEVICE_STATE_AVAILABLE, AudioSystem.AUDIO_FORMAT_DEFAULT);
if (res != AudioSystem.AUDIO_STATUS_OK) {
AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
"APM failed to make available LE Audio device addr=" + address
@@ -1359,12 +1897,13 @@ public class AudioDeviceInventory {
AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
"LE Audio device addr=" + address + " now available").printLog(TAG));
}
-
// Reset LEA suspend state each time a new sink is connected
mDeviceBroker.clearLeAudioSuspended();
+ UUID sensorUuid = UuidUtils.uuidFromAudioDeviceAttributes(ada);
mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address),
- new DeviceInfo(device, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT));
+ new DeviceInfo(device, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT,
+ sensorUuid));
mDeviceBroker.postAccessoryPlugMediaUnmute(device);
setCurrentAudioRouteNameIfPossible(name, /*fromA2dp=*/false);
}
@@ -1380,6 +1919,8 @@ public class AudioDeviceInventory {
final int maxIndex = mDeviceBroker.getMaxVssVolumeForStream(streamType);
mDeviceBroker.postSetLeAudioVolumeIndex(leAudioVolIndex, maxIndex, streamType);
mDeviceBroker.postApplyVolumeOnDevice(streamType, device, "makeLeAudioDeviceAvailable");
+
+ updateBluetoothPreferredModes_l(btInfo.mDevice /*connectedDevice*/);
}
@GuardedBy("mDevicesLock")
@@ -1404,6 +1945,8 @@ public class AudioDeviceInventory {
}
setCurrentAudioRouteNameIfPossible(null, false /*fromA2dp*/);
+ updateBluetoothPreferredModes_l(null /*connectedDevice*/);
+ purgeDevicesRoles_l();
}
@GuardedBy("mDevicesLock")
@@ -1739,18 +2282,6 @@ public class AudioDeviceInventory {
}
}
- /* package */ AudioDeviceAttributes getDeviceOfType(int type) {
- synchronized (mDevicesLock) {
- for (DeviceInfo di : mConnectedDevices.values()) {
- if (di.mDeviceType == type) {
- return new AudioDeviceAttributes(
- di.mDeviceType, di.mDeviceAddress, di.mDeviceName);
- }
- }
- }
- return null;
- }
-
//----------------------------------------------------------
// For tests only
@@ -1761,10 +2292,12 @@ public class AudioDeviceInventory {
*/
@VisibleForTesting
public boolean isA2dpDeviceConnected(@NonNull BluetoothDevice device) {
- final String key = DeviceInfo.makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
- device.getAddress());
- synchronized (mDevicesLock) {
- return (mConnectedDevices.get(key) != null);
+ for (DeviceInfo di : getConnectedDevicesOfTypes(
+ Sets.newHashSet(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP))) {
+ if (di.mDeviceAddress.equals(device.getAddress())) {
+ return true;
+ }
}
+ return false;
}
}
diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
index d066340c42b2..43438942a060 100644
--- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java
+++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
@@ -445,7 +445,7 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback,
}
/**
- * Same as {@link AudioSystem#removeDevicesRoleForCapturePreset(int, int, int[], String[])}
+ * Same as {@link AudioSystem#removeDevicesRoleForCapturePreset(int, int, List)}
* @param capturePreset
* @param role
* @param devicesToRemove
@@ -458,6 +458,19 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback,
}
/**
+ * Same as {@link AudioSystem#addDevicesRoleForCapturePreset(int, int, List)}
+ * @param capturePreset the capture preset to configure
+ * @param role the role of the devices
+ * @param devices the list of devices to be added as role for the given capture preset
+ * @return {@link #SUCCESS} if successfully added
+ */
+ public int addDevicesRoleForCapturePreset(
+ int capturePreset, int role, @NonNull List<AudioDeviceAttributes> devices) {
+ invalidateRoutingCache();
+ return AudioSystem.addDevicesRoleForCapturePreset(capturePreset, role, devices);
+ }
+
+ /**
* Same as {@link AudioSystem#}
* @param capturePreset
* @param role
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 8c27c3ecfd87..e46c3cc4a285 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -33,6 +33,7 @@ import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.BluetoothProfileConnectionInfo;
import android.os.Binder;
+import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -150,60 +151,12 @@ public class BtHelper {
}
}
- //----------------------------------------------------------------------
- /*package*/ static class BluetoothA2dpDeviceInfo {
- private final @NonNull BluetoothDevice mBtDevice;
- private final int mVolume;
- private final @AudioSystem.AudioFormatNativeEnumForBtCodec int mCodec;
-
- BluetoothA2dpDeviceInfo(@NonNull BluetoothDevice btDevice) {
- this(btDevice, -1, AudioSystem.AUDIO_FORMAT_DEFAULT);
- }
-
- BluetoothA2dpDeviceInfo(@NonNull BluetoothDevice btDevice, int volume, int codec) {
- mBtDevice = btDevice;
- mVolume = volume;
- mCodec = codec;
- }
-
- public @NonNull BluetoothDevice getBtDevice() {
- return mBtDevice;
- }
-
- public int getVolume() {
- return mVolume;
- }
-
- public @AudioSystem.AudioFormatNativeEnumForBtCodec int getCodec() {
- return mCodec;
- }
-
- // redefine equality op so we can match messages intended for this device
- @Override
- public boolean equals(Object o) {
- if (o == null) {
- return false;
- }
- if (this == o) {
- return true;
- }
- if (o instanceof BluetoothA2dpDeviceInfo) {
- return mBtDevice.equals(((BluetoothA2dpDeviceInfo) o).getBtDevice());
- }
- return false;
- }
-
-
- }
-
// A2DP device events
/*package*/ static final int EVENT_DEVICE_CONFIG_CHANGE = 0;
- /*package*/ static final int EVENT_ACTIVE_DEVICE_CHANGE = 1;
- /*package*/ static String a2dpDeviceEventToString(int event) {
+ /*package*/ static String deviceEventToString(int event) {
switch (event) {
case EVENT_DEVICE_CONFIG_CHANGE: return "DEVICE_CONFIG_CHANGE";
- case EVENT_ACTIVE_DEVICE_CHANGE: return "ACTIVE_DEVICE_CHANGE";
default:
return new String("invalid event:" + event);
}
@@ -620,11 +573,12 @@ public class BtHelper {
return btHeadsetDeviceToAudioDevice(mBluetoothHeadsetDevice);
}
- private AudioDeviceAttributes btHeadsetDeviceToAudioDevice(BluetoothDevice btDevice) {
+ private static AudioDeviceAttributes btHeadsetDeviceToAudioDevice(BluetoothDevice btDevice) {
if (btDevice == null) {
return new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, "");
}
String address = btDevice.getAddress();
+ String name = getName(btDevice);
if (!BluetoothAdapter.checkBluetoothAddress(address)) {
address = "";
}
@@ -646,7 +600,7 @@ public class BtHelper {
+ " btClass: " + (btClass == null ? "Unknown" : btClass)
+ " nativeType: " + nativeType + " address: " + address);
}
- return new AudioDeviceAttributes(nativeType, address);
+ return new AudioDeviceAttributes(nativeType, address, name);
}
private boolean handleBtScoActiveDeviceChange(BluetoothDevice btDevice, boolean isActive) {
@@ -655,12 +609,9 @@ public class BtHelper {
}
int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
AudioDeviceAttributes audioDevice = btHeadsetDeviceToAudioDevice(btDevice);
- String btDeviceName = getName(btDevice);
boolean result = false;
if (isActive) {
- result |= mDeviceBroker.handleDeviceConnection(new AudioDeviceAttributes(
- audioDevice.getInternalType(), audioDevice.getAddress(), btDeviceName),
- isActive);
+ result |= mDeviceBroker.handleDeviceConnection(audioDevice, isActive, btDevice);
} else {
int[] outDeviceTypes = {
AudioSystem.DEVICE_OUT_BLUETOOTH_SCO,
@@ -669,14 +620,14 @@ public class BtHelper {
};
for (int outDeviceType : outDeviceTypes) {
result |= mDeviceBroker.handleDeviceConnection(new AudioDeviceAttributes(
- outDeviceType, audioDevice.getAddress(), btDeviceName),
- isActive);
+ outDeviceType, audioDevice.getAddress(), audioDevice.getName()),
+ isActive, btDevice);
}
}
// handleDeviceConnection() && result to make sure the method get executed
result = mDeviceBroker.handleDeviceConnection(new AudioDeviceAttributes(
- inDevice, audioDevice.getAddress(), btDeviceName),
- isActive) && result;
+ inDevice, audioDevice.getAddress(), audioDevice.getName()),
+ isActive, btDevice) && result;
return result;
}
@@ -973,6 +924,30 @@ public class BtHelper {
}
}
+ /*package */ static int getProfileFromType(int deviceType) {
+ if (AudioSystem.isBluetoothA2dpOutDevice(deviceType)) {
+ return BluetoothProfile.A2DP;
+ } else if (AudioSystem.isBluetoothScoDevice(deviceType)) {
+ return BluetoothProfile.HEADSET;
+ } else if (AudioSystem.isBluetoothLeDevice(deviceType)) {
+ return BluetoothProfile.LE_AUDIO;
+ }
+ return 0; // 0 is not a valid profile
+ }
+
+ /*package */ static Bundle getPreferredAudioProfiles(String address) {
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ return adapter.getPreferredAudioProfiles(adapter.getRemoteDevice(address));
+ }
+
+ /**
+ * Notifies Bluetooth framework that new preferred audio profiles for Bluetooth devices
+ * have been applied.
+ */
+ public static void onNotifyPreferredAudioProfileApplied(BluetoothDevice btDevice) {
+ BluetoothAdapter.getDefaultAdapter().notifyActiveDeviceChangeApplied(btDevice);
+ }
+
/**
* Returns the string equivalent for the btDeviceClass class.
*/
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 1dc2725feb1b..c678a92af13a 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -85,6 +85,7 @@ import android.net.NetworkScore;
import android.net.NetworkSpecifier;
import android.net.RouteInfo;
import android.net.TelephonyNetworkSpecifier;
+import android.net.TransportInfo;
import android.net.UidRangeParcel;
import android.net.UnderlyingNetworkInfo;
import android.net.Uri;
@@ -107,6 +108,8 @@ import android.net.ipsec.ike.exceptions.IkeNetworkLostException;
import android.net.ipsec.ike.exceptions.IkeNonProtocolException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
import android.net.ipsec.ike.exceptions.IkeTimeoutException;
+import android.net.vcn.VcnGatewayConnectionConfig;
+import android.net.vcn.VcnTransportInfo;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
@@ -453,22 +456,22 @@ public class Vpn {
private static class CarrierConfigInfo {
public final String mccMnc;
- public final int keepaliveDelayMs;
+ public final int keepaliveDelaySec;
public final int encapType;
public final int ipVersion;
- CarrierConfigInfo(String mccMnc, int keepaliveDelayMs,
+ CarrierConfigInfo(String mccMnc, int keepaliveDelaySec,
int encapType,
int ipVersion) {
this.mccMnc = mccMnc;
- this.keepaliveDelayMs = keepaliveDelayMs;
+ this.keepaliveDelaySec = keepaliveDelaySec;
this.encapType = encapType;
this.ipVersion = ipVersion;
}
@Override
public String toString() {
- return "CarrierConfigInfo(" + mccMnc + ") [keepaliveDelayMs=" + keepaliveDelayMs
+ return "CarrierConfigInfo(" + mccMnc + ") [keepaliveDelaySec=" + keepaliveDelaySec
+ ", encapType=" + encapType + ", ipVersion=" + ipVersion + "]";
}
}
@@ -3556,39 +3559,63 @@ public class Vpn {
}
private int guessEspIpVersionForNetwork() {
- final CarrierConfigInfo carrierconfig = getCarrierConfig();
+ if (mUnderlyingNetworkCapabilities.getTransportInfo() instanceof VcnTransportInfo) {
+ Log.d(TAG, "Running over VCN, esp IP version is auto");
+ return ESP_IP_VERSION_AUTO;
+ }
+ final CarrierConfigInfo carrierconfig = getCarrierConfigForUnderlyingNetwork();
final int ipVersion = (carrierconfig != null)
? carrierconfig.ipVersion : ESP_IP_VERSION_AUTO;
if (carrierconfig != null) {
- Log.d(TAG, "Get customized IP version(" + ipVersion + ") on SIM("
+ Log.d(TAG, "Get customized IP version (" + ipVersion + ") on SIM (mccmnc="
+ carrierconfig.mccMnc + ")");
}
return ipVersion;
}
private int guessEspEncapTypeForNetwork() {
- final CarrierConfigInfo carrierconfig = getCarrierConfig();
+ if (mUnderlyingNetworkCapabilities.getTransportInfo() instanceof VcnTransportInfo) {
+ Log.d(TAG, "Running over VCN, encap type is auto");
+ return ESP_ENCAP_TYPE_AUTO;
+ }
+ final CarrierConfigInfo carrierconfig = getCarrierConfigForUnderlyingNetwork();
final int encapType = (carrierconfig != null)
? carrierconfig.encapType : ESP_ENCAP_TYPE_AUTO;
if (carrierconfig != null) {
- Log.d(TAG, "Get customized encap type(" + encapType + ") on SIM("
+ Log.d(TAG, "Get customized encap type (" + encapType + ") on SIM (mccmnc="
+ carrierconfig.mccMnc + ")");
}
return encapType;
}
+
private int guessNattKeepaliveTimerForNetwork() {
- final CarrierConfigInfo carrierconfig = getCarrierConfig();
- final int natKeepalive = (carrierconfig != null)
- ? carrierconfig.keepaliveDelayMs : AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
+ final TransportInfo transportInfo = mUnderlyingNetworkCapabilities.getTransportInfo();
+ if (transportInfo instanceof VcnTransportInfo) {
+ final int nattKeepaliveSec =
+ ((VcnTransportInfo) transportInfo).getMinUdpPort4500NatTimeoutSeconds();
+ Log.d(TAG, "Running over VCN, keepalive timer : " + nattKeepaliveSec + "s");
+ if (VcnGatewayConnectionConfig.MIN_UDP_PORT_4500_NAT_TIMEOUT_UNSET
+ != nattKeepaliveSec) {
+ return nattKeepaliveSec;
+ }
+ // else fall back to carrier config, if any
+ }
+ final CarrierConfigInfo carrierconfig = getCarrierConfigForUnderlyingNetwork();
+ final int nattKeepaliveSec = (carrierconfig != null)
+ ? carrierconfig.keepaliveDelaySec : AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
if (carrierconfig != null) {
- Log.d(TAG, "Get customized keepalive(" + natKeepalive + ") on SIM("
+ Log.d(TAG, "Get customized keepalive (" + nattKeepaliveSec + "s) on SIM (mccmnc="
+ carrierconfig.mccMnc + ")");
}
- return natKeepalive;
+ return nattKeepaliveSec;
}
- private CarrierConfigInfo getCarrierConfig() {
+ /**
+ * Returns the carrier config for the underlying network, or null if not a cell network.
+ */
+ @Nullable
+ private CarrierConfigInfo getCarrierConfigForUnderlyingNetwork() {
final int subId = getCellSubIdForNetworkCapabilities(mUnderlyingNetworkCapabilities);
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
Log.d(TAG, "Underlying network is not a cellular network");
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 29c5adaea844..97e7f6f41703 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1148,12 +1148,21 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
info.userId = userId;
info.installerPackageName = mInstallSource.mInstallerPackageName;
info.installerAttributionTag = mInstallSource.mInstallerAttributionTag;
+ info.resolvedBaseCodePath = null;
if (mContext.checkCallingOrSelfPermission(
Manifest.permission.READ_INSTALLED_SESSION_PATHS)
- == PackageManager.PERMISSION_GRANTED && mResolvedBaseFile != null) {
- info.resolvedBaseCodePath = mResolvedBaseFile.getAbsolutePath();
- } else {
- info.resolvedBaseCodePath = null;
+ == PackageManager.PERMISSION_GRANTED) {
+ File file = mResolvedBaseFile;
+ if (file == null) {
+ // Try to guess mResolvedBaseFile file.
+ final List<File> addedFiles = getAddedApksLocked();
+ if (addedFiles.size() > 0) {
+ file = addedFiles.get(0);
+ }
+ }
+ if (file != null) {
+ info.resolvedBaseCodePath = file.getAbsolutePath();
+ }
}
info.progress = progress;
info.sealed = mSealed;
@@ -1355,9 +1364,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@GuardedBy("mLock")
private String[] getStageDirContentsLocked() {
+ if (stageDir == null) {
+ return EmptyArray.STRING;
+ }
String[] result = stageDir.list();
if (result == null) {
- result = EmptyArray.STRING;
+ return EmptyArray.STRING;
}
return result;
}
diff --git a/services/core/java/com/android/server/pm/UserJourneyLogger.java b/services/core/java/com/android/server/pm/UserJourneyLogger.java
new file mode 100644
index 000000000000..f48a1669c259
--- /dev/null
+++ b/services/core/java/com/android/server/pm/UserJourneyLogger.java
@@ -0,0 +1,552 @@
+/*
+ * 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.pm;
+
+import static android.os.UserManager.USER_TYPE_FULL_DEMO;
+import static android.os.UserManager.USER_TYPE_FULL_GUEST;
+import static android.os.UserManager.USER_TYPE_FULL_RESTRICTED;
+import static android.os.UserManager.USER_TYPE_FULL_SECONDARY;
+import static android.os.UserManager.USER_TYPE_FULL_SYSTEM;
+import static android.os.UserManager.USER_TYPE_PROFILE_CLONE;
+import static android.os.UserManager.USER_TYPE_PROFILE_MANAGED;
+import static android.os.UserManager.USER_TYPE_SYSTEM_HEADLESS;
+
+import static com.android.internal.util.FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__UNKNOWN;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.content.pm.UserInfo;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * This class is logging User Lifecycle statsd events and synchronise User Lifecycle Journeys
+ * by making sure all events are called in correct order and errors are reported in case of
+ * unexpected journeys. This class also makes sure that all user sub-journeys are logged so
+ * for example User Switch also log User Start Journey.
+ */
+public class UserJourneyLogger {
+
+ public static final int ERROR_CODE_INVALID_SESSION_ID = 0;
+ public static final int ERROR_CODE_UNSPECIFIED = -1;
+ /*
+ * Possible reasons for ERROR_CODE_INCOMPLETE_OR_TIMEOUT to occur:
+ * - A user switch journey is received while another user switch journey is in
+ * process for the same user.
+ * - A user switch journey is received while user start journey is in process for
+ * the same user.
+ * - A user start journey is received while another user start journey is in process
+ * for the same user.
+ * In all cases potentially an incomplete, timed-out session or multiple
+ * simultaneous requests. It is not possible to keep track of multiple sessions for
+ * the same user, so previous session is abandoned.
+ */
+ public static final int ERROR_CODE_INCOMPLETE_OR_TIMEOUT = 2;
+ public static final int ERROR_CODE_ABORTED = 3;
+ public static final int ERROR_CODE_NULL_USER_INFO = 4;
+ public static final int ERROR_CODE_USER_ALREADY_AN_ADMIN = 5;
+ public static final int ERROR_CODE_USER_IS_NOT_AN_ADMIN = 6;
+
+ @IntDef(prefix = {"ERROR_CODE"}, value = {
+ ERROR_CODE_UNSPECIFIED,
+ ERROR_CODE_INCOMPLETE_OR_TIMEOUT,
+ ERROR_CODE_ABORTED,
+ ERROR_CODE_NULL_USER_INFO,
+ ERROR_CODE_USER_ALREADY_AN_ADMIN,
+ ERROR_CODE_USER_IS_NOT_AN_ADMIN,
+ ERROR_CODE_INVALID_SESSION_ID
+ })
+ public @interface UserJourneyErrorCode {
+ }
+
+ // The various user journeys, defined in the UserLifecycleJourneyReported atom for statsd
+ public static final int USER_JOURNEY_UNKNOWN =
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__UNKNOWN;
+ public static final int USER_JOURNEY_USER_SWITCH_FG =
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_SWITCH_FG;
+ public static final int USER_JOURNEY_USER_SWITCH_UI =
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_SWITCH_UI;
+ public static final int USER_JOURNEY_USER_START =
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_START;
+ public static final int USER_JOURNEY_USER_CREATE =
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_CREATE;
+ public static final int USER_JOURNEY_USER_STOP =
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_STOP;
+ public static final int USER_JOURNEY_USER_REMOVE =
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_REMOVE;
+ public static final int USER_JOURNEY_GRANT_ADMIN =
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__GRANT_ADMIN;
+ public static final int USER_JOURNEY_REVOKE_ADMIN =
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__REVOKE_ADMIN;
+
+ @IntDef(prefix = {"USER_JOURNEY"}, value = {
+ USER_JOURNEY_UNKNOWN,
+ USER_JOURNEY_USER_SWITCH_FG,
+ USER_JOURNEY_USER_SWITCH_UI,
+ USER_JOURNEY_USER_START,
+ USER_JOURNEY_USER_STOP,
+ USER_JOURNEY_USER_CREATE,
+ USER_JOURNEY_USER_REMOVE,
+ USER_JOURNEY_GRANT_ADMIN,
+ USER_JOURNEY_REVOKE_ADMIN
+ })
+ public @interface UserJourney {
+ }
+
+
+ // The various user lifecycle events, defined in the UserLifecycleEventOccurred atom for statsd
+ public static final int USER_LIFECYCLE_EVENT_UNKNOWN =
+ USER_LIFECYCLE_EVENT_OCCURRED__EVENT__UNKNOWN;
+ public static final int USER_LIFECYCLE_EVENT_SWITCH_USER =
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__SWITCH_USER;
+ public static final int USER_LIFECYCLE_EVENT_START_USER =
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__START_USER;
+ public static final int USER_LIFECYCLE_EVENT_CREATE_USER =
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__CREATE_USER;
+ public static final int USER_LIFECYCLE_EVENT_REMOVE_USER =
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__REMOVE_USER;
+ public static final int USER_LIFECYCLE_EVENT_USER_RUNNING_LOCKED =
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__USER_RUNNING_LOCKED;
+ public static final int USER_LIFECYCLE_EVENT_UNLOCKING_USER =
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__UNLOCKING_USER;
+ public static final int USER_LIFECYCLE_EVENT_UNLOCKED_USER =
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__UNLOCKED_USER;
+ public static final int USER_LIFECYCLE_EVENT_STOP_USER =
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__STOP_USER;
+ public static final int USER_LIFECYCLE_EVENT_GRANT_ADMIN =
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__GRANT_ADMIN;
+ public static final int USER_LIFECYCLE_EVENT_REVOKE_ADMIN =
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__REVOKE_ADMIN;
+
+ @IntDef(prefix = {"USER_LIFECYCLE_EVENT"}, value = {
+ USER_LIFECYCLE_EVENT_UNKNOWN,
+ USER_LIFECYCLE_EVENT_SWITCH_USER,
+ USER_LIFECYCLE_EVENT_START_USER,
+ USER_LIFECYCLE_EVENT_CREATE_USER,
+ USER_LIFECYCLE_EVENT_REMOVE_USER,
+ USER_LIFECYCLE_EVENT_USER_RUNNING_LOCKED,
+ USER_LIFECYCLE_EVENT_UNLOCKING_USER,
+ USER_LIFECYCLE_EVENT_UNLOCKED_USER,
+ USER_LIFECYCLE_EVENT_STOP_USER,
+ USER_LIFECYCLE_EVENT_GRANT_ADMIN,
+ USER_LIFECYCLE_EVENT_REVOKE_ADMIN
+ })
+ public @interface UserLifecycleEvent {
+ }
+
+ // User lifecycle event state, defined in the UserLifecycleEventOccurred atom for statsd
+ public static final int EVENT_STATE_BEGIN =
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__BEGIN;
+ public static final int EVENT_STATE_FINISH =
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__FINISH;
+ public static final int EVENT_STATE_NONE =
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__NONE;
+ public static final int EVENT_STATE_CANCEL =
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__CANCEL;
+ public static final int EVENT_STATE_ERROR =
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__ERROR;
+
+ @IntDef(prefix = {"EVENT_STATE"}, value = {
+ EVENT_STATE_BEGIN,
+ EVENT_STATE_FINISH,
+ EVENT_STATE_NONE,
+ EVENT_STATE_CANCEL,
+ EVENT_STATE_ERROR,
+ })
+ public @interface UserLifecycleEventState {
+ }
+
+ private static final int USER_ID_KEY_MULTIPLICATION = 100;
+
+ private final Object mLock = new Object();
+
+ /**
+ * {@link UserIdInt} and {@link UserJourney} to {@link UserJourneySession} mapping used for
+ * statsd logging for the UserLifecycleJourneyReported and UserLifecycleEventOccurred atoms.
+ */
+ @GuardedBy("mLock")
+ private final SparseArray<UserJourneySession> mUserIdToUserJourneyMap = new SparseArray<>();
+
+ /**
+ * Returns event equivalent of given journey
+ */
+ @UserLifecycleEvent
+ private static int journeyToEvent(@UserJourney int journey) {
+ switch (journey) {
+ case USER_JOURNEY_USER_SWITCH_UI:
+ case USER_JOURNEY_USER_SWITCH_FG:
+ return USER_LIFECYCLE_EVENT_SWITCH_USER;
+ case USER_JOURNEY_USER_START:
+ return USER_LIFECYCLE_EVENT_START_USER;
+ case USER_JOURNEY_USER_CREATE:
+ return USER_LIFECYCLE_EVENT_CREATE_USER;
+ case USER_JOURNEY_USER_STOP:
+ return USER_LIFECYCLE_EVENT_STOP_USER;
+ case USER_JOURNEY_USER_REMOVE:
+ return USER_LIFECYCLE_EVENT_REMOVE_USER;
+ case USER_JOURNEY_GRANT_ADMIN:
+ return USER_LIFECYCLE_EVENT_GRANT_ADMIN;
+ case USER_JOURNEY_REVOKE_ADMIN:
+ return USER_LIFECYCLE_EVENT_REVOKE_ADMIN;
+ default:
+ return USER_LIFECYCLE_EVENT_UNKNOWN;
+ }
+ }
+
+ /**
+ * Returns the enum defined in the statsd UserLifecycleJourneyReported atom corresponding to
+ * the user type.
+ * Changes to this method require changes in CTS file
+ * com.android.cts.packagemanager.stats.device.UserInfoUtil
+ * which is duplicate for CTS tests purposes.
+ */
+ public static int getUserTypeForStatsd(@NonNull String userType) {
+ switch (userType) {
+ case USER_TYPE_FULL_SYSTEM:
+ return FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SYSTEM;
+ case USER_TYPE_FULL_SECONDARY:
+ return FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY;
+ case USER_TYPE_FULL_GUEST:
+ return FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_GUEST;
+ case USER_TYPE_FULL_DEMO:
+ return FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_DEMO;
+ case USER_TYPE_FULL_RESTRICTED:
+ return FrameworkStatsLog
+ .USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_RESTRICTED;
+ case USER_TYPE_PROFILE_MANAGED:
+ return FrameworkStatsLog
+ .USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__PROFILE_MANAGED;
+ case USER_TYPE_SYSTEM_HEADLESS:
+ return FrameworkStatsLog
+ .USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__SYSTEM_HEADLESS;
+ case USER_TYPE_PROFILE_CLONE:
+ return FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__PROFILE_CLONE;
+ default:
+ return FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__TYPE_UNKNOWN;
+ }
+ }
+
+ /**
+ * Map error code to the event finish state.
+ */
+ @UserLifecycleEventState
+ private static int errorToFinishState(@UserJourneyErrorCode int errorCode) {
+ switch (errorCode) {
+ case ERROR_CODE_ABORTED:
+ return EVENT_STATE_CANCEL;
+ case ERROR_CODE_UNSPECIFIED:
+ return EVENT_STATE_FINISH;
+ default:
+ return EVENT_STATE_ERROR;
+ }
+ }
+
+ /**
+ * Simply logging USER_LIFECYCLE_JOURNEY_REPORTED if session exists.
+ * If session does not exist then it logs ERROR_CODE_INVALID_SESSION_ID
+ */
+ @VisibleForTesting
+ public void logUserLifecycleJourneyReported(@Nullable UserJourneySession session,
+ @UserJourney int journey, @UserIdInt int originalUserId, @UserIdInt int targetUserId,
+ int userType, int userFlags, @UserJourneyErrorCode int errorCode) {
+ if (session == null) {
+ writeUserLifecycleJourneyReported(-1, journey, originalUserId, targetUserId,
+ userType, userFlags, ERROR_CODE_INVALID_SESSION_ID);
+ } else {
+ writeUserLifecycleJourneyReported(
+ session.mSessionId, journey, originalUserId, targetUserId, userType, userFlags,
+ errorCode);
+ }
+ }
+
+ /**
+ * Helper method for spy testing
+ */
+ @VisibleForTesting
+ public void writeUserLifecycleJourneyReported(long sessionId, int journey, int originalUserId,
+ int targetUserId, int userType, int userFlags, int errorCode) {
+ FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED,
+ sessionId, journey, originalUserId, targetUserId, userType, userFlags,
+ errorCode);
+ }
+
+ /**
+ * Simply logging USER_LIFECYCLE_EVENT_OCCURRED if session exists.
+ * If session does not exist then it logs ERROR_CODE_INVALID_SESSION_ID
+ * and EVENT_STATE_ERROR
+ */
+ @VisibleForTesting
+ public void logUserLifecycleEventOccurred(UserJourneySession session,
+ @UserIdInt int targetUserId, @UserLifecycleEvent int event,
+ @UserLifecycleEventState int state, @UserJourneyErrorCode int errorCode) {
+ if (session == null) {
+ writeUserLifecycleEventOccurred(-1, targetUserId, event,
+ EVENT_STATE_ERROR, ERROR_CODE_INVALID_SESSION_ID);
+ } else {
+ writeUserLifecycleEventOccurred(session.mSessionId, targetUserId, event, state,
+ errorCode);
+ }
+ }
+
+ /**
+ * Helper method for spy testing
+ */
+ @VisibleForTesting
+ public void writeUserLifecycleEventOccurred(long sessionId, int userId, int event, int state,
+ int errorCode) {
+ FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED,
+ sessionId, userId, event, state, errorCode);
+ }
+
+ /**
+ * statsd helper method for logging the given event for the UserLifecycleEventOccurred statsd
+ * atom. It finds the user journey session for target user id and logs it as that journey.
+ */
+ public void logUserLifecycleEvent(@UserIdInt int userId, @UserLifecycleEvent int event,
+ @UserLifecycleEventState int eventState) {
+ final UserJourneySession userJourneySession = findUserJourneySession(userId);
+ logUserLifecycleEventOccurred(userJourneySession, userId,
+ event, eventState, UserJourneyLogger.ERROR_CODE_UNSPECIFIED);
+ }
+
+ /**
+ * Returns first user session from mUserIdToUserJourneyMap for given user id,
+ * or null if user id was not found in mUserIdToUserJourneyMap.
+ */
+ private @Nullable UserJourneySession findUserJourneySession(@UserIdInt int userId) {
+ synchronized (mLock) {
+ final int keyMapSize = mUserIdToUserJourneyMap.size();
+ for (int i = 0; i < keyMapSize; i++) {
+ int key = mUserIdToUserJourneyMap.keyAt(i);
+ if (key / USER_ID_KEY_MULTIPLICATION == userId) {
+ return mUserIdToUserJourneyMap.get(key);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns unique id for user and journey. For example if user id = 11 and journey = 7
+ * then unique key = 11 * 100 + 7 = 1107
+ */
+ private int getUserJourneyKey(@UserIdInt int targetUserId, @UserJourney int journey) {
+ // We leave 99 for user journeys ids.
+ return (targetUserId * USER_ID_KEY_MULTIPLICATION) + journey;
+ }
+
+ /**
+ * Special use case when user journey incomplete or timeout and current user is unclear
+ */
+ @VisibleForTesting
+ public UserJourneySession finishAndClearIncompleteUserJourney(@UserIdInt int targetUserId,
+ @UserJourney int journey) {
+ synchronized (mLock) {
+ final int key = getUserJourneyKey(targetUserId, journey);
+ final UserJourneySession userJourneySession = mUserIdToUserJourneyMap.get(key);
+ if (userJourneySession != null) {
+ logUserLifecycleEventOccurred(
+ userJourneySession,
+ targetUserId,
+ journeyToEvent(userJourneySession.mJourney),
+ EVENT_STATE_ERROR,
+ UserJourneyLogger.ERROR_CODE_INCOMPLETE_OR_TIMEOUT);
+
+ logUserLifecycleJourneyReported(
+ userJourneySession,
+ journey,
+ /* originalUserId= */ -1,
+ targetUserId,
+ getUserTypeForStatsd(""), -1,
+ ERROR_CODE_INCOMPLETE_OR_TIMEOUT);
+ mUserIdToUserJourneyMap.remove(key);
+
+ return userJourneySession;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Log user journey event and report finishing without error
+ */
+ public UserJourneySession logUserJourneyFinish(@UserIdInt int originalUserId,
+ UserInfo targetUser, @UserJourney int journey) {
+ return logUserJourneyFinishWithError(originalUserId, targetUser, journey,
+ ERROR_CODE_UNSPECIFIED);
+ }
+
+ /**
+ * Special case when it is unknown which user switch journey was used and checking both
+ */
+ @VisibleForTesting
+ public UserJourneySession logUserSwitchJourneyFinish(@UserIdInt int originalUserId,
+ UserInfo targetUser) {
+ synchronized (mLock) {
+ final int key_fg = getUserJourneyKey(targetUser.id, USER_JOURNEY_USER_SWITCH_FG);
+ final int key_ui = getUserJourneyKey(targetUser.id, USER_JOURNEY_USER_SWITCH_UI);
+
+ if (mUserIdToUserJourneyMap.contains(key_fg)) {
+ return logUserJourneyFinish(originalUserId, targetUser,
+ USER_JOURNEY_USER_SWITCH_FG);
+ }
+
+ if (mUserIdToUserJourneyMap.contains(key_ui)) {
+ return logUserJourneyFinish(originalUserId, targetUser,
+ USER_JOURNEY_USER_SWITCH_UI);
+ }
+
+ return null;
+ }
+ }
+
+ /**
+ * Log user journey event and report finishing with error
+ */
+ public UserJourneySession logUserJourneyFinishWithError(@UserIdInt int originalUserId,
+ UserInfo targetUser, @UserJourney int journey, @UserJourneyErrorCode int errorCode) {
+ synchronized (mLock) {
+ final int state = errorToFinishState(errorCode);
+ final int key = getUserJourneyKey(targetUser.id, journey);
+ final UserJourneySession userJourneySession = mUserIdToUserJourneyMap.get(key);
+ if (userJourneySession != null) {
+ logUserLifecycleEventOccurred(
+ userJourneySession, targetUser.id,
+ journeyToEvent(userJourneySession.mJourney),
+ state,
+ errorCode);
+
+ logUserLifecycleJourneyReported(
+ userJourneySession,
+ journey, originalUserId, targetUser.id,
+ getUserTypeForStatsd(targetUser.userType),
+ targetUser.flags,
+ errorCode);
+ mUserIdToUserJourneyMap.remove(key);
+
+ return userJourneySession;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Log event and report finish when user is null. This is edge case when UserInfo
+ * can not be passed because it is null, therefore all information are passed as arguments.
+ */
+ public UserJourneySession logNullUserJourneyError(@UserJourney int journey,
+ @UserIdInt int currentUserId, @UserIdInt int targetUserId, String targetUserType,
+ int targetUserFlags) {
+ synchronized (mLock) {
+ final int key = getUserJourneyKey(targetUserId, journey);
+ final UserJourneySession session = mUserIdToUserJourneyMap.get(key);
+
+ logUserLifecycleEventOccurred(
+ session, targetUserId, journeyToEvent(journey),
+ EVENT_STATE_ERROR,
+ ERROR_CODE_NULL_USER_INFO);
+
+ logUserLifecycleJourneyReported(
+ session, journey, currentUserId, targetUserId,
+ getUserTypeForStatsd(targetUserType), targetUserFlags,
+ ERROR_CODE_NULL_USER_INFO);
+
+ mUserIdToUserJourneyMap.remove(key);
+ return session;
+ }
+ }
+
+ /**
+ * Log for user creation finish event and report. This is edge case when target user id is
+ * different in begin event and finish event as it is unknown what is user id
+ * until it has been created.
+ */
+ public UserJourneySession logUserCreateJourneyFinish(@UserIdInt int originalUserId,
+ UserInfo targetUser) {
+ synchronized (mLock) {
+ // we do not know user id until we create new user which is why we use -1
+ // as user id to create and find session, but we log correct id.
+ final int key = getUserJourneyKey(-1, USER_JOURNEY_USER_CREATE);
+ final UserJourneySession userJourneySession = mUserIdToUserJourneyMap.get(key);
+ if (userJourneySession != null) {
+ logUserLifecycleEventOccurred(
+ userJourneySession, targetUser.id,
+ USER_LIFECYCLE_EVENT_CREATE_USER,
+ EVENT_STATE_FINISH,
+ ERROR_CODE_UNSPECIFIED);
+
+ logUserLifecycleJourneyReported(
+ userJourneySession,
+ USER_JOURNEY_USER_CREATE, originalUserId, targetUser.id,
+ getUserTypeForStatsd(targetUser.userType),
+ targetUser.flags,
+ ERROR_CODE_UNSPECIFIED);
+ mUserIdToUserJourneyMap.remove(key);
+
+ return userJourneySession;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Adds new UserJourneySession to mUserIdToUserJourneyMap and log UserJourneyEvent Begin state
+ */
+ public UserJourneySession logUserJourneyBegin(@UserIdInt int targetId,
+ @UserJourney int journey) {
+ final long newSessionId = ThreadLocalRandom.current().nextLong(1, Long.MAX_VALUE);
+ synchronized (mLock) {
+ final int key = getUserJourneyKey(targetId, journey);
+ final UserJourneySession userJourneySession =
+ new UserJourneySession(newSessionId, journey);
+ mUserIdToUserJourneyMap.append(key, userJourneySession);
+
+ logUserLifecycleEventOccurred(
+ userJourneySession, targetId,
+ journeyToEvent(userJourneySession.mJourney),
+ EVENT_STATE_BEGIN,
+ ERROR_CODE_UNSPECIFIED);
+
+ return userJourneySession;
+ }
+ }
+
+ /**
+ * Helper class to store user journey and session id.
+ *
+ * <p> User journey tracks a chain of user lifecycle events occurring during different user
+ * activities such as user start, user switch, and user creation.
+ */
+ public static class UserJourneySession {
+ public final long mSessionId;
+ @UserJourney
+ public final int mJourney;
+
+ @VisibleForTesting
+ public UserJourneySession(long sessionId, @UserJourney int journey) {
+ mJourney = journey;
+ mSessionId = sessionId;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 5f8efe29459d..b92cdde5910f 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -23,6 +23,15 @@ import static android.os.UserManager.DISALLOW_USER_SWITCH;
import static android.os.UserManager.SYSTEM_USER_MODE_EMULATION_PROPERTY;
import static android.os.UserManager.USER_OPERATION_ERROR_UNKNOWN;
+import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_ABORTED;
+import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_UNSPECIFIED;
+import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_USER_ALREADY_AN_ADMIN;
+import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_USER_IS_NOT_AN_ADMIN;
+import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_GRANT_ADMIN;
+import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_REVOKE_ADMIN;
+import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_CREATE;
+import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_REMOVE;
+
import android.Manifest;
import android.accounts.Account;
import android.accounts.AccountManager;
@@ -162,7 +171,6 @@ import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@@ -519,6 +527,8 @@ public class UserManagerService extends IUserManager.Stub {
@GuardedBy("mUserLifecycleListeners")
private final ArrayList<UserLifecycleListener> mUserLifecycleListeners = new ArrayList<>();
+ private final UserJourneyLogger mUserJourneyLogger = new UserJourneyLogger();
+
private final LockPatternUtils mLockPatternUtils;
private final String ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK =
@@ -1580,45 +1590,56 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public void setUserAdmin(@UserIdInt int userId) {
checkManageUserAndAcrossUsersFullPermission("set user admin");
- final long sessionId = logGrantAdminJourneyBegin(userId);
+ mUserJourneyLogger.logUserJourneyBegin(userId, USER_JOURNEY_GRANT_ADMIN);
UserInfo info;
synchronized (mPackagesLock) {
synchronized (mUsersLock) {
info = getUserInfoLU(userId);
}
- if (info == null || info.isAdmin()) {
- // Exit if no user found with that id, or the user is already an Admin.
- logUserJourneyError(sessionId,
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__GRANT_ADMIN,
- userId);
+ if (info == null) {
+ // Exit if no user found with that id,
+ mUserJourneyLogger.logNullUserJourneyError(USER_JOURNEY_GRANT_ADMIN,
+ getCurrentUserId(), userId, /* userType */ "", /* userFlags */ -1);
+ return;
+ } else if (info.isAdmin()) {
+ // Exit if the user is already an Admin.
+ mUserJourneyLogger.logUserJourneyFinishWithError(getCurrentUserId(), info,
+ USER_JOURNEY_GRANT_ADMIN, ERROR_CODE_USER_ALREADY_AN_ADMIN);
return;
}
info.flags ^= UserInfo.FLAG_ADMIN;
writeUserLP(getUserDataLU(info.id));
}
- logGrantAdminJourneyFinish(sessionId, userId, info.userType, info.flags);
+ mUserJourneyLogger.logUserJourneyFinishWithError(getCurrentUserId(), info,
+ USER_JOURNEY_GRANT_ADMIN, ERROR_CODE_UNSPECIFIED);
}
@Override
public void revokeUserAdmin(@UserIdInt int userId) {
checkManageUserAndAcrossUsersFullPermission("revoke admin privileges");
- final long sessionId = logRevokeAdminJourneyBegin(userId);
+ mUserJourneyLogger.logUserJourneyBegin(userId, USER_JOURNEY_REVOKE_ADMIN);
UserData user;
synchronized (mPackagesLock) {
synchronized (mUsersLock) {
user = getUserDataLU(userId);
- if (user == null || !user.info.isAdmin()) {
- // Exit if no user found with that id, or the user is not an Admin.
- logUserJourneyError(sessionId, FrameworkStatsLog
- .USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__REVOKE_ADMIN,
- userId);
+ if (user == null) {
+ // Exit if no user found with that id
+ mUserJourneyLogger.logNullUserJourneyError(
+ USER_JOURNEY_REVOKE_ADMIN,
+ getCurrentUserId(), userId, "", -1);
+ return;
+ } else if (!user.info.isAdmin()) {
+ // Exit if no user is not an Admin.
+ mUserJourneyLogger.logUserJourneyFinishWithError(getCurrentUserId(), user.info,
+ USER_JOURNEY_REVOKE_ADMIN, ERROR_CODE_USER_IS_NOT_AN_ADMIN);
return;
}
user.info.flags ^= UserInfo.FLAG_ADMIN;
writeUserLP(user);
}
}
- logRevokeAdminJourneyFinish(sessionId, userId, user.info.userType, user.info.flags);
+ mUserJourneyLogger.logUserJourneyFinishWithError(getCurrentUserId(), user.info,
+ USER_JOURNEY_REVOKE_ADMIN, ERROR_CODE_UNSPECIFIED);
}
/**
@@ -4700,16 +4721,20 @@ public class UserManagerService extends IUserManager.Stub {
final int noneUserId = -1;
final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
t.traceBegin("createUser-" + flags);
- final long sessionId = logUserCreateJourneyBegin(noneUserId);
+ mUserJourneyLogger.logUserJourneyBegin(noneUserId, USER_JOURNEY_USER_CREATE);
UserInfo newUser = null;
try {
newUser = createUserInternalUncheckedNoTracing(name, userType, flags, parentId,
preCreate, disallowedPackages, t, token);
return newUser;
} finally {
- logUserCreateJourneyFinish(sessionId,
- newUser != null ? newUser.id : noneUserId, userType, flags,
- newUser != null);
+ if (newUser != null) {
+ mUserJourneyLogger.logUserCreateJourneyFinish(getCurrentUserId(), newUser);
+ } else {
+ mUserJourneyLogger.logNullUserJourneyError(
+ USER_JOURNEY_USER_CREATE,
+ getCurrentUserId(), noneUserId, userType, flags);
+ }
t.traceEnd();
}
}
@@ -5198,137 +5223,6 @@ public class UserManagerService extends IUserManager.Stub {
&& !userTypeDetails.getName().equals(UserManager.USER_TYPE_FULL_RESTRICTED);
}
- private long logUserCreateJourneyBegin(@UserIdInt int userId) {
- return logUserJourneyBegin(
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_CREATE,
- userId);
- }
-
- private void logUserCreateJourneyFinish(long sessionId, @UserIdInt int userId, String userType,
- @UserInfoFlag int flags, boolean finish) {
- logUserJourneyFinish(sessionId,
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_CREATE,
- userId, userType, flags, finish);
- }
-
- private long logUserRemoveJourneyBegin(@UserIdInt int userId) {
- return logUserJourneyBegin(
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_REMOVE,
- userId);
- }
-
- private void logUserRemoveJourneyFinish(long sessionId, @UserIdInt int userId, String userType,
- @UserInfoFlag int flags, boolean finish) {
- logUserJourneyFinish(sessionId,
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_REMOVE,
- userId, userType, flags, finish);
- }
-
- private long logGrantAdminJourneyBegin(@UserIdInt int userId) {
- return logUserJourneyBegin(
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__GRANT_ADMIN,
- userId);
- }
-
- private void logGrantAdminJourneyFinish(long sessionId, @UserIdInt int userId, String userType,
- @UserInfoFlag int flags) {
- logUserJourneyFinish(sessionId,
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__GRANT_ADMIN,
- userId, userType, flags, true);
- }
-
- private long logRevokeAdminJourneyBegin(@UserIdInt int userId) {
- return logUserJourneyBegin(
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__REVOKE_ADMIN,
- userId);
- }
-
- private void logRevokeAdminJourneyFinish(long sessionId, @UserIdInt int userId, String userType,
- @UserInfoFlag int flags) {
- logUserJourneyFinish(sessionId,
- FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__REVOKE_ADMIN,
- userId, userType, flags, true);
- }
-
- private void logUserJourneyFinish(long sessionId, int journey, @UserIdInt int userId,
- String userType, @UserInfoFlag int flags, boolean finish) {
-
- // log the journey atom with the user metadata
- FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED, sessionId,
- journey, /* origin_user= */ getCurrentUserId(), userId,
- UserManager.getUserTypeForStatsd(userType), flags);
-
- int event;
- switch (journey) {
- case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_CREATE:
- event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__CREATE_USER;
- break;
- case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_REMOVE:
- event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__REMOVE_USER;
- break;
- case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__GRANT_ADMIN:
- event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__GRANT_ADMIN;
- break;
- case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__REVOKE_ADMIN:
- event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__REVOKE_ADMIN;
- break;
- default:
- throw new IllegalArgumentException("Journey " + journey + " not expected.");
- }
- FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED, sessionId, userId,
- event,
- finish ? FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__FINISH
- : FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__NONE);
- }
-
- private long logUserJourneyBegin(int journey, @UserIdInt int userId) {
- final long sessionId = ThreadLocalRandom.current().nextLong(1, Long.MAX_VALUE);
-
- // log the event atom to indicate the event start
- int event;
- switch (journey) {
- case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_CREATE:
- event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__CREATE_USER;
- break;
- case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__USER_REMOVE:
- event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__REMOVE_USER;
- break;
- case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__GRANT_ADMIN:
- event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__GRANT_ADMIN;
- break;
- case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__REVOKE_ADMIN:
- event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__REVOKE_ADMIN;
- break;
- default:
- throw new IllegalArgumentException("Journey " + journey + " not expected.");
- }
-
- FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED, sessionId, userId,
- event, FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__BEGIN);
- return sessionId;
- }
-
- private void logUserJourneyError(long sessionId, int journey, @UserIdInt int userId) {
-
- // log the journey atom with the user metadata
- FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED, sessionId,
- journey, /* origin_user= */ getCurrentUserId(), userId);
-
- int event;
- switch (journey) {
- case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__GRANT_ADMIN:
- event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__GRANT_ADMIN;
- break;
- case FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__JOURNEY__REVOKE_ADMIN:
- event = FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__REVOKE_ADMIN;
- break;
- default:
- throw new IllegalArgumentException("Journey " + journey + " not expected.");
- }
- FrameworkStatsLog.write(FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED, sessionId, userId,
- event, FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__STATE__ERROR);
- }
-
/** Register callbacks for statsd pulled atoms. */
private void registerStatsCallbacks() {
final StatsManager statsManager = mContext.getSystemService(StatsManager.class);
@@ -5352,7 +5246,8 @@ public class UserManagerService extends IUserManager.Stub {
if (size > 1) {
for (int idx = 0; idx < size; idx++) {
final UserInfo user = users.get(idx);
- final int userTypeStandard = UserManager.getUserTypeForStatsd(user.userType);
+ final int userTypeStandard = mUserJourneyLogger
+ .getUserTypeForStatsd(user.userType);
final String userTypeCustom = (userTypeStandard == FrameworkStatsLog
.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__TYPE_UNKNOWN)
?
@@ -5635,7 +5530,7 @@ public class UserManagerService extends IUserManager.Stub {
writeUserLP(userData);
}
- final long sessionId = logUserRemoveJourneyBegin(userId);
+ mUserJourneyLogger.logUserJourneyBegin(userId, USER_JOURNEY_USER_REMOVE);
try {
mAppOpsService.removeUser(userId);
@@ -5657,13 +5552,17 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public void userStopped(int userIdParam) {
finishRemoveUser(userIdParam);
- logUserRemoveJourneyFinish(sessionId, userIdParam,
- userData.info.userType, userData.info.flags, true);
+ int originUserId = UserManagerService.this.getCurrentUserId();
+ mUserJourneyLogger.logUserJourneyFinishWithError(originUserId,
+ userData.info, USER_JOURNEY_USER_REMOVE,
+ ERROR_CODE_UNSPECIFIED);
}
@Override
public void userStopAborted(int userIdParam) {
- logUserRemoveJourneyFinish(sessionId, userIdParam,
- userData.info.userType, userData.info.flags, false);
+ int originUserId = UserManagerService.this.getCurrentUserId();
+ mUserJourneyLogger.logUserJourneyFinishWithError(originUserId,
+ userData.info, USER_JOURNEY_USER_REMOVE,
+ ERROR_CODE_ABORTED);
}
});
} catch (RemoteException e) {
@@ -7297,9 +7196,9 @@ public class UserManagerService extends IUserManager.Stub {
final UserInfo userInfo = getUserInfo(userIds[i]);
if (userInfo == null) {
// Not possible because the input user ids should all be valid
- userTypes[i] = UserManager.getUserTypeForStatsd("");
+ userTypes[i] = mUserJourneyLogger.getUserTypeForStatsd("");
} else {
- userTypes[i] = UserManager.getUserTypeForStatsd(userInfo.userType);
+ userTypes[i] = mUserJourneyLogger.getUserTypeForStatsd(userInfo.userType);
}
}
return userTypes;
@@ -7536,4 +7435,11 @@ public class UserManagerService extends IUserManager.Stub {
.getBoolean(R.bool.config_canSwitchToHeadlessSystemUser);
}
+ /**
+ * Returns instance of {@link com.android.server.pm.UserJourneyLogger}.
+ */
+ public UserJourneyLogger getUserJourneyLogger() {
+ return mUserJourneyLogger;
+ }
+
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 9ff98be6f5cd..f8954b7c7f95 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -5690,8 +5690,14 @@ public final class PowerManagerService extends SystemService
}
if (eventTime > now) {
- Slog.e(TAG, "Event time " + eventTime + " cannot be newer than " + now);
- throw new IllegalArgumentException("event time must not be in the future");
+ Slog.wtf(TAG, "Event cannot be newer than the current time ("
+ + "now=" + now
+ + ", eventTime=" + eventTime
+ + ", displayId=" + displayId
+ + ", event=" + PowerManager.userActivityEventToString(event)
+ + ", flags=" + flags
+ + ")");
+ return;
}
final int uid = Binder.getCallingUid();
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 9020cb3405a2..45c7c9ad4477 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -2445,12 +2445,36 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
/**
* TODO(multi-display) Extends this method with specific display.
- * Propagate ambient state to wallpaper engine.
+ * Propagate ambient state to wallpaper engine(s).
*
* @param inAmbientMode {@code true} when in ambient mode, {@code false} otherwise.
* @param animationDuration Duration of the animation, or 0 when immediate.
*/
public void setInAmbientMode(boolean inAmbientMode, long animationDuration) {
+ if (mIsLockscreenLiveWallpaperEnabled) {
+ List<IWallpaperEngine> engines = new ArrayList<>();
+ synchronized (mLock) {
+ mInAmbientMode = inAmbientMode;
+ for (WallpaperData data : getActiveWallpapers()) {
+ if (data.connection.mInfo == null
+ || data.connection.mInfo.supportsAmbientMode()) {
+ // TODO(multi-display) Extends this method with specific display.
+ IWallpaperEngine engine = data.connection
+ .getDisplayConnectorOrCreate(DEFAULT_DISPLAY).mEngine;
+ if (engine != null) engines.add(engine);
+ }
+ }
+ }
+ for (IWallpaperEngine engine : engines) {
+ try {
+ engine.setInAmbientMode(inAmbientMode, animationDuration);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to set ambient mode", e);
+ }
+ }
+ return;
+ }
+
final IWallpaperEngine engine;
synchronized (mLock) {
mInAmbientMode = inAmbientMode;
@@ -2475,10 +2499,25 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
/**
- * Propagate a wake event to the wallpaper engine.
+ * Propagate a wake event to the wallpaper engine(s).
*/
public void notifyWakingUp(int x, int y, @NonNull Bundle extras) {
synchronized (mLock) {
+ if (mIsLockscreenLiveWallpaperEnabled) {
+ for (WallpaperData data : getActiveWallpapers()) {
+ data.connection.forEachDisplayConnector(displayConnector -> {
+ if (displayConnector.mEngine != null) {
+ try {
+ displayConnector.mEngine.dispatchWallpaperCommand(
+ WallpaperManager.COMMAND_WAKING_UP, x, y, -1, extras);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to dispatch COMMAND_WAKING_UP", e);
+ }
+ }
+ });
+ }
+ return;
+ }
final WallpaperData data = mWallpaperMap.get(mCurrentUserId);
if (data != null && data.connection != null) {
data.connection.forEachDisplayConnector(
@@ -2497,10 +2536,26 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
/**
- * Propagate a sleep event to the wallpaper engine.
+ * Propagate a sleep event to the wallpaper engine(s).
*/
public void notifyGoingToSleep(int x, int y, @NonNull Bundle extras) {
synchronized (mLock) {
+ if (mIsLockscreenLiveWallpaperEnabled) {
+ for (WallpaperData data : getActiveWallpapers()) {
+ data.connection.forEachDisplayConnector(displayConnector -> {
+ if (displayConnector.mEngine != null) {
+ try {
+ displayConnector.mEngine.dispatchWallpaperCommand(
+ WallpaperManager.COMMAND_GOING_TO_SLEEP, x, y, -1,
+ extras);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to dispatch COMMAND_GOING_TO_SLEEP", e);
+ }
+ }
+ });
+ }
+ return;
+ }
final WallpaperData data = mWallpaperMap.get(mCurrentUserId);
if (data != null && data.connection != null) {
data.connection.forEachDisplayConnector(
@@ -2520,11 +2575,27 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
/**
- * Propagates screen turned on event to wallpaper engine.
+ * Propagates screen turned on event to wallpaper engine(s).
*/
@Override
public void notifyScreenTurnedOn(int displayId) {
synchronized (mLock) {
+ if (mIsLockscreenLiveWallpaperEnabled) {
+ for (WallpaperData data : getActiveWallpapers()) {
+ if (data.connection.containsDisplay(displayId)) {
+ final IWallpaperEngine engine = data.connection
+ .getDisplayConnectorOrCreate(displayId).mEngine;
+ if (engine != null) {
+ try {
+ engine.onScreenTurnedOn();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to notify that the screen turned on", e);
+ }
+ }
+ }
+ }
+ return;
+ }
final WallpaperData data = mWallpaperMap.get(mCurrentUserId);
if (data != null
&& data.connection != null
@@ -2545,11 +2616,27 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
/**
- * Propagate screen turning on event to wallpaper engine.
+ * Propagate screen turning on event to wallpaper engine(s).
*/
@Override
public void notifyScreenTurningOn(int displayId) {
synchronized (mLock) {
+ if (mIsLockscreenLiveWallpaperEnabled) {
+ for (WallpaperData data : getActiveWallpapers()) {
+ if (data.connection.containsDisplay(displayId)) {
+ final IWallpaperEngine engine = data.connection
+ .getDisplayConnectorOrCreate(displayId).mEngine;
+ if (engine != null) {
+ try {
+ engine.onScreenTurningOn();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to notify that the screen is turning on", e);
+ }
+ }
+ }
+ }
+ return;
+ }
final WallpaperData data = mWallpaperMap.get(mCurrentUserId);
if (data != null
&& data.connection != null
@@ -2576,6 +2663,17 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
return true;
}
+ private WallpaperData[] getActiveWallpapers() {
+ WallpaperData systemWallpaper = mWallpaperMap.get(mCurrentUserId);
+ WallpaperData lockWallpaper = mLockWallpaperMap.get(mCurrentUserId);
+ boolean systemValid = systemWallpaper != null && systemWallpaper.connection != null;
+ boolean lockValid = lockWallpaper != null && lockWallpaper.connection != null;
+ return systemValid && lockValid ? new WallpaperData[]{systemWallpaper, lockWallpaper}
+ : systemValid ? new WallpaperData[]{systemWallpaper}
+ : lockValid ? new WallpaperData[]{lockWallpaper}
+ : new WallpaperData[0];
+ }
+
private IWallpaperEngine getEngine(int which, int userId, int displayId) {
WallpaperData wallpaperData = findWallpaperAtDisplay(userId, displayId);
if (wallpaperData == null) return null;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 25e5dacb25e3..26b40b4c09ee 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -582,6 +582,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
boolean mPauseSchedulePendingForPip = false;
+ // Gets set to indicate that the activity is currently being auto-pipped.
+ boolean mAutoEnteringPip = false;
+
private void updateEnterpriseThumbnailDrawable(Context context) {
DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
mEnterpriseThumbnailDrawable = dpm.getResources().getDrawable(
@@ -4908,9 +4911,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mTransitionController.setStatusBarTransitionDelay(
mPendingRemoteAnimation.getStatusBarTransitionDelay());
} else {
- if (mPendingOptions == null
- || mPendingOptions.getAnimationType() == ANIM_SCENE_TRANSITION) {
- // Scene transition will run on the client side.
+ if (mPendingOptions == null) {
+ return;
+ } else if (mPendingOptions.getAnimationType() == ANIM_SCENE_TRANSITION) {
+ // Scene transition will run on the client side, so just notify transition
+ // controller but don't clear the animation information from the options since they
+ // need to be sent to the animating activity.
+ mTransitionController.setOverrideAnimation(
+ AnimationOptions.makeSceneTransitionAnimOptions(), null, null);
return;
}
applyOptionsAnimation(mPendingOptions, intent);
@@ -6094,8 +6102,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
try {
mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), token,
PauseActivityItem.obtain(finishing, false /* userLeaving */,
- configChangeFlags, false /* dontReport */,
- false /* autoEnteringPip */));
+ configChangeFlags, false /* dontReport */, mAutoEnteringPip));
} catch (Exception e) {
Slog.w(TAG, "Exception thrown sending pause: " + intent.getComponent(), e);
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index a0ea1c3dbdbf..f86df2aa9bed 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3592,15 +3592,21 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
}
+ boolean enterPictureInPictureMode(@NonNull ActivityRecord r,
+ @NonNull PictureInPictureParams params, boolean fromClient) {
+ return enterPictureInPictureMode(r, params, fromClient, false /* isAutoEnter */);
+ }
+
/**
* Puts the given activity in picture in picture mode if possible.
*
* @param fromClient true if this comes from a client call (eg. Activity.enterPip).
+ * @param isAutoEnter true if this comes from an automatic pip-enter.
* @return true if the activity is now in picture-in-picture mode, or false if it could not
* enter picture-in-picture mode.
*/
boolean enterPictureInPictureMode(@NonNull ActivityRecord r,
- @NonNull PictureInPictureParams params, boolean fromClient) {
+ @NonNull PictureInPictureParams params, boolean fromClient, boolean isAutoEnter) {
// If the activity is already in picture in picture mode, then just return early
if (r.inPinnedWindowingMode()) {
return true;
@@ -3635,6 +3641,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
return;
}
r.setPictureInPictureParams(params);
+ r.mAutoEnteringPip = isAutoEnter;
mRootWindowContainer.moveActivityToPinnedRootTask(r,
null /* launchIntoPipHostActivity */, "enterPictureInPictureMode",
transition);
@@ -3643,6 +3650,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
r.getTask().schedulePauseActivity(r, false /* userLeaving */,
false /* pauseImmediately */, true /* autoEnteringPip */, "auto-pip");
}
+ r.mAutoEnteringPip = false;
}
};
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index ce4362853b23..be52e5a4566b 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1095,11 +1095,9 @@ public class DisplayPolicy {
} else {
overrideProviders = null;
}
- final @InsetsType int type = provider.getType();
- final int id = InsetsSource.createId(
- provider.getOwner(), provider.getIndex(), type);
- mDisplayContent.getInsetsStateController().getOrCreateSourceProvider(id, type)
- .setWindowContainer(win, frameProvider, overrideProviders);
+ mDisplayContent.getInsetsStateController().getOrCreateSourceProvider(
+ provider.getId(), provider.getType()).setWindowContainer(
+ win, frameProvider, overrideProviders);
mInsetsSourceWindowsExceptIme.add(win);
}
}
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index fe13b87a079a..ddf96c53323d 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -311,16 +311,13 @@ class InsetsPolicy {
state.removeSource(ID_IME);
} else if (attrs.providedInsets != null) {
for (InsetsFrameProvider provider : attrs.providedInsets) {
- final int id = InsetsSource.createId(
- provider.getOwner(), provider.getIndex(), provider.getType());
- final @InsetsType int type = provider.getType();
- if ((type & WindowInsets.Type.systemBars()) == 0) {
+ if ((provider.getType() & WindowInsets.Type.systemBars()) == 0) {
continue;
}
if (state == originalState) {
state = new InsetsState(state);
}
- state.removeSource(id);
+ state.removeSource(provider.getId());
}
}
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 08a6358afbc7..5f6d66011768 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -269,6 +269,8 @@ class KeyguardController {
TRANSIT_TO_BACK, transitFlags, null /* trigger */, dc);
updateKeyguardSleepToken();
+ // Make the home wallpaper visible
+ dc.mWallpaperController.showHomeWallpaperInTransition();
// Some stack visibility might change (e.g. docked stack)
mRootWindowContainer.resumeFocusedTasksTopActivities();
mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 7bd3b3253614..a1e497e1e099 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -607,9 +607,10 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
recordDisplay(wc.getDisplayContent());
if (info.mShowWallpaper) {
// Collect the wallpaper token (for isWallpaper(wc)) so it is part of the sync set.
- final WindowState wallpaper =
- wc.getDisplayContent().mWallpaperController.getTopVisibleWallpaper();
- if (wallpaper != null) {
+ final List<WindowState> wallpapers =
+ wc.getDisplayContent().mWallpaperController.getAllTopWallpapers();
+ for (int i = wallpapers.size() - 1; i >= 0; i--) {
+ WindowState wallpaper = wallpapers.get(i);
collect(wallpaper.mToken);
}
}
@@ -954,8 +955,15 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
// to the transient activity.
ar.supportsEnterPipOnTaskSwitch = true;
}
+ // Make sure this activity can enter pip under the current circumstances.
+ // `enterPictureInPicture` internally checks, but with beforeStopping=false which
+ // is specifically for non-auto-enter.
+ if (!ar.checkEnterPictureInPictureState("enterPictureInPictureMode",
+ true /* beforeStopping */)) {
+ return false;
+ }
return mController.mAtm.enterPictureInPictureMode(ar, ar.pictureInPictureArgs,
- false /* fromClient */);
+ false /* fromClient */, true /* isAutoEnter */);
}
// Legacy pip-entry (not via isAutoEnterEnabled).
@@ -1317,6 +1325,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
// ActivityRecord#canShowWindows() may reject to show its window. The visibility also
// needs to be updated for STATE_ABORT.
commitVisibleActivities(transaction);
+ commitVisibleWallpapers();
// Fall-back to the default display if there isn't one participating.
final DisplayContent primaryDisplay = !mTargetDisplays.isEmpty() ? mTargetDisplays.get(0)
@@ -1349,6 +1358,7 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
}
// Resolve the animating targets from the participants.
mTargets = calculateTargets(mParticipants, mChanges);
+
// Check whether the participants were animated from back navigation.
mController.mAtm.mBackNavigationController.onTransactionReady(this, mTargets);
final TransitionInfo info = calculateTransitionInfo(mType, mFlags, mTargets, transaction);
@@ -1625,6 +1635,30 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
}
}
+ /**
+ * Reset waitingToshow for all wallpapers, and commit the visibility of the visible ones
+ */
+ private void commitVisibleWallpapers() {
+ boolean showWallpaper = shouldWallpaperBeVisible();
+ for (int i = mParticipants.size() - 1; i >= 0; --i) {
+ final WallpaperWindowToken wallpaper = mParticipants.valueAt(i).asWallpaperToken();
+ if (wallpaper != null) {
+ wallpaper.waitingToShow = false;
+ if (!wallpaper.isVisible() && wallpaper.isVisibleRequested()) {
+ wallpaper.commitVisibility(showWallpaper);
+ }
+ }
+ }
+ }
+
+ private boolean shouldWallpaperBeVisible() {
+ for (int i = mParticipants.size() - 1; i >= 0; --i) {
+ WindowContainer participant = mParticipants.valueAt(i);
+ if (participant.showWallpaper()) return true;
+ }
+ return false;
+ }
+
// TODO(b/188595497): Remove after migrating to shell.
/** @see RecentsAnimationController#attachNavigationBarToApp */
private void handleLegacyRecentsStartBehavior(DisplayContent dc, TransitionInfo info) {
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index 7cb6b46666f9..c9316bf6e972 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -813,6 +813,10 @@ class TransitionController {
}
ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Finish Transition: %s", record);
mPlayingTransitions.remove(record);
+ if (!inTransition()) {
+ // reset track-count now since shell-side is idle.
+ mTrackCount = 0;
+ }
updateRunningRemoteAnimation(record, false /* isPlaying */);
record.finishTransition();
for (int i = mAnimatingExitWindows.size() - 1; i >= 0; i--) {
@@ -825,10 +829,9 @@ class TransitionController {
}
}
mRunningLock.doNotifyLocked();
- // Run state-validation checks when no transitions are active anymore.
+ // Run state-validation checks when no transitions are active anymore (Note: sometimes
+ // finish can start a transition, so check afterwards -- eg. pip).
if (!inTransition()) {
- // Can reset track-count now that everything is idle.
- mTrackCount = 0;
validateStates();
mAtm.mWindowManager.onAnimationFinished();
}
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 7ceac4fe7f16..edafe0606b13 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -124,24 +124,19 @@ class WallpaperController {
final boolean mIsLockscreenLiveWallpaperEnabled;
- private final ToBooleanFunction<WindowState> mFindWallpaperTargetFunction = w -> {
- if ((w.mAttrs.type == TYPE_WALLPAPER)) {
- if (mFindResults.topWallpaper == null || mFindResults.resetTopWallpaper) {
- WallpaperWindowToken token = w.mToken.asWallpaperToken();
- if (token == null) {
- Slog.w(TAG, "Window " + w + " has wallpaper type but not wallpaper token");
- return false;
- }
- if (!token.canShowWhenLocked() && mDisplayContent.isKeyguardLocked()) {
- return false;
- }
- mFindResults.setTopWallpaper(w);
- mFindResults.resetTopWallpaper = false;
+ private final Consumer<WindowState> mFindWallpapers = w -> {
+ if (w.mAttrs.type == TYPE_WALLPAPER) {
+ WallpaperWindowToken token = w.mToken.asWallpaperToken();
+ if (token.canShowWhenLocked() && !mFindResults.hasTopShowWhenLockedWallpaper()) {
+ mFindResults.setTopShowWhenLockedWallpaper(w);
+ } else if (!token.canShowWhenLocked()
+ && !mFindResults.hasTopHideWhenLockedWallpaper()) {
+ mFindResults.setTopHideWhenLockedWallpaper(w);
}
- return false;
}
+ };
- mFindResults.resetTopWallpaper = true;
+ private final ToBooleanFunction<WindowState> mFindWallpaperTargetFunction = w -> {
if (!w.mTransitionController.isShellTransitionsEnabled()) {
if (w.mActivityRecord != null && !w.mActivityRecord.isVisible()
&& !w.mActivityRecord.isAnimating(TRANSITION | PARENTS)) {
@@ -344,6 +339,31 @@ class WallpaperController {
}
}
+ /**
+ * Change the visibility if wallpaper is home screen only.
+ * This is called during the keyguard unlocking transition
+ * (see {@link KeyguardController#keyguardGoingAway(int, int)}) and thus assumes that if the
+ * system wallpaper is shared with lock, then it needs no animation.
+ */
+ public void showHomeWallpaperInTransition() {
+ updateWallpaperWindowsTarget(mFindResults);
+
+ if (!mFindResults.hasTopShowWhenLockedWallpaper()) {
+ Slog.w(TAG, "There is no wallpaper for the lock screen");
+ return;
+ }
+ WindowState hideWhenLocked = mFindResults.mTopWallpaper.mTopHideWhenLockedWallpaper;
+ WindowState showWhenLocked = mFindResults.mTopWallpaper.mTopShowWhenLockedWallpaper;
+ if (!mFindResults.hasTopHideWhenLockedWallpaper()) {
+ // Shared wallpaper, ensure its visibility
+ showWhenLocked.mToken.asWallpaperToken().updateWallpaperWindows(true);
+ } else {
+ // Separate lock and home wallpapers: show home wallpaper and hide lock
+ hideWhenLocked.mToken.asWallpaperToken().updateWallpaperWindowsInTransition(true);
+ showWhenLocked.mToken.asWallpaperToken().updateWallpaperWindowsInTransition(false);
+ }
+ }
+
void hideDeferredWallpapersIfNeededLegacy() {
for (int i = mWallpaperTokens.size() - 1; i >= 0; i--) {
final WallpaperWindowToken token = mWallpaperTokens.get(i);
@@ -668,13 +688,26 @@ class WallpaperController {
mFindResults.setUseTopWallpaperAsTarget(true);
}
+ mDisplayContent.forAllWindows(mFindWallpapers, true /* traverseTopToBottom */);
mDisplayContent.forAllWindows(mFindWallpaperTargetFunction, true /* traverseTopToBottom */);
if (mFindResults.wallpaperTarget == null && mFindResults.useTopWallpaperAsTarget) {
- mFindResults.setWallpaperTarget(mFindResults.topWallpaper);
+ mFindResults.setWallpaperTarget(
+ mFindResults.getTopWallpaper(mDisplayContent.isKeyguardLocked()));
}
}
+ List<WindowState> getAllTopWallpapers() {
+ ArrayList<WindowState> wallpapers = new ArrayList<>(2);
+ if (mFindResults.hasTopShowWhenLockedWallpaper()) {
+ wallpapers.add(mFindResults.mTopWallpaper.mTopShowWhenLockedWallpaper);
+ }
+ if (mFindResults.hasTopHideWhenLockedWallpaper()) {
+ wallpapers.add(mFindResults.mTopWallpaper.mTopHideWhenLockedWallpaper);
+ }
+ return wallpapers;
+ }
+
private boolean isFullscreen(WindowManager.LayoutParams attrs) {
return attrs.x == 0 && attrs.y == 0
&& attrs.width == MATCH_PARENT && attrs.height == MATCH_PARENT;
@@ -760,10 +793,16 @@ class WallpaperController {
result.setWallpaperTarget(wallpaperTarget);
}
+ /**
+ * Change the visibility of the top wallpaper to {@param visibility} and hide all the others.
+ */
private void updateWallpaperTokens(boolean visibility, boolean locked) {
+ WindowState topWallpaper = mFindResults.getTopWallpaper(locked);
+ WallpaperWindowToken topWallpaperToken =
+ topWallpaper == null ? null : topWallpaper.mToken.asWallpaperToken();
for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
- token.updateWallpaperWindows(visibility && (!locked || token.canShowWhenLocked()));
+ token.updateWallpaperWindows(visibility && (token == topWallpaperToken));
}
}
@@ -801,8 +840,10 @@ class WallpaperController {
}
}
- // Keep both wallpapers visible unless the keyguard is locked (then hide private wp)
- updateWallpaperTokens(visible, mDisplayContent.isKeyguardLocked());
+ if (!mDisplayContent.isKeyguardGoingAway() || !mIsLockscreenLiveWallpaperEnabled) {
+ // When keyguard goes away, KeyguardController handles the visibility
+ updateWallpaperTokens(visible, mDisplayContent.isKeyguardLocked());
+ }
if (DEBUG_WALLPAPER) {
Slog.v(TAG, "adjustWallpaperWindows: wallpaper visibility " + visible
@@ -1019,14 +1060,52 @@ class WallpaperController {
/** Helper class for storing the results of a wallpaper target find operation. */
final private static class FindWallpaperTargetResult {
- WindowState topWallpaper = null;
+
+ static final class TopWallpaper {
+ // A wp that can be visible on home screen only
+ WindowState mTopHideWhenLockedWallpaper = null;
+ // A wallpaper that has permission to be visible on lock screen (lock or shared wp)
+ WindowState mTopShowWhenLockedWallpaper = null;
+
+ void reset() {
+ mTopHideWhenLockedWallpaper = null;
+ mTopShowWhenLockedWallpaper = null;
+ }
+ }
+
+ TopWallpaper mTopWallpaper = new TopWallpaper();
boolean useTopWallpaperAsTarget = false;
WindowState wallpaperTarget = null;
- boolean resetTopWallpaper = false;
boolean isWallpaperTargetForLetterbox = false;
- void setTopWallpaper(WindowState win) {
- topWallpaper = win;
+ void setTopHideWhenLockedWallpaper(WindowState win) {
+ if (DEBUG_WALLPAPER) {
+ Slog.v(TAG, "setTopHideWhenLockedWallpaper " + win);
+ }
+ mTopWallpaper.mTopHideWhenLockedWallpaper = win;
+ }
+
+ void setTopShowWhenLockedWallpaper(WindowState win) {
+ if (DEBUG_WALLPAPER) {
+ Slog.v(TAG, "setTopShowWhenLockedWallpaper " + win);
+ }
+ mTopWallpaper.mTopShowWhenLockedWallpaper = win;
+ }
+
+ boolean hasTopHideWhenLockedWallpaper() {
+ return mTopWallpaper.mTopHideWhenLockedWallpaper != null;
+ }
+
+ boolean hasTopShowWhenLockedWallpaper() {
+ return mTopWallpaper.mTopShowWhenLockedWallpaper != null;
+ }
+
+ WindowState getTopWallpaper(boolean isKeyguardLocked) {
+ if (!isKeyguardLocked && hasTopHideWhenLockedWallpaper()) {
+ return mTopWallpaper.mTopHideWhenLockedWallpaper;
+ } else {
+ return mTopWallpaper.mTopShowWhenLockedWallpaper;
+ }
}
void setWallpaperTarget(WindowState win) {
@@ -1042,10 +1121,9 @@ class WallpaperController {
}
void reset() {
- topWallpaper = null;
+ mTopWallpaper.reset();
wallpaperTarget = null;
useTopWallpaperAsTarget = false;
- resetTopWallpaper = false;
isWallpaperTargetForLetterbox = false;
}
}
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 1ffee05d20ec..5ea8f65b759c 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -128,6 +128,20 @@ class WallpaperWindowToken extends WindowToken {
}
}
+ /**
+ * Update the visibility of the token to {@param visible}. If a transition will collect the
+ * wallpaper, then the visibility will be committed during the execution of the transition.
+ *
+ * waitingToShow is reset at the beginning of the transition:
+ * {@link Transition#onTransactionReady(int, SurfaceControl.Transaction)}
+ */
+ void updateWallpaperWindowsInTransition(boolean visible) {
+ if (mTransitionController.isCollecting() && mVisibleRequested != visible) {
+ waitingToShow = true;
+ }
+ updateWallpaperWindows(visible);
+ }
+
void updateWallpaperWindows(boolean visible) {
if (mVisibleRequested != visible) {
ProtoLog.d(WM_DEBUG_WALLPAPER, "Wallpaper token %s visible=%b",
@@ -199,11 +213,11 @@ class WallpaperWindowToken extends WindowToken {
}
/**
- * Commits the visibility of this token. This will directly update the visibility without
- * regard for other state (like being in a transition).
+ * Commits the visibility of this token. This will directly update the visibility unless the
+ * wallpaper is in a transition.
*/
void commitVisibility(boolean visible) {
- if (visible == isVisible()) return;
+ if (visible == isVisible() || waitingToShow) return;
ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
"commitVisibility: %s: visible=%b mVisibleRequested=%b", this,
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index a5cdd0b43eb0..3ccf183920d3 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -435,8 +435,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
if (mLocalInsetsSources == null) {
mLocalInsetsSources = new SparseArray<>();
}
- final int id = InsetsSource.createId(
- provider.getOwner(), provider.getIndex(), provider.getType());
+ final int id = provider.getId();
if (mLocalInsetsSources.get(id) != null) {
if (DEBUG) {
Slog.d(TAG, "The local insets source for this " + provider
@@ -457,8 +456,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
return;
}
- final int id = InsetsSource.createId(
- provider.getOwner(), provider.getIndex(), provider.getType());
+ final int id = provider.getId();
if (mLocalInsetsSources.get(id) == null) {
if (DEBUG) {
Slog.d(TAG, "Given " + provider + " doesn't have a local insets source.");
diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
index 4af685e42246..0488247ec78b 100644
--- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
+++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
@@ -561,6 +561,14 @@ static jstring com_android_server_am_CachedAppOptimizer_getFreezerCheckPath(JNIE
return env->NewStringUTF(path.c_str());
}
+static jboolean com_android_server_am_CachedAppOptimizer_isFreezerProfileValid(JNIEnv* env) {
+ int uid = getuid();
+ int pid = getpid();
+
+ return isProfileValidForProcess("Frozen", uid, pid) &&
+ isProfileValidForProcess("Unfrozen", uid, pid);
+}
+
static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"cancelCompaction", "()V",
@@ -578,7 +586,9 @@ static const JNINativeMethod sMethods[] = {
{"getBinderFreezeInfo", "(I)I",
(void*)com_android_server_am_CachedAppOptimizer_getBinderFreezeInfo},
{"getFreezerCheckPath", "()Ljava/lang/String;",
- (void*)com_android_server_am_CachedAppOptimizer_getFreezerCheckPath}};
+ (void*)com_android_server_am_CachedAppOptimizer_getFreezerCheckPath},
+ {"isFreezerProfileValid", "()Z",
+ (void*)com_android_server_am_CachedAppOptimizer_isFreezerProfileValid}};
int register_android_server_am_CachedAppOptimizer(JNIEnv* env)
{
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
index cf49dcf8004e..0c4830afafcc 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyEngine.java
@@ -684,6 +684,38 @@ final class DevicePolicyEngine {
}
}
+ <V> void transferPolicies(EnforcingAdmin oldAdmin, EnforcingAdmin newAdmin) {
+ Set<PolicyKey> globalPolicies = new HashSet<>(mGlobalPolicies.keySet());
+ for (PolicyKey policy : globalPolicies) {
+ PolicyState<?> policyState = mGlobalPolicies.get(policy);
+ if (policyState.getPoliciesSetByAdmins().containsKey(oldAdmin)) {
+ PolicyDefinition<V> policyDefinition =
+ (PolicyDefinition<V>) policyState.getPolicyDefinition();
+ PolicyValue<V> policyValue =
+ (PolicyValue<V>) policyState.getPoliciesSetByAdmins().get(oldAdmin);
+ setGlobalPolicy(policyDefinition, newAdmin, policyValue);
+ }
+ }
+
+ for (int i = 0; i < mLocalPolicies.size(); i++) {
+ int userId = mLocalPolicies.keyAt(i);
+ Set<PolicyKey> localPolicies = new HashSet<>(
+ mLocalPolicies.get(userId).keySet());
+ for (PolicyKey policy : localPolicies) {
+ PolicyState<?> policyState = mLocalPolicies.get(userId).get(policy);
+ if (policyState.getPoliciesSetByAdmins().containsKey(oldAdmin)) {
+ PolicyDefinition<V> policyDefinition =
+ (PolicyDefinition<V>) policyState.getPolicyDefinition();
+ PolicyValue<V> policyValue =
+ (PolicyValue<V>) policyState.getPoliciesSetByAdmins().get(oldAdmin);
+ setLocalPolicy(policyDefinition, newAdmin, policyValue, userId);
+ }
+ }
+ }
+
+ removePoliciesForAdmin(oldAdmin);
+ }
+
private Set<UserRestrictionPolicyKey> getUserRestrictionPolicyKeysForAdminLocked(
Map<PolicyKey, PolicyState<?>> policies,
EnforcingAdmin admin) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 675ebd3ddd60..3578b16d62c6 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3882,6 +3882,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final ActiveAdmin adminToTransfer = policy.mAdminMap.get(outgoingReceiver);
final int oldAdminUid = adminToTransfer.getUid();
+ if (isPolicyEngineForFinanceFlagEnabled() || isPermissionCheckFlagEnabled()) {
+ EnforcingAdmin oldAdmin =
+ EnforcingAdmin.createEnterpriseEnforcingAdmin(
+ outgoingReceiver, userHandle, adminToTransfer);
+ EnforcingAdmin newAdmin =
+ EnforcingAdmin.createEnterpriseEnforcingAdmin(
+ incomingReceiver, userHandle, adminToTransfer);
+
+ mDevicePolicyEngine.transferPolicies(oldAdmin, newAdmin);
+ }
+
adminToTransfer.transfer(incomingDeviceInfo);
policy.mAdminMap.remove(outgoingReceiver);
policy.mAdminMap.put(incomingReceiver, adminToTransfer);
@@ -6051,7 +6062,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public void lockNow(int flags, String callerPackageName, boolean parent) {
CallerIdentity caller;
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
caller = getCallerIdentity(callerPackageName);
} else {
caller = getCallerIdentity();
@@ -6063,7 +6074,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ActiveAdmin admin;
// Make sure the caller has any active admin with the right policy or
// the required permission.
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
admin = enforcePermissionAndGetEnforcingAdmin(
/* admin= */ null,
/* permission= */ MANAGE_DEVICE_POLICY_LOCK,
@@ -8917,13 +8928,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
CallerIdentity caller;
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
} else {
caller = getCallerIdentity(who);
}
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
// The effect of this policy is device-wide.
enforcePermission(SET_TIME, caller.getPackageName(), UserHandle.USER_ALL);
} else {
@@ -8951,13 +8962,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return false;
}
CallerIdentity caller;
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
} else {
caller = getCallerIdentity(who);
}
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
enforceCanQuery(SET_TIME, caller.getPackageName(), UserHandle.USER_ALL);
} else {
Objects.requireNonNull(who, "ComponentName is null");
@@ -8980,13 +8991,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
CallerIdentity caller;
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
} else {
caller = getCallerIdentity(who);
}
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
// The effect of this policy is device-wide.
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
who,
@@ -9026,13 +9037,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
CallerIdentity caller;
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
} else {
caller = getCallerIdentity(who);
}
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
// The effect of this policy is device-wide.
enforceCanQuery(SET_TIME_ZONE, caller.getPackageName(), UserHandle.USER_ALL);
} else {
@@ -9335,7 +9346,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
CallerIdentity caller;
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
} else {
caller = getCallerIdentity(who);
@@ -9345,7 +9356,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final int userHandle = caller.getUserId();
int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle;
synchronized (getLockObject()) {
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
// SUPPORT USES_POLICY_DISABLE_KEYGUARD_FEATURES
EnforcingAdmin admin = enforcePermissionAndGetEnforcingAdmin(
who, MANAGE_DEVICE_POLICY_KEYGUARD, caller.getPackageName(),
@@ -9424,13 +9435,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (getLockObject()) {
if (who != null) {
- if (isPermissionCheckFlagEnabled()) {
- EnforcingAdmin admin = getEnforcingAdminForCaller(
- who, who.getPackageName());
+ if (isUnicornFlagEnabled()) {
+ EnforcingAdmin admin = getEnforcingAdminForPackage(
+ who, who.getPackageName(), userHandle);
Integer features = mDevicePolicyEngine.getLocalPolicySetByAdmin(
PolicyDefinition.KEYGUARD_DISABLED_FEATURES,
admin,
affectedUserId);
+
return features == null ? 0 : features;
} else {
ActiveAdmin admin = getActiveAdminUncheckedLocked(who, userHandle, parent);
@@ -9438,7 +9450,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
Integer features = mDevicePolicyEngine.getResolvedPolicy(
PolicyDefinition.KEYGUARD_DISABLED_FEATURES,
affectedUserId);
@@ -9999,10 +10011,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
"clearDeviceOwner can only be called by the device owner");
}
enforceUserUnlocked(deviceOwnerUserId);
- DevicePolicyData policy = getUserData(deviceOwnerUserId);
- if (policy.mPasswordTokenHandle != 0) {
- mLockPatternUtils.removeEscrowToken(policy.mPasswordTokenHandle, deviceOwnerUserId);
- }
final ActiveAdmin admin = getDeviceOwnerAdminLocked();
mInjector.binderWithCleanCallingIdentity(() -> {
@@ -10057,6 +10065,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
final DevicePolicyData policyData = getUserData(userId);
policyData.mCurrentInputMethodSet = false;
+ if (policyData.mPasswordTokenHandle != 0) {
+ mLockPatternUtils.removeEscrowToken(policyData.mPasswordTokenHandle, userId);
+ policyData.mPasswordTokenHandle = 0;
+ }
saveSettingsLocked(userId);
mPolicyCache.onUserRemoved(userId);
final DevicePolicyData systemPolicyData = getUserData(UserHandle.USER_SYSTEM);
@@ -10748,7 +10760,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@VisibleForTesting
boolean hasDeviceIdAccessUnchecked(String packageName, int uid) {
final int userId = UserHandle.getUserId(uid);
- if (isPermissionCheckFlagEnabled()) {
+ // TODO(b/280048070): Introduce a permission to handle device ID access
+ if (isPermissionCheckFlagEnabled()
+ && !(isUidProfileOwnerLocked(uid) || isUidDeviceOwnerLocked(uid))) {
return hasPermission(MANAGE_DEVICE_POLICY_CERTIFICATES, packageName, userId);
} else {
ComponentName deviceOwner = getDeviceOwnerComponent(true);
@@ -11635,7 +11649,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_APPLICATION_RESTRICTIONS);
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
who,
MANAGE_DEVICE_POLICY_APP_RESTRICTIONS,
@@ -13062,7 +13076,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
String packageName) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
EnforcingAdmin enforcingAdmin = enforceCanQueryAndGetEnforcingAdmin(
who,
MANAGE_DEVICE_POLICY_APP_RESTRICTIONS,
@@ -13132,7 +13146,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
ActiveAdmin admin;
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
who,
MANAGE_DEVICE_POLICY_PACKAGE_STATE,
@@ -13229,7 +13243,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
public boolean isPackageSuspended(ComponentName who, String callerPackage, String packageName) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
enforcePermission(
MANAGE_DEVICE_POLICY_PACKAGE_STATE,
caller.getPackageName(),
@@ -13835,7 +13849,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
boolean hidden, boolean parent) {
CallerIdentity caller = getCallerIdentity(who, callerPackage);
final int userId = parent ? getProfileParentId(caller.getUserId()) : caller.getUserId();
- if (isPermissionCheckFlagEnabled()) {
+ if (isPolicyEngineForFinanceFlagEnabled()) {
// TODO: We need to ensure the delegate with DELEGATION_PACKAGE_ACCESS can do this
enforcePermission(MANAGE_DEVICE_POLICY_PACKAGE_STATE, caller.getPackageName(), userId);
} else {
@@ -13854,7 +13868,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
boolean result;
synchronized (getLockObject()) {
if (parent) {
- if (!isPermissionCheckFlagEnabled()) {
+ if (!isPolicyEngineForFinanceFlagEnabled()) {
Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(
caller.getUserId()) && isManagedProfile(caller.getUserId()));
@@ -13871,7 +13885,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Slogf.v(LOG_TAG, "calling pm.setApplicationHiddenSettingAsUser(%s, %b, %d)",
packageName, hidden, userId);
}
- if (isPermissionCheckFlagEnabled()) {
+ if (isPolicyEngineForFinanceFlagEnabled()) {
EnforcingAdmin admin = getEnforcingAdminForCaller(who, callerPackage);
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.APPLICATION_HIDDEN(packageName),
@@ -13910,7 +13924,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
String packageName, boolean parent) {
CallerIdentity caller = getCallerIdentity(who, callerPackage);
int userId = parent ? getProfileParentId(caller.getUserId()) : caller.getUserId();
- if (isPermissionCheckFlagEnabled()) {
+ if (isPolicyEngineForFinanceFlagEnabled()) {
// TODO: Also support DELEGATION_PACKAGE_ACCESS
enforcePermission(MANAGE_DEVICE_POLICY_PACKAGE_STATE, caller.getPackageName(), userId);
} else {
@@ -13922,7 +13936,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (getLockObject()) {
if (parent) {
- if (!isPermissionCheckFlagEnabled()) {
+ if (!isPolicyEngineForFinanceFlagEnabled()) {
Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(caller.getUserId())
&& isManagedProfile(caller.getUserId()));
@@ -14114,13 +14128,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
enforceMaxStringLength(accountType, "account type");
CallerIdentity caller;
- if (isPermissionCheckFlagEnabled()) {
+ if (isPolicyEngineForFinanceFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
} else {
caller = getCallerIdentity(who);
}
synchronized (getLockObject()) {
- if (isPermissionCheckFlagEnabled()) {
+ if (isPolicyEngineForFinanceFlagEnabled()) {
int affectedUser = getAffectedUser(parent);
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
who,
@@ -14183,7 +14197,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
CallerIdentity caller;
Preconditions.checkArgumentNonnegative(userId, "Invalid userId");
final ArraySet<String> resultSet = new ArraySet<>();
- if (isPermissionCheckFlagEnabled()) {
+ if (isPolicyEngineForFinanceFlagEnabled()) {
int affectedUser = parent ? getProfileParentId(userId) : userId;
caller = getCallerIdentity(callerPackageName);
if (!hasPermission(MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT,
@@ -15554,12 +15568,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
public boolean setStatusBarDisabled(ComponentName who, String callerPackageName,
boolean disabled) {
CallerIdentity caller;
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
caller = getCallerIdentity(who, callerPackageName);
} else {
caller = getCallerIdentity(who);
}
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
enforcePermission(MANAGE_DEVICE_POLICY_STATUS_BAR, caller.getPackageName(),
UserHandle.USER_ALL);
} else {
@@ -15570,7 +15584,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
int userId = caller.getUserId();
synchronized (getLockObject()) {
- if (!isPermissionCheckFlagEnabled()) {
+ if (!isUnicornFlagEnabled()) {
Preconditions.checkCallAuthorization(isUserAffiliatedWithDeviceLocked(userId),
"Admin " + who + " is neither the device owner or affiliated "
+ "user's profile owner.");
@@ -15629,7 +15643,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public boolean isStatusBarDisabled(String callerPackage) {
final CallerIdentity caller = getCallerIdentity(callerPackage);
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
enforceCanQuery(
MANAGE_DEVICE_POLICY_STATUS_BAR, caller.getPackageName(), caller.getUserId());
} else {
@@ -15639,7 +15653,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
int userId = caller.getUserId();
synchronized (getLockObject()) {
- if (!isPermissionCheckFlagEnabled()) {
+ if (!isUnicornFlagEnabled()) {
Preconditions.checkCallAuthorization(isUserAffiliatedWithDeviceLocked(userId),
"Admin " + callerPackage
+ " is neither the device owner or affiliated user's profile owner.");
@@ -16800,7 +16814,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
EnforcingAdmin enforcingAdmin;
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
admin,
MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS,
@@ -16971,7 +16985,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
public int getPermissionGrantState(ComponentName admin, String callerPackage,
String packageName, String permission) throws RemoteException {
final CallerIdentity caller = getCallerIdentity(admin, callerPackage);
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
enforceCanQuery(MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, caller.getPackageName(),
caller.getUserId());
} else {
@@ -19109,14 +19123,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
throw new IllegalArgumentException("token must be at least 32-byte long");
}
CallerIdentity caller;
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
caller = getCallerIdentity(admin, callerPackageName);
} else {
caller = getCallerIdentity(admin);
}
final int userId = caller.getUserId();
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
admin,
MANAGE_DEVICE_POLICY_RESET_PASSWORD,
@@ -19172,7 +19186,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return false;
}
CallerIdentity caller;
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
caller = getCallerIdentity(admin, callerPackageName);
} else {
caller = getCallerIdentity(admin);
@@ -19180,7 +19194,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final int userId = caller.getUserId();
boolean result = false;
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
admin,
MANAGE_DEVICE_POLICY_RESET_PASSWORD,
@@ -19219,14 +19233,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return false;
}
CallerIdentity caller;
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
caller = getCallerIdentity(admin, callerPackageName);
} else {
caller = getCallerIdentity(admin);
}
int userId = caller.getUserId();
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
admin,
MANAGE_DEVICE_POLICY_RESET_PASSWORD,
@@ -19268,7 +19282,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
Objects.requireNonNull(token);
CallerIdentity caller;
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
caller = getCallerIdentity(admin, callerPackageName);
} else {
caller = getCallerIdentity(admin);
@@ -19278,7 +19292,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
boolean result = false;
final String password = passwordOrNull != null ? passwordOrNull : "";
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
admin,
MANAGE_DEVICE_POLICY_RESET_PASSWORD,
@@ -19309,7 +19323,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
if (result) {
- if (isPermissionCheckFlagEnabled()) {
+ if (isUnicornFlagEnabled()) {
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.RESET_PASSWORD_WITH_TOKEN)
.setAdmin(callerPackageName)
@@ -22930,6 +22944,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
MANAGE_DEVICE_POLICY_LOCATION,
MANAGE_DEVICE_POLICY_LOCK,
MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
+ MANAGE_DEVICE_POLICY_CERTIFICATES,
MANAGE_DEVICE_POLICY_NEARBY_COMMUNICATION,
MANAGE_DEVICE_POLICY_ORGANIZATION_IDENTITY,
MANAGE_DEVICE_POLICY_PACKAGE_STATE,
@@ -23566,6 +23581,30 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return EnforcingAdmin.createEnforcingAdmin(caller.getPackageName(), userId, admin);
}
+ private EnforcingAdmin getEnforcingAdminForPackage(@Nullable ComponentName who,
+ String packageName, int userId) {
+ ActiveAdmin admin;
+ if (who != null) {
+ if (isDeviceOwner(who, userId) || isProfileOwner(who, userId)) {
+ synchronized (getLockObject()) {
+ admin = getActiveAdminUncheckedLocked(who, userId);
+ }
+ if (admin != null) {
+ return EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userId, admin);
+ }
+ } else {
+ // Check for non-DPC active admins.
+ admin = getActiveAdminUncheckedLocked(who, userId);
+ if (admin != null) {
+ return EnforcingAdmin.createDeviceAdminEnforcingAdmin(who, userId, admin);
+ }
+ }
+ }
+
+ admin = getUserData(userId).createOrGetPermissionBasedAdmin(userId);
+ return EnforcingAdmin.createEnforcingAdmin(packageName, userId, admin);
+ }
+
private int getAffectedUser(boolean calledOnParent) {
int callingUserId = mInjector.userHandleGetCallingUserId();
return calledOnParent ? getProfileParentId(callingUserId) : callingUserId;
@@ -23621,6 +23660,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DEFAULT_KEEP_PROFILES_RUNNING_FLAG);
}
+ private boolean isUnicornFlagEnabled() {
+ return false;
+ }
+
private boolean isWorkProfileTelephonyEnabled() {
return isWorkProfileTelephonyDevicePolicyManagerFlagEnabled()
&& isWorkProfileTelephonySubscriptionManagerFlagEnabled();
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index f05b1d47ac0b..475966ea00b8 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -20,9 +20,11 @@ import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.os.Handler;
import android.os.IBinder.DeathRecipient;
import android.os.Looper;
@@ -53,7 +55,8 @@ public final class ProfcollectForwardingService extends SystemService {
public static final String LOG_TAG = "ProfcollectForwardingService";
private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
-
+ private static final String INTENT_UPLOAD_PROFILES =
+ "com.android.server.profcollect.UPLOAD_PROFILES";
private static final long BG_PROCESS_PERIOD = TimeUnit.HOURS.toMillis(4); // every 4 hours.
private IProfCollectd mIProfcollect;
@@ -66,6 +69,16 @@ public final class ProfcollectForwardingService extends SystemService {
}
};
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction() == INTENT_UPLOAD_PROFILES) {
+ Log.d(LOG_TAG, "Received broadcast to pack and upload reports");
+ packAndUploadReport();
+ }
+ }
+ };
+
public ProfcollectForwardingService(Context context) {
super(context);
@@ -73,6 +86,10 @@ public final class ProfcollectForwardingService extends SystemService {
throw new AssertionError("only one service instance allowed");
}
sSelfService = this;
+
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(INTENT_UPLOAD_PROFILES);
+ context.registerReceiver(mBroadcastReceiver, filter);
}
/**
@@ -296,7 +313,7 @@ public final class ProfcollectForwardingService extends SystemService {
}
if (status == UpdateEngine.UpdateStatusConstants.UPDATED_NEED_REBOOT) {
- packProfileReport();
+ packAndUploadReport();
}
}
@@ -307,7 +324,7 @@ public final class ProfcollectForwardingService extends SystemService {
});
}
- private void packProfileReport() {
+ private void packAndUploadReport() {
if (mIProfcollect == null) {
return;
}
diff --git a/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java
index f788c92b24b2..46974cf72381 100644
--- a/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UidObserverControllerTest.java
@@ -28,6 +28,8 @@ import static android.app.ActivityManager.PROCESS_STATE_RECEIVER;
import static android.app.ActivityManager.PROCESS_STATE_SERVICE;
import static android.app.ActivityManager.PROCESS_STATE_TOP;
+import static com.android.server.am.ProcessList.UNKNOWN_ADJ;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
@@ -81,7 +83,7 @@ public class UidObserverControllerTest {
public void testEnqueueUidChange() {
int change = mUidObserverController.enqueueUidChange(null, TEST_UID1,
UidRecord.CHANGE_ACTIVE, PROCESS_STATE_FOREGROUND_SERVICE,
- PROCESS_CAPABILITY_ALL, 0, false);
+ UNKNOWN_ADJ, PROCESS_CAPABILITY_ALL, 0, false);
assertEquals("expected=ACTIVE,actual=" + changeToStr(change),
UidRecord.CHANGE_ACTIVE, change);
assertPendingChange(TEST_UID1, UidRecord.CHANGE_ACTIVE, PROCESS_STATE_FOREGROUND_SERVICE,
@@ -91,8 +93,8 @@ public class UidObserverControllerTest {
final ChangeRecord record2 = new ChangeRecord();
change = mUidObserverController.enqueueUidChange(record2, TEST_UID2,
- UidRecord.CHANGE_CACHED, PROCESS_STATE_CACHED_RECENT, PROCESS_CAPABILITY_NONE,
- 99, true);
+ UidRecord.CHANGE_CACHED, PROCESS_STATE_CACHED_RECENT, UNKNOWN_ADJ,
+ PROCESS_CAPABILITY_NONE, 99, true);
assertEquals("expected=ACTIVE,actual=" + changeToStr(change),
UidRecord.CHANGE_CACHED, change);
assertPendingChange(TEST_UID1, UidRecord.CHANGE_ACTIVE, PROCESS_STATE_FOREGROUND_SERVICE,
@@ -101,7 +103,8 @@ public class UidObserverControllerTest {
PROCESS_CAPABILITY_NONE, 99, true, record2);
change = mUidObserverController.enqueueUidChange(record1, TEST_UID1,
- UidRecord.CHANGE_UNCACHED, PROCESS_STATE_TOP, PROCESS_CAPABILITY_ALL, 0, false);
+ UidRecord.CHANGE_UNCACHED, PROCESS_STATE_TOP, UNKNOWN_ADJ,
+ PROCESS_CAPABILITY_ALL, 0, false);
assertEquals("expected=ACTIVE|UNCACHED,actual=" + changeToStr(change),
UidRecord.CHANGE_ACTIVE | UidRecord.CHANGE_UNCACHED, change);
assertPendingChange(TEST_UID1, UidRecord.CHANGE_ACTIVE | UidRecord.CHANGE_UNCACHED,
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index d12741ac8bd6..cbc7dc2f2fe5 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -100,6 +100,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.server.FgThread;
import com.android.server.SystemService;
import com.android.server.am.UserState.KeyEvictedCallback;
+import com.android.server.pm.UserJourneyLogger;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerService;
import com.android.server.wm.WindowManagerService;
@@ -1074,6 +1075,8 @@ public class UserControllerTest {
private final KeyguardManager mKeyguardManagerMock;
private final LockPatternUtils mLockPatternUtilsMock;
+ private final UserJourneyLogger mUserJourneyLoggerMock;
+
private final Context mCtx;
TestInjector(Context ctx) {
@@ -1090,6 +1093,7 @@ public class UserControllerTest {
mKeyguardManagerMock = mock(KeyguardManager.class);
when(mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(true);
mLockPatternUtilsMock = mock(LockPatternUtils.class);
+ mUserJourneyLoggerMock = mock(UserJourneyLogger.class);
}
@Override
@@ -1220,6 +1224,11 @@ public class UserControllerTest {
void onSystemUserVisibilityChanged(boolean visible) {
Log.i(TAG, "onSystemUserVisibilityChanged(" + visible + ")");
}
+
+ @Override
+ protected UserJourneyLogger getUserJourneyLogger() {
+ return mUserJourneyLoggerMock;
+ }
}
private static class TestHandler extends Handler {
diff --git a/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncDataTest.java b/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncDataTest.java
index c5a9af7d909d..dcd06c9cc716 100644
--- a/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncDataTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncDataTest.java
@@ -30,7 +30,7 @@ public class CallMetadataSyncDataTest {
@Test
public void call_writeToParcel_fromParcel_reconstructsSuccessfully() {
final CallMetadataSyncData.Call call = new CallMetadataSyncData.Call();
- final long id = 5;
+ final String id = "5";
final String callerId = "callerId";
final byte[] appIcon = "appIcon".getBytes();
final String appName = "appName";
diff --git a/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncInCallServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncInCallServiceTest.java
index a488ab446aff..afddf3c9be29 100644
--- a/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncInCallServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CallMetadataSyncInCallServiceTest.java
@@ -47,24 +47,24 @@ public class CallMetadataSyncInCallServiceTest {
@Test
public void getCallForId_invalid() {
- when(mMockCrossDeviceCall.getId()).thenReturn(-1L);
- final CrossDeviceCall call = mSyncInCallService.getCallForId(-1L,
+ when(mMockCrossDeviceCall.getId()).thenReturn(null);
+ final CrossDeviceCall call = mSyncInCallService.getCallForId(null,
List.of(mMockCrossDeviceCall));
assertWithMessage("Unexpectedly found a match for call id").that(call).isNull();
}
@Test
public void getCallForId_noMatch() {
- when(mMockCrossDeviceCall.getId()).thenReturn(5L);
- final CrossDeviceCall call = mSyncInCallService.getCallForId(1L,
+ when(mMockCrossDeviceCall.getId()).thenReturn("123abc");
+ final CrossDeviceCall call = mSyncInCallService.getCallForId("abc123",
List.of(mMockCrossDeviceCall));
assertWithMessage("Unexpectedly found a match for call id").that(call).isNull();
}
@Test
public void getCallForId_hasMatch() {
- when(mMockCrossDeviceCall.getId()).thenReturn(5L);
- final CrossDeviceCall call = mSyncInCallService.getCallForId(5L,
+ when(mMockCrossDeviceCall.getId()).thenReturn("123abc");
+ final CrossDeviceCall call = mSyncInCallService.getCallForId("123abc",
List.of(mMockCrossDeviceCall));
assertWithMessage("Unexpectedly did not find a match for call id").that(call).isNotNull();
}
diff --git a/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CrossDeviceCallTest.java b/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CrossDeviceCallTest.java
index 9d42a5bf05d2..5a0646c0e0e5 100644
--- a/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CrossDeviceCallTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CrossDeviceCallTest.java
@@ -62,9 +62,9 @@ public class CrossDeviceCallTest {
assertWithMessage("Wrong status").that(crossDeviceCall.getStatus())
.isEqualTo(android.companion.Telecom.Call.RINGING);
assertWithMessage("Wrong controls").that(crossDeviceCall.getControls())
- .isEqualTo(Set.of(android.companion.Telecom.Call.ACCEPT,
- android.companion.Telecom.Call.REJECT,
- android.companion.Telecom.Call.SILENCE));
+ .isEqualTo(Set.of(android.companion.Telecom.ACCEPT,
+ android.companion.Telecom.REJECT,
+ android.companion.Telecom.SILENCE));
}
@Test
@@ -77,9 +77,9 @@ public class CrossDeviceCallTest {
assertWithMessage("Wrong status").that(crossDeviceCall.getStatus())
.isEqualTo(android.companion.Telecom.Call.ONGOING);
assertWithMessage("Wrong controls").that(crossDeviceCall.getControls())
- .isEqualTo(Set.of(android.companion.Telecom.Call.END,
- android.companion.Telecom.Call.MUTE,
- android.companion.Telecom.Call.PUT_ON_HOLD));
+ .isEqualTo(Set.of(android.companion.Telecom.END,
+ android.companion.Telecom.MUTE,
+ android.companion.Telecom.PUT_ON_HOLD));
}
@Test
@@ -92,8 +92,8 @@ public class CrossDeviceCallTest {
assertWithMessage("Wrong status").that(crossDeviceCall.getStatus())
.isEqualTo(android.companion.Telecom.Call.ON_HOLD);
assertWithMessage("Wrong controls").that(crossDeviceCall.getControls())
- .isEqualTo(Set.of(android.companion.Telecom.Call.END,
- android.companion.Telecom.Call.TAKE_OFF_HOLD));
+ .isEqualTo(Set.of(android.companion.Telecom.END,
+ android.companion.Telecom.TAKE_OFF_HOLD));
}
@Test
@@ -106,8 +106,8 @@ public class CrossDeviceCallTest {
assertWithMessage("Wrong status").that(crossDeviceCall.getStatus())
.isEqualTo(android.companion.Telecom.Call.ONGOING);
assertWithMessage("Wrong controls").that(crossDeviceCall.getControls())
- .isEqualTo(Set.of(android.companion.Telecom.Call.END,
- android.companion.Telecom.Call.MUTE));
+ .isEqualTo(Set.of(android.companion.Telecom.END,
+ android.companion.Telecom.MUTE));
}
@Test
@@ -120,8 +120,8 @@ public class CrossDeviceCallTest {
assertWithMessage("Wrong status").that(crossDeviceCall.getStatus())
.isEqualTo(android.companion.Telecom.Call.ONGOING);
assertWithMessage("Wrong controls").that(crossDeviceCall.getControls())
- .isEqualTo(Set.of(android.companion.Telecom.Call.END,
- android.companion.Telecom.Call.PUT_ON_HOLD));
+ .isEqualTo(Set.of(android.companion.Telecom.END,
+ android.companion.Telecom.PUT_ON_HOLD));
}
@Test
@@ -134,17 +134,17 @@ public class CrossDeviceCallTest {
assertWithMessage("Wrong status for ringing state").that(crossDeviceCall.getStatus())
.isEqualTo(android.companion.Telecom.Call.RINGING);
assertWithMessage("Wrong controls for ringing state").that(crossDeviceCall.getControls())
- .isEqualTo(Set.of(android.companion.Telecom.Call.ACCEPT,
- android.companion.Telecom.Call.REJECT,
- android.companion.Telecom.Call.SILENCE));
+ .isEqualTo(Set.of(android.companion.Telecom.ACCEPT,
+ android.companion.Telecom.REJECT,
+ android.companion.Telecom.SILENCE));
crossDeviceCall.updateCallDetails(createCallDetails(Call.STATE_ACTIVE,
Call.Details.CAPABILITY_HOLD | Call.Details.CAPABILITY_MUTE));
assertWithMessage("Wrong status for active state").that(crossDeviceCall.getStatus())
.isEqualTo(android.companion.Telecom.Call.ONGOING);
assertWithMessage("Wrong controls for active state").that(crossDeviceCall.getControls())
- .isEqualTo(Set.of(android.companion.Telecom.Call.END,
- android.companion.Telecom.Call.MUTE,
- android.companion.Telecom.Call.PUT_ON_HOLD));
+ .isEqualTo(Set.of(android.companion.Telecom.END,
+ android.companion.Telecom.MUTE,
+ android.companion.Telecom.PUT_ON_HOLD));
}
@Test
@@ -158,8 +158,8 @@ public class CrossDeviceCallTest {
assertWithMessage("Wrong status").that(crossDeviceCall.getStatus())
.isEqualTo(android.companion.Telecom.Call.RINGING_SILENCED);
assertWithMessage("Wrong controls").that(crossDeviceCall.getControls())
- .isEqualTo(Set.of(android.companion.Telecom.Call.ACCEPT,
- android.companion.Telecom.Call.REJECT));
+ .isEqualTo(Set.of(android.companion.Telecom.ACCEPT,
+ android.companion.Telecom.REJECT));
}
@Test
@@ -173,9 +173,9 @@ public class CrossDeviceCallTest {
assertWithMessage("Wrong status").that(crossDeviceCall.getStatus())
.isEqualTo(android.companion.Telecom.Call.ONGOING);
assertWithMessage("Wrong controls").that(crossDeviceCall.getControls())
- .isEqualTo(Set.of(android.companion.Telecom.Call.END,
- android.companion.Telecom.Call.MUTE,
- android.companion.Telecom.Call.PUT_ON_HOLD));
+ .isEqualTo(Set.of(android.companion.Telecom.END,
+ android.companion.Telecom.MUTE,
+ android.companion.Telecom.PUT_ON_HOLD));
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CrossDeviceSyncControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CrossDeviceSyncControllerTest.java
index eec026ccfc8a..25b0ae486230 100644
--- a/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CrossDeviceSyncControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/datatransfer/contextsync/CrossDeviceSyncControllerTest.java
@@ -81,7 +81,7 @@ public class CrossDeviceSyncControllerTest {
@Test
public void processTelecomDataFromSync_createCallUpdateMessage_hasCalls() {
- when(mMockCrossDeviceCall.getId()).thenReturn(5L);
+ when(mMockCrossDeviceCall.getId()).thenReturn("123abc");
final String callerId = "Firstname Lastname";
when(mMockCrossDeviceCall.getReadableCallerId(anyBoolean())).thenReturn(callerId);
final String appName = "AppName";
@@ -90,9 +90,9 @@ public class CrossDeviceSyncControllerTest {
when(mMockCrossDeviceCall.getCallingAppIcon()).thenReturn(appIcon.getBytes());
when(mMockCrossDeviceCall.getStatus()).thenReturn(android.companion.Telecom.Call.RINGING);
final Set<Integer> controls = Set.of(
- android.companion.Telecom.Call.ACCEPT,
- android.companion.Telecom.Call.REJECT,
- android.companion.Telecom.Call.SILENCE);
+ android.companion.Telecom.ACCEPT,
+ android.companion.Telecom.REJECT,
+ android.companion.Telecom.SILENCE);
when(mMockCrossDeviceCall.getControls()).thenReturn(controls);
final byte[] data = mCrossDeviceSyncController.createCallUpdateMessage(
new HashSet<>(List.of(mMockCrossDeviceCall)),
@@ -103,35 +103,33 @@ public class CrossDeviceSyncControllerTest {
callMetadataSyncData.getCalls()).hasSize(1);
final CallMetadataSyncData.Call call =
callMetadataSyncData.getCalls().stream().findAny().orElseThrow();
- assertWithMessage("Wrong id").that(call.getId()).isEqualTo(5L);
+ assertWithMessage("Wrong id").that(call.getId()).isEqualTo("123abc");
assertWithMessage("Wrong app icon").that(new String(call.getAppIcon())).isEqualTo(appIcon);
assertWithMessage("Wrong app name").that(call.getAppName()).isEqualTo(appName);
assertWithMessage("Wrong caller id").that(call.getCallerId()).isEqualTo(callerId);
assertWithMessage("Wrong status").that(call.getStatus())
.isEqualTo(android.companion.Telecom.Call.RINGING);
assertWithMessage("Wrong controls").that(call.getControls()).isEqualTo(controls);
- assertWithMessage("Unexpectedly has requests").that(
- callMetadataSyncData.getRequests()).isEmpty();
}
@Test
public void processTelecomDataFromMessage_createCallControlMessage_hasCallControlRequest() {
final byte[] data = CrossDeviceSyncController.createCallControlMessage(
- /* callId= */ 5L, /* status= */ android.companion.Telecom.Call.ACCEPT);
+ /* callId= */ "123abc", /* status= */ android.companion.Telecom.ACCEPT);
final CallMetadataSyncData callMetadataSyncData =
mCrossDeviceSyncController.processTelecomDataFromSync(data);
assertWithMessage("Wrong number of requests").that(
callMetadataSyncData.getRequests()).hasSize(1);
final CallMetadataSyncData.Call call =
callMetadataSyncData.getRequests().stream().findAny().orElseThrow();
- assertWithMessage("Wrong id").that(call.getId()).isEqualTo(5L);
+ assertWithMessage("Wrong id").that(call.getId()).isEqualTo("123abc");
assertWithMessage("Wrong app icon").that(call.getAppIcon()).isNull();
assertWithMessage("Wrong app name").that(call.getAppName()).isNull();
assertWithMessage("Wrong caller id").that(call.getCallerId()).isNull();
assertWithMessage("Wrong status").that(call.getStatus())
.isEqualTo(android.companion.Telecom.Call.UNKNOWN_STATUS);
assertWithMessage("Wrong controls").that(call.getControls())
- .isEqualTo(Set.of(android.companion.Telecom.Call.ACCEPT));
+ .isEqualTo(Set.of(android.companion.Telecom.ACCEPT));
assertWithMessage("Unexpectedly has active calls").that(
callMetadataSyncData.getCalls()).isEmpty();
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 1e342f580745..57755a9525fc 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1512,6 +1512,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
* Validates that when the device owner is removed, the reset password token is cleared
*/
@Test
+ @Ignore("b/277916462")
public void testClearDeviceOwner_clearResetPasswordToken() throws Exception {
mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -2602,6 +2603,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
@Test
+ @Ignore("b/277916462")
public void testSetApplicationHiddenWithDO() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -2627,6 +2629,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
@Test
+ @Ignore("b/277916462")
public void testSetApplicationHiddenWithPOOfOrganizationOwnedDevice() throws Exception {
final int MANAGED_PROFILE_USER_ID = CALLER_USER_HANDLE;
final int MANAGED_PROFILE_ADMIN_UID =
@@ -4373,6 +4376,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
@Test
+ @Ignore("b/277916462")
public void testSetAutoTimeZoneEnabledModifiesSetting() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -4384,6 +4388,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
@Test
+ @Ignore("b/277916462")
public void testSetAutoTimeZoneEnabledWithPOOnUser0() throws Exception {
mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
setupProfileOwnerOnUser0();
@@ -4395,6 +4400,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
@Test
+ @Ignore("b/277916462")
public void testSetAutoTimeZoneEnabledFailWithPONotOnUser0() throws Exception {
setupProfileOwner();
assertExpectException(SecurityException.class, null,
@@ -4404,6 +4410,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
@Test
+ @Ignore("b/277916462")
public void testSetAutoTimeZoneEnabledWithPOOfOrganizationOwnedDevice() throws Exception {
setupProfileOwner();
configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
@@ -5377,6 +5384,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
@Test
+ @Ignore("b/277916462")
public void testResetPasswordWithToken() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -5411,6 +5419,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
@Test
+ @Ignore("b/277916462")
public void resetPasswordWithToken_NumericPin() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -5431,6 +5440,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
@Test
+ @Ignore("b/277916462")
public void resetPasswordWithToken_EmptyPassword() throws Exception {
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
setupDeviceOwner();
@@ -7251,6 +7261,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
@Test
+ @Ignore("b/277916462")
public void testCanProfileOwnerResetPasswordWhenLocked() throws Exception {
setDeviceEncryptionPerUser();
setupProfileOwner();
@@ -7314,6 +7325,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
@Test
+ @Ignore("b/277916462")
public void testSetAccountTypesWithManagementDisabledOnManagedProfile() throws Exception {
setupProfileOwner();
@@ -7333,6 +7345,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
@Test
+ @Ignore("b/277916462")
public void testSetAccountTypesWithManagementDisabledOnOrgOwnedManagedProfile()
throws Exception {
mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS);
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserJourneyLoggerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserJourneyLoggerTest.java
new file mode 100644
index 000000000000..20e2692cb747
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/UserJourneyLoggerTest.java
@@ -0,0 +1,580 @@
+/*
+ * 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.pm;
+
+import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_ABORTED;
+import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_INCOMPLETE_OR_TIMEOUT;
+import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_NULL_USER_INFO;
+import static com.android.server.pm.UserJourneyLogger.ERROR_CODE_UNSPECIFIED;
+import static com.android.server.pm.UserJourneyLogger.EVENT_STATE_BEGIN;
+import static com.android.server.pm.UserJourneyLogger.EVENT_STATE_CANCEL;
+import static com.android.server.pm.UserJourneyLogger.EVENT_STATE_ERROR;
+import static com.android.server.pm.UserJourneyLogger.EVENT_STATE_FINISH;
+import static com.android.server.pm.UserJourneyLogger.EVENT_STATE_NONE;
+import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_GRANT_ADMIN;
+import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_CREATE;
+import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_REMOVE;
+import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_START;
+import static com.android.server.pm.UserJourneyLogger.USER_JOURNEY_USER_STOP;
+import static com.android.server.pm.UserJourneyLogger.USER_LIFECYCLE_EVENT_CREATE_USER;
+import static com.android.server.pm.UserJourneyLogger.USER_LIFECYCLE_EVENT_REMOVE_USER;
+import static com.android.server.pm.UserJourneyLogger.USER_LIFECYCLE_EVENT_REVOKE_ADMIN;
+import static com.android.server.pm.UserJourneyLogger.USER_LIFECYCLE_EVENT_START_USER;
+import static com.android.server.pm.UserJourneyLogger.USER_LIFECYCLE_EVENT_STOP_USER;
+import static com.android.server.pm.UserJourneyLogger.USER_LIFECYCLE_EVENT_USER_RUNNING_LOCKED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.pm.UserInfo;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class UserJourneyLoggerTest {
+
+ public static final int FULL_USER_ADMIN_FLAG = 0x00000402;
+ private UserJourneyLogger mUserJourneyLogger;
+
+ @Before
+ public void setup() throws Exception {
+ mUserJourneyLogger = spy(new UserJourneyLogger());
+ }
+
+ @Test
+ public void testUserStartLifecycleJourneyReported() {
+ final UserLifecycleJourneyReportedCaptor report1 = new UserLifecycleJourneyReportedCaptor();
+ final UserJourneyLogger.UserJourneySession session = new UserJourneyLogger
+ .UserJourneySession(10, USER_JOURNEY_USER_START);
+
+ report1.captureLogAndAssert(mUserJourneyLogger, session,
+ USER_JOURNEY_USER_START, 0, 10,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY, 1,
+ ERROR_CODE_UNSPECIFIED);
+ }
+
+
+ @Test
+ public void testUserLifecycleEventOccurred() {
+ final UserLifecycleEventOccurredCaptor report1 = new UserLifecycleEventOccurredCaptor();
+ final UserJourneyLogger.UserJourneySession session = new UserJourneyLogger
+ .UserJourneySession(10, USER_JOURNEY_USER_START);
+
+ report1.captureLogAndAssert(mUserJourneyLogger, session, 0,
+ USER_LIFECYCLE_EVENT_START_USER, EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED);
+ }
+
+ @Test
+ public void testLogUserLifecycleEvent() {
+ final UserLifecycleEventOccurredCaptor report1 = new UserLifecycleEventOccurredCaptor();
+ final UserJourneyLogger.UserJourneySession session = mUserJourneyLogger
+ .logUserJourneyBegin(10, USER_JOURNEY_USER_START);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_START_USER, EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 1);
+
+ mUserJourneyLogger.logUserLifecycleEvent(10, USER_LIFECYCLE_EVENT_USER_RUNNING_LOCKED,
+ EVENT_STATE_NONE);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_USER_RUNNING_LOCKED,
+ EVENT_STATE_NONE, ERROR_CODE_UNSPECIFIED, 2);
+ }
+
+
+ @Test
+ public void testCreateUserJourney() {
+ final UserLifecycleEventOccurredCaptor report1 = new UserLifecycleEventOccurredCaptor();
+ final UserJourneyLogger.UserJourneySession session = mUserJourneyLogger
+ .logUserJourneyBegin(-1, USER_JOURNEY_USER_CREATE);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, -1,
+ USER_LIFECYCLE_EVENT_CREATE_USER,
+ EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 1);
+
+ final UserLifecycleJourneyReportedCaptor report2 = new UserLifecycleJourneyReportedCaptor();
+ UserInfo targetUser = new UserInfo(10, "test target user",
+ UserInfo.FLAG_ADMIN | UserInfo.FLAG_FULL);
+ mUserJourneyLogger.logUserCreateJourneyFinish(0, targetUser);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_CREATE_USER,
+ EVENT_STATE_FINISH, ERROR_CODE_UNSPECIFIED, 2);
+
+ report2.captureAndAssert(mUserJourneyLogger, session.mSessionId,
+ USER_JOURNEY_USER_CREATE, 0, 10,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY,
+ 0x00000402, ERROR_CODE_UNSPECIFIED, 1);
+ }
+
+ @Test
+ public void testRemoveUserJourney() {
+ final UserLifecycleEventOccurredCaptor report1 = new UserLifecycleEventOccurredCaptor();
+ final UserJourneyLogger.UserJourneySession session = mUserJourneyLogger
+ .logUserJourneyBegin(10, USER_JOURNEY_USER_REMOVE);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_REMOVE_USER,
+ EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 1);
+
+ final UserLifecycleJourneyReportedCaptor report2 = new UserLifecycleJourneyReportedCaptor();
+ final UserInfo targetUser = new UserInfo(10, "test target user",
+ UserInfo.FLAG_ADMIN | UserInfo.FLAG_FULL);
+ mUserJourneyLogger.logUserJourneyFinish(0, targetUser,
+ USER_JOURNEY_USER_REMOVE);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_REMOVE_USER,
+ EVENT_STATE_FINISH, ERROR_CODE_UNSPECIFIED, 2);
+
+ report2.captureAndAssert(mUserJourneyLogger, session.mSessionId,
+ USER_JOURNEY_USER_REMOVE, 0, 10,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY,
+ 0x00000402, ERROR_CODE_UNSPECIFIED, 1);
+ }
+
+ @Test
+ public void testStartUserJourney() {
+ final UserLifecycleEventOccurredCaptor report1 = new UserLifecycleEventOccurredCaptor();
+ final UserJourneyLogger.UserJourneySession session = mUserJourneyLogger
+ .logUserJourneyBegin(10, USER_JOURNEY_USER_START);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_START_USER,
+ EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 1);
+
+ final UserLifecycleJourneyReportedCaptor report2 = new UserLifecycleJourneyReportedCaptor();
+ final UserInfo targetUser = new UserInfo(10, "test target user",
+ UserInfo.FLAG_ADMIN | UserInfo.FLAG_FULL);
+ mUserJourneyLogger.logUserJourneyFinish(0, targetUser,
+ USER_JOURNEY_USER_START);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_START_USER,
+ EVENT_STATE_FINISH, ERROR_CODE_UNSPECIFIED, 2);
+
+ report2.captureAndAssert(mUserJourneyLogger, session.mSessionId,
+ USER_JOURNEY_USER_START, 0, 10,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY,
+ 0x00000402, ERROR_CODE_UNSPECIFIED, 1);
+ }
+
+ @Test
+ public void testStopUserJourney() {
+ final UserLifecycleEventOccurredCaptor report1 = new UserLifecycleEventOccurredCaptor();
+ final UserJourneyLogger.UserJourneySession session = mUserJourneyLogger
+ .logUserJourneyBegin(10, USER_JOURNEY_USER_STOP);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_STOP_USER, EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 1);
+
+ final UserLifecycleJourneyReportedCaptor report2 = new UserLifecycleJourneyReportedCaptor();
+ final UserInfo targetUser = new UserInfo(10, "test target user",
+ UserInfo.FLAG_ADMIN | UserInfo.FLAG_FULL);
+ mUserJourneyLogger.logUserJourneyFinish(0, targetUser,
+ USER_JOURNEY_USER_STOP);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_STOP_USER, EVENT_STATE_FINISH, ERROR_CODE_UNSPECIFIED, 2);
+
+ report2.captureAndAssert(mUserJourneyLogger, session.mSessionId,
+ USER_JOURNEY_USER_STOP, 0, 10,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY,
+ 0x00000402, ERROR_CODE_UNSPECIFIED, 1);
+ }
+
+ @Test
+ public void testAbortStopUserJourney() {
+ final UserLifecycleEventOccurredCaptor report1 = new UserLifecycleEventOccurredCaptor();
+ final UserJourneyLogger.UserJourneySession session = mUserJourneyLogger
+ .logUserJourneyBegin(10, USER_JOURNEY_USER_STOP);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_STOP_USER, EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 1);
+
+ final UserLifecycleJourneyReportedCaptor report2 = new UserLifecycleJourneyReportedCaptor();
+ final UserInfo targetUser = new UserInfo(10, "test target user",
+ UserInfo.FLAG_ADMIN | UserInfo.FLAG_FULL);
+
+ mUserJourneyLogger.logUserJourneyFinishWithError(-1, targetUser,
+ USER_JOURNEY_USER_STOP, ERROR_CODE_ABORTED);
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_STOP_USER,
+ EVENT_STATE_CANCEL, ERROR_CODE_ABORTED, 2);
+
+ report2.captureAndAssert(mUserJourneyLogger, session.mSessionId,
+ USER_JOURNEY_USER_STOP, -1, 10,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY,
+ 0x00000402, ERROR_CODE_ABORTED, 1);
+ }
+
+ @Test
+ public void testIncompleteStopUserJourney() {
+ final UserLifecycleEventOccurredCaptor report1 = new UserLifecycleEventOccurredCaptor();
+ final UserLifecycleJourneyReportedCaptor report2 = new UserLifecycleJourneyReportedCaptor();
+
+ final UserJourneyLogger.UserJourneySession session = mUserJourneyLogger
+ .logUserJourneyBegin(10, USER_JOURNEY_USER_STOP);
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_STOP_USER,
+ EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 1);
+
+ mUserJourneyLogger.finishAndClearIncompleteUserJourney(10, USER_JOURNEY_USER_STOP);
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_STOP_USER,
+ EVENT_STATE_ERROR,
+ ERROR_CODE_INCOMPLETE_OR_TIMEOUT, 2);
+
+ report2.captureAndAssert(mUserJourneyLogger, session.mSessionId,
+ USER_JOURNEY_USER_STOP, -1, 10,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__TYPE_UNKNOWN,
+ -1, // information about user are incomplete
+ ERROR_CODE_INCOMPLETE_OR_TIMEOUT, 1);
+ }
+
+ @Test
+ public void testGrantAdminUserJourney() {
+ final UserLifecycleEventOccurredCaptor report1 = new UserLifecycleEventOccurredCaptor();
+ final UserJourneyLogger.UserJourneySession session = mUserJourneyLogger
+ .logUserJourneyBegin(10, USER_JOURNEY_GRANT_ADMIN);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ UserJourneyLogger.USER_LIFECYCLE_EVENT_GRANT_ADMIN,
+ EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 1);
+
+ final UserLifecycleJourneyReportedCaptor report2 = new UserLifecycleJourneyReportedCaptor();
+ final UserInfo targetUser = new UserInfo(10, "test target user",
+ UserInfo.FLAG_ADMIN | UserInfo.FLAG_FULL);
+ mUserJourneyLogger.logUserJourneyFinish(0, targetUser,
+ USER_JOURNEY_GRANT_ADMIN);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ UserJourneyLogger.USER_LIFECYCLE_EVENT_GRANT_ADMIN,
+ EVENT_STATE_FINISH, ERROR_CODE_UNSPECIFIED, 2);
+
+ report2.captureAndAssert(mUserJourneyLogger, session.mSessionId,
+ USER_JOURNEY_GRANT_ADMIN, 0, 10,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY,
+ 0x00000402, ERROR_CODE_UNSPECIFIED, 1);
+ }
+
+ @Test
+ public void testNullUserErrorGrantAdminUserJourney() {
+ final UserLifecycleEventOccurredCaptor report1 = new UserLifecycleEventOccurredCaptor();
+ final UserLifecycleJourneyReportedCaptor report2 = new UserLifecycleJourneyReportedCaptor();
+
+ UserJourneyLogger.UserJourneySession session = mUserJourneyLogger
+ .logUserJourneyBegin(10, USER_JOURNEY_GRANT_ADMIN);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ UserJourneyLogger.USER_LIFECYCLE_EVENT_GRANT_ADMIN,
+ EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 1);
+
+ mUserJourneyLogger.logNullUserJourneyError(USER_JOURNEY_GRANT_ADMIN,
+ 0, 10, "", -1);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ UserJourneyLogger.USER_LIFECYCLE_EVENT_GRANT_ADMIN,
+ EVENT_STATE_ERROR, ERROR_CODE_NULL_USER_INFO, 2);
+
+ report2.captureAndAssert(mUserJourneyLogger, session.mSessionId,
+ USER_JOURNEY_GRANT_ADMIN, 0, 10,
+ FrameworkStatsLog.USER_LIFECYCLE_EVENT_OCCURRED__EVENT__UNKNOWN,
+ -1, ERROR_CODE_NULL_USER_INFO, 1);
+ }
+
+ @Test
+ public void testRevokeAdminUserJourney() {
+ final UserLifecycleEventOccurredCaptor report1 = new UserLifecycleEventOccurredCaptor();
+ final UserJourneyLogger.UserJourneySession session = mUserJourneyLogger
+ .logUserJourneyBegin(10, UserJourneyLogger.USER_JOURNEY_REVOKE_ADMIN);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_REVOKE_ADMIN,
+ EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 1);
+
+ final UserLifecycleJourneyReportedCaptor report2 = new UserLifecycleJourneyReportedCaptor();
+ final UserInfo targetUser = new UserInfo(10, "test target user", UserInfo.FLAG_FULL);
+ mUserJourneyLogger.logUserJourneyFinish(0, targetUser,
+ UserJourneyLogger.USER_JOURNEY_REVOKE_ADMIN);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_REVOKE_ADMIN,
+ EVENT_STATE_FINISH, ERROR_CODE_UNSPECIFIED, 2);
+
+ report2.captureAndAssert(mUserJourneyLogger, session.mSessionId,
+ UserJourneyLogger.USER_JOURNEY_REVOKE_ADMIN, 0, 10,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY,
+ 0x00000400, ERROR_CODE_UNSPECIFIED, 1);
+ }
+
+ @Test
+ public void testSwitchFGUserJourney() {
+ final UserLifecycleEventOccurredCaptor report1 = new UserLifecycleEventOccurredCaptor();
+ final UserJourneyLogger.UserJourneySession session = mUserJourneyLogger
+ .logUserJourneyBegin(11, UserJourneyLogger.USER_JOURNEY_USER_SWITCH_FG);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 11,
+ UserJourneyLogger.USER_LIFECYCLE_EVENT_SWITCH_USER,
+ EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 1);
+
+ final UserJourneyLogger.UserJourneySession session2 = mUserJourneyLogger
+ .logUserJourneyBegin(11, USER_JOURNEY_USER_START);
+
+ report1.captureAndAssert(mUserJourneyLogger, session2.mSessionId, 11,
+ USER_LIFECYCLE_EVENT_START_USER,
+ EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 2);
+
+ final UserLifecycleJourneyReportedCaptor report2 = new UserLifecycleJourneyReportedCaptor();
+ final UserInfo targetUser = new UserInfo(11, "test target user",
+ UserInfo.FLAG_ADMIN | UserInfo.FLAG_FULL);
+ mUserJourneyLogger.logUserJourneyFinish(10, targetUser,
+ USER_JOURNEY_USER_START);
+
+ report1.captureAndAssert(mUserJourneyLogger, session2.mSessionId, 11,
+ USER_LIFECYCLE_EVENT_START_USER,
+ EVENT_STATE_FINISH, ERROR_CODE_UNSPECIFIED, 3);
+
+ report2.captureAndAssert(mUserJourneyLogger, session2.mSessionId,
+ USER_JOURNEY_USER_START, 10, 11,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY,
+ 0x00000402, ERROR_CODE_UNSPECIFIED, 1);
+
+ mUserJourneyLogger.logUserSwitchJourneyFinish(10, targetUser);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 11,
+ UserJourneyLogger.USER_LIFECYCLE_EVENT_SWITCH_USER,
+ EVENT_STATE_FINISH, ERROR_CODE_UNSPECIFIED, 4);
+
+ report2.captureAndAssert(mUserJourneyLogger, session.mSessionId,
+ UserJourneyLogger.USER_JOURNEY_USER_SWITCH_FG, 10, 11,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY,
+ 0x00000402, ERROR_CODE_UNSPECIFIED, 2);
+ }
+
+
+ @Test
+ public void testSwitchUIUserJourney() {
+ final UserLifecycleEventOccurredCaptor report1 = new UserLifecycleEventOccurredCaptor();
+ final UserJourneyLogger.UserJourneySession session = mUserJourneyLogger
+ .logUserJourneyBegin(11, UserJourneyLogger.USER_JOURNEY_USER_SWITCH_UI);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 11,
+ UserJourneyLogger.USER_LIFECYCLE_EVENT_SWITCH_USER,
+ EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 1);
+
+ final UserJourneyLogger.UserJourneySession session2 = mUserJourneyLogger
+ .logUserJourneyBegin(11, USER_JOURNEY_USER_START);
+
+ report1.captureAndAssert(mUserJourneyLogger, session2.mSessionId, 11,
+ USER_LIFECYCLE_EVENT_START_USER,
+ EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 2);
+
+ final UserLifecycleJourneyReportedCaptor report2 = new UserLifecycleJourneyReportedCaptor();
+ UserInfo targetUser = new UserInfo(11, "test target user",
+ UserInfo.FLAG_ADMIN | UserInfo.FLAG_FULL);
+ mUserJourneyLogger.logUserJourneyFinish(10, targetUser,
+ USER_JOURNEY_USER_START);
+
+ report1.captureAndAssert(mUserJourneyLogger, session2.mSessionId, 11,
+ USER_LIFECYCLE_EVENT_START_USER,
+ EVENT_STATE_FINISH, ERROR_CODE_UNSPECIFIED, 3);
+
+ report2.captureAndAssert(mUserJourneyLogger, session2.mSessionId,
+ USER_JOURNEY_USER_START, 10, 11,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY,
+ 0x00000402, ERROR_CODE_UNSPECIFIED, 1);
+
+ mUserJourneyLogger.logUserSwitchJourneyFinish(10, targetUser);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 11,
+ UserJourneyLogger.USER_LIFECYCLE_EVENT_SWITCH_USER,
+ EVENT_STATE_FINISH,
+ ERROR_CODE_UNSPECIFIED, 4);
+
+ report2.captureAndAssert(mUserJourneyLogger, session.mSessionId,
+ UserJourneyLogger.USER_JOURNEY_USER_SWITCH_UI, 10, 11,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY,
+ 0x00000402, ERROR_CODE_UNSPECIFIED, 2);
+ }
+
+
+ @Test
+ public void testSwitchWithStopUIUserJourney() {
+ final UserLifecycleEventOccurredCaptor report1 = new UserLifecycleEventOccurredCaptor();
+
+ // BEGIN USER SWITCH
+ final UserJourneyLogger.UserJourneySession session = mUserJourneyLogger
+ .logUserJourneyBegin(11, UserJourneyLogger.USER_JOURNEY_USER_SWITCH_UI);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 11,
+ UserJourneyLogger.USER_LIFECYCLE_EVENT_SWITCH_USER,
+ EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 1);
+
+ // BEGIN USER STOP
+ final UserJourneyLogger.UserJourneySession session2 = mUserJourneyLogger
+ .logUserJourneyBegin(10, USER_JOURNEY_USER_STOP);
+
+ report1.captureAndAssert(mUserJourneyLogger, session2.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_STOP_USER,
+ EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 2);
+
+ // BEGIN USER START
+ UserJourneyLogger.UserJourneySession session3 = mUserJourneyLogger
+ .logUserJourneyBegin(11, USER_JOURNEY_USER_START);
+
+ report1.captureAndAssert(mUserJourneyLogger, session3.mSessionId, 11,
+ USER_LIFECYCLE_EVENT_START_USER,
+ EVENT_STATE_BEGIN, ERROR_CODE_UNSPECIFIED, 3);
+
+
+ // FINISH USER STOP
+ final UserLifecycleJourneyReportedCaptor report2 = new UserLifecycleJourneyReportedCaptor();
+ final UserInfo targetUser = new UserInfo(10, "test target user",
+ UserInfo.FLAG_ADMIN | UserInfo.FLAG_FULL);
+ mUserJourneyLogger.logUserJourneyFinish(-1, targetUser,
+ USER_JOURNEY_USER_STOP);
+
+ report1.captureAndAssert(mUserJourneyLogger, session2.mSessionId, 10,
+ USER_LIFECYCLE_EVENT_STOP_USER,
+ EVENT_STATE_FINISH, ERROR_CODE_UNSPECIFIED, 4);
+
+ report2.captureAndAssert(mUserJourneyLogger, session2.mSessionId,
+ USER_JOURNEY_USER_STOP, -1, 10,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY,
+ FULL_USER_ADMIN_FLAG, ERROR_CODE_UNSPECIFIED, 1);
+
+ // FINISH USER START
+ final UserInfo targetUser2 = new UserInfo(11, "test target user",
+ UserInfo.FLAG_ADMIN | UserInfo.FLAG_FULL);
+ mUserJourneyLogger.logUserJourneyFinish(10, targetUser2,
+ USER_JOURNEY_USER_START);
+
+ report1.captureAndAssert(mUserJourneyLogger, session3.mSessionId, 11,
+ USER_LIFECYCLE_EVENT_START_USER,
+ EVENT_STATE_FINISH, ERROR_CODE_UNSPECIFIED, 5);
+
+ report2.captureAndAssert(mUserJourneyLogger, session3.mSessionId,
+ USER_JOURNEY_USER_START, 10, 11,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY,
+ FULL_USER_ADMIN_FLAG, ERROR_CODE_UNSPECIFIED, 2);
+
+
+ // FINISH USER SWITCH
+ mUserJourneyLogger.logUserSwitchJourneyFinish(10, targetUser2);
+
+ report1.captureAndAssert(mUserJourneyLogger, session.mSessionId, 11,
+ UserJourneyLogger.USER_LIFECYCLE_EVENT_SWITCH_USER,
+ EVENT_STATE_FINISH, ERROR_CODE_UNSPECIFIED, 6);
+
+ report2.captureAndAssert(mUserJourneyLogger, session.mSessionId,
+ UserJourneyLogger.USER_JOURNEY_USER_SWITCH_UI, 10, 11,
+ FrameworkStatsLog.USER_LIFECYCLE_JOURNEY_REPORTED__USER_TYPE__FULL_SECONDARY,
+ 0x00000402, ERROR_CODE_UNSPECIFIED, 3);
+ }
+
+ static class UserLifecycleJourneyReportedCaptor {
+ ArgumentCaptor<Long> mSessionId = ArgumentCaptor.forClass(Long.class);
+ ArgumentCaptor<Integer> mJourney = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> mOriginalUserId = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> mTargetUserId = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> mUserType = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> mUserFlags = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> mErrorCode = ArgumentCaptor.forClass(Integer.class);
+
+ public void captureAndAssert(UserJourneyLogger mUserJourneyLogger,
+ long sessionId, int journey, int originalUserId,
+ int targetUserId, int userType, int userFlags, int errorCode, int times) {
+ verify(mUserJourneyLogger, times(times))
+ .writeUserLifecycleJourneyReported(mSessionId.capture(),
+ mJourney.capture(),
+ mOriginalUserId.capture(),
+ mTargetUserId.capture(),
+ mUserType.capture(),
+ mUserFlags.capture(),
+ mErrorCode.capture());
+
+ assertThat(mSessionId.getValue()).isEqualTo(sessionId);
+ assertThat(mJourney.getValue()).isEqualTo(journey);
+ assertThat(mOriginalUserId.getValue()).isEqualTo(originalUserId);
+ assertThat(mTargetUserId.getValue()).isEqualTo(targetUserId);
+ assertThat(mUserType.getValue()).isEqualTo(userType);
+ assertThat(mUserFlags.getValue()).isEqualTo(userFlags);
+ assertThat(mErrorCode.getValue()).isEqualTo(errorCode);
+ }
+
+
+ public void captureLogAndAssert(UserJourneyLogger mUserJourneyLogger,
+ UserJourneyLogger.UserJourneySession session, int journey, int originalUserId,
+ int targetUserId, int userType, int userFlags, int errorCode) {
+ mUserJourneyLogger.logUserLifecycleJourneyReported(session, journey, originalUserId,
+ targetUserId, userType, userFlags, errorCode);
+
+ captureAndAssert(mUserJourneyLogger, session.mSessionId, journey, originalUserId,
+ targetUserId, userType, userFlags, errorCode, 1);
+ }
+ }
+
+
+ static class UserLifecycleEventOccurredCaptor {
+ ArgumentCaptor<Long> mSessionId = ArgumentCaptor.forClass(Long.class);
+ ArgumentCaptor<Integer> mTargetUserId = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> mEvent = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> mStste = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> mErrorCode = ArgumentCaptor.forClass(Integer.class);
+
+
+ public void captureAndAssert(UserJourneyLogger mUserJourneyLogger,
+ long sessionId, int targetUserId, int event, int state, int errorCode, int times) {
+ verify(mUserJourneyLogger, times(times))
+ .writeUserLifecycleEventOccurred(mSessionId.capture(),
+ mTargetUserId.capture(),
+ mEvent.capture(),
+ mStste.capture(),
+ mErrorCode.capture());
+
+ assertThat(mSessionId.getValue()).isEqualTo(sessionId);
+ assertThat(mTargetUserId.getValue()).isEqualTo(targetUserId);
+ assertThat(mEvent.getValue()).isEqualTo(event);
+ assertThat(mStste.getValue()).isEqualTo(state);
+ assertThat(mErrorCode.getValue()).isEqualTo(errorCode);
+ }
+
+
+ public void captureLogAndAssert(UserJourneyLogger mUserJourneyLogger,
+ UserJourneyLogger.UserJourneySession session, int targetUserId, int event,
+ int state, int errorCode) {
+ mUserJourneyLogger.logUserLifecycleEventOccurred(session, targetUserId, event,
+ state, errorCode);
+
+ captureAndAssert(mUserJourneyLogger, session.mSessionId, targetUserId, event,
+ state, errorCode, 1);
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 52bf244e99fb..ae3ceb1203f8 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -20,6 +20,7 @@ import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
import static android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED;
+import static android.os.PowerManager.USER_ACTIVITY_EVENT_BUTTON;
import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
@@ -41,6 +42,7 @@ import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.atMost;
+import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -112,6 +114,7 @@ import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
+import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;
@@ -2468,4 +2471,18 @@ public class PowerManagerServiceTest {
verify(mNotifierMock).onWakeLockReleased(anyInt(), eq(tag), eq(packageName), anyInt(),
anyInt(), any(), any(), same(callback2));
}
+
+ @Test
+ public void testUserActivity_futureEventsAreIgnored() {
+ createService();
+ startSystem();
+ // Starting the system triggers a user activity event, so clear that before calling
+ // userActivity() directly.
+ clearInvocations(mNotifierMock);
+ final long eventTime = mClock.now() + Duration.ofHours(10).toMillis();
+ mService.getBinderServiceInstance().userActivity(Display.DEFAULT_DISPLAY, eventTime,
+ USER_ACTIVITY_EVENT_BUTTON, /* flags= */ 0);
+ verify(mNotifierMock, never()).onUserActivity(anyInt(), anyInt(), anyInt());
+ }
+
}
diff --git a/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger/DeviceStateHandlerTest.java b/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger/DeviceStateHandlerTest.java
new file mode 100644
index 000000000000..089bd454bfb8
--- /dev/null
+++ b/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger/DeviceStateHandlerTest.java
@@ -0,0 +1,261 @@
+/*
+ * 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.soundtrigger;
+
+import static android.os.PowerManager.SOUND_TRIGGER_MODE_ALL_DISABLED;
+import static android.os.PowerManager.SOUND_TRIGGER_MODE_ALL_ENABLED;
+import static android.os.PowerManager.SOUND_TRIGGER_MODE_CRITICAL_ONLY;
+
+import static com.android.server.soundtrigger.DeviceStateHandler.SoundTriggerDeviceState;
+import static com.android.server.soundtrigger.DeviceStateHandler.SoundTriggerDeviceState.*;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.SystemClock;
+
+import androidx.test.filters.FlakyTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.utils.EventLogger;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+public final class DeviceStateHandlerTest {
+ private final long CONFIRM_NO_EVENT_WAIT_MS = 1000;
+ // A wait substantially less than the duration we delay phone notifications by
+ private final long PHONE_DELAY_BRIEF_WAIT_MS =
+ DeviceStateHandler.CALL_INACTIVE_MSG_DELAY_MS / 4;
+
+ private DeviceStateHandler mHandler;
+ private DeviceStateHandler.DeviceStateListener mDeviceStateCallback;
+
+ private final Object mLock = new Object();
+
+ @GuardedBy("mLock")
+ private SoundTriggerDeviceState mState;
+
+ @GuardedBy("mLock")
+ private CountDownLatch mLatch;
+
+ private EventLogger mEventLogger;
+
+ @Before
+ public void setup() {
+ // Reset the state prior to each test
+ mEventLogger = new EventLogger(256, "test logger");
+ synchronized (mLock) {
+ mLatch = new CountDownLatch(1);
+ }
+ mDeviceStateCallback =
+ (SoundTriggerDeviceState state) -> {
+ synchronized (mLock) {
+ mState = state;
+ mLatch.countDown();
+ }
+ };
+ mHandler = new DeviceStateHandler(Runnable::run, mEventLogger);
+ mHandler.onPhoneCallStateChanged(false);
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_ALL_ENABLED);
+ mHandler.registerListener(mDeviceStateCallback);
+ try {
+ waitAndAssertState(ENABLE);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void waitAndAssertState(SoundTriggerDeviceState state) throws InterruptedException {
+ CountDownLatch latch;
+ synchronized (mLock) {
+ latch = mLatch;
+ }
+ latch.await();
+ synchronized (mLock) {
+ assertThat(mState).isEqualTo(state);
+ mLatch = new CountDownLatch(1);
+ }
+ }
+
+ private void waitToConfirmNoEventReceived() throws InterruptedException {
+ CountDownLatch latch;
+ synchronized (mLock) {
+ latch = mLatch;
+ }
+ // Check that we time out
+ assertThat(latch.await(CONFIRM_NO_EVENT_WAIT_MS, TimeUnit.MILLISECONDS)).isFalse();
+ }
+
+ @Test
+ public void onPowerModeChangedCritical_receiveStateChange() throws Exception {
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_CRITICAL_ONLY);
+ waitAndAssertState(CRITICAL);
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_ALL_ENABLED);
+ waitAndAssertState(ENABLE);
+ }
+
+ @Test
+ public void onPowerModeChangedDisabled_receiveStateChange() throws Exception {
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_ALL_DISABLED);
+ waitAndAssertState(DISABLE);
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_ALL_ENABLED);
+ waitAndAssertState(ENABLE);
+ }
+
+ @Test
+ public void onPowerModeChangedMultiple_receiveStateChange() throws Exception {
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_ALL_DISABLED);
+ waitAndAssertState(DISABLE);
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_CRITICAL_ONLY);
+ waitAndAssertState(CRITICAL);
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_ALL_DISABLED);
+ waitAndAssertState(DISABLE);
+ }
+
+ @Test
+ public void onPowerModeSameState_noStateChange() throws Exception {
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_ALL_DISABLED);
+ waitAndAssertState(DISABLE);
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_ALL_DISABLED);
+ waitToConfirmNoEventReceived();
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_CRITICAL_ONLY);
+ waitAndAssertState(CRITICAL);
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_CRITICAL_ONLY);
+ waitToConfirmNoEventReceived();
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_ALL_ENABLED);
+ waitAndAssertState(ENABLE);
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_ALL_ENABLED);
+ waitToConfirmNoEventReceived();
+ }
+
+ @Test
+ public void onPhoneCall_receiveStateChange() throws Exception {
+ mHandler.onPhoneCallStateChanged(true);
+ waitAndAssertState(DISABLE);
+ mHandler.onPhoneCallStateChanged(false);
+ waitAndAssertState(ENABLE);
+ }
+
+ @Test
+ public void onPhoneCall_receiveStateChangeIsDelayed() throws Exception {
+ mHandler.onPhoneCallStateChanged(true);
+ waitAndAssertState(DISABLE);
+ long beforeTime = SystemClock.uptimeMillis();
+ mHandler.onPhoneCallStateChanged(false);
+ waitAndAssertState(ENABLE);
+ long afterTime = SystemClock.uptimeMillis();
+ assertThat(afterTime - beforeTime).isAtLeast(DeviceStateHandler.CALL_INACTIVE_MSG_DELAY_MS);
+ }
+
+ @Test
+ public void onPhoneCallEnterExitEnter_receiveNoStateChange() throws Exception {
+ mHandler.onPhoneCallStateChanged(true);
+ waitAndAssertState(DISABLE);
+ mHandler.onPhoneCallStateChanged(false);
+ SystemClock.sleep(PHONE_DELAY_BRIEF_WAIT_MS);
+ mHandler.onPhoneCallStateChanged(true);
+ waitToConfirmNoEventReceived();
+ }
+
+ @Test
+ public void onBatteryCallbackDuringPhoneWait_receiveStateChangeDelayed() throws Exception {
+ mHandler.onPhoneCallStateChanged(true);
+ waitAndAssertState(DISABLE);
+ mHandler.onPhoneCallStateChanged(false);
+ SystemClock.sleep(PHONE_DELAY_BRIEF_WAIT_MS);
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_CRITICAL_ONLY);
+ waitAndAssertState(CRITICAL);
+ // Ensure we don't get an ENABLE event after
+ waitToConfirmNoEventReceived();
+ }
+
+ @Test
+ public void onBatteryChangeWhenInPhoneCall_receiveNoStateChange() throws Exception {
+ mHandler.onPhoneCallStateChanged(true);
+ waitAndAssertState(DISABLE);
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_ALL_ENABLED);
+ waitToConfirmNoEventReceived();
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_CRITICAL_ONLY);
+ waitToConfirmNoEventReceived();
+ }
+
+ @Test
+ public void whenBatteryCriticalChangeDuringCallAfterPhoneCall_receiveCriticalStateChange()
+ throws Exception {
+ mHandler.onPhoneCallStateChanged(true);
+ waitAndAssertState(DISABLE);
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_CRITICAL_ONLY);
+ waitToConfirmNoEventReceived();
+ mHandler.onPhoneCallStateChanged(false);
+ waitAndAssertState(CRITICAL);
+ }
+
+ @Test
+ public void whenBatteryDisableDuringCallAfterPhoneCallBatteryEnable_receiveStateChange()
+ throws Exception {
+ mHandler.onPhoneCallStateChanged(true);
+ waitAndAssertState(DISABLE);
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_ALL_DISABLED);
+ waitToConfirmNoEventReceived();
+ mHandler.onPhoneCallStateChanged(false);
+ waitToConfirmNoEventReceived();
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_CRITICAL_ONLY);
+ waitAndAssertState(CRITICAL);
+ }
+
+ @Test
+ public void whenPhoneCallDuringBatteryDisable_receiveNoStateChange() throws Exception {
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_ALL_DISABLED);
+ waitAndAssertState(DISABLE);
+ mHandler.onPhoneCallStateChanged(true);
+ waitToConfirmNoEventReceived();
+ mHandler.onPhoneCallStateChanged(false);
+ waitToConfirmNoEventReceived();
+ }
+
+ @Test
+ public void whenPhoneCallDuringBatteryCritical_receiveStateChange() throws Exception {
+ mHandler.onPowerModeChanged(SOUND_TRIGGER_MODE_CRITICAL_ONLY);
+ waitAndAssertState(CRITICAL);
+ mHandler.onPhoneCallStateChanged(true);
+ waitAndAssertState(DISABLE);
+ mHandler.onPhoneCallStateChanged(false);
+ waitAndAssertState(CRITICAL);
+ }
+
+ // This test could be flaky, but we want to verify that we only delay notification if
+ // we are exiting a call, NOT if we are entering a call.
+ @FlakyTest
+ @Test
+ public void whenPhoneCallReceived_receiveStateChangeFast() throws Exception {
+ mHandler.onPhoneCallStateChanged(true);
+ CountDownLatch latch;
+ synchronized (mLock) {
+ latch = mLatch;
+ }
+ assertThat(latch.await(PHONE_DELAY_BRIEF_WAIT_MS, TimeUnit.MILLISECONDS)).isTrue();
+ synchronized (mLock) {
+ assertThat(mState).isEqualTo(DISABLE);
+ }
+ }
+}
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 ad606cb90841..2d8ddfa47300 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -1443,10 +1443,8 @@ public class WindowContainerTests extends WindowTestsBase {
final InsetsFrameProvider provider2 =
new InsetsFrameProvider(null, 2, WindowInsets.Type.systemOverlays())
.setArbitraryRectangle(genericOverlayInsetsRect2);
- final int sourceId1 = InsetsSource.createId(
- provider1.getOwner(), provider1.getIndex(), provider1.getType());
- final int sourceId2 = InsetsSource.createId(
- provider2.getOwner(), provider2.getIndex(), provider2.getType());
+ final int sourceId1 = provider1.getId();
+ final int sourceId2 = provider2.getId();
rootTask.addLocalInsetsFrameProvider(provider1);
container.addLocalInsetsFrameProvider(provider2);
@@ -1504,10 +1502,8 @@ public class WindowContainerTests extends WindowTestsBase {
final InsetsFrameProvider provider2 =
new InsetsFrameProvider(null, 1, WindowInsets.Type.systemOverlays())
.setArbitraryRectangle(genericOverlayInsetsRect2);
- final int sourceId1 = InsetsSource.createId(
- provider1.getOwner(), provider1.getIndex(), provider1.getType());
- final int sourceId2 = InsetsSource.createId(
- provider2.getOwner(), provider2.getIndex(), provider2.getType());
+ final int sourceId1 = provider1.getId();
+ final int sourceId2 = provider2.getId();
rootTask.addLocalInsetsFrameProvider(provider1);
activity0.forAllWindows(window -> {
@@ -1566,10 +1562,8 @@ public class WindowContainerTests extends WindowTestsBase {
final InsetsFrameProvider provider2 =
new InsetsFrameProvider(null, 2, WindowInsets.Type.systemOverlays())
.setArbitraryRectangle(navigationBarInsetsRect2);
- final int sourceId1 = InsetsSource.createId(
- provider1.getOwner(), provider1.getIndex(), provider1.getType());
- final int sourceId2 = InsetsSource.createId(
- provider2.getOwner(), provider2.getIndex(), provider2.getType());
+ final int sourceId1 = provider1.getId();
+ final int sourceId2 = provider2.getId();
rootTask.addLocalInsetsFrameProvider(provider1);
container.addLocalInsetsFrameProvider(provider2);
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 a63807d23a14..a4cad5e24dc1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -359,9 +359,12 @@ class WindowTestsBase extends SystemServiceTestsBase {
new InsetsFrameProvider(owner, 0, WindowInsets.Type.tappableElement()),
new InsetsFrameProvider(owner, 0, WindowInsets.Type.mandatorySystemGestures())
};
- for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
- mNavBarWindow.mAttrs.paramsForRotation[rot] =
- getNavBarLayoutParamsForRotation(rot, owner);
+ // If the navigation bar cannot move then it is always at the bottom.
+ if (mDisplayContent.getDisplayPolicy().navigationBarCanMove()) {
+ for (int rot = Surface.ROTATION_0; rot <= Surface.ROTATION_270; rot++) {
+ mNavBarWindow.mAttrs.paramsForRotation[rot] =
+ getNavBarLayoutParamsForRotation(rot, owner);
+ }
}
}
if (addAll || ArrayUtils.contains(requestedWindows, W_DOCK_DIVIDER)) {
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/DeviceStateHandler.java b/services/voiceinteraction/java/com/android/server/soundtrigger/DeviceStateHandler.java
new file mode 100644
index 000000000000..66054494c277
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/DeviceStateHandler.java
@@ -0,0 +1,279 @@
+/**
+ * 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.soundtrigger;
+
+import static android.os.PowerManager.SOUND_TRIGGER_MODE_ALL_DISABLED;
+import static android.os.PowerManager.SOUND_TRIGGER_MODE_ALL_ENABLED;
+import static android.os.PowerManager.SOUND_TRIGGER_MODE_CRITICAL_ONLY;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.utils.EventLogger;
+
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Manages device state events which require pausing SoundTrigger recognition
+ *
+ * @hide
+ */
+public class DeviceStateHandler implements PhoneCallStateHandler.Callback {
+
+ public static final long CALL_INACTIVE_MSG_DELAY_MS = 1000;
+
+ public interface DeviceStateListener {
+ void onSoundTriggerDeviceStateUpdate(SoundTriggerDeviceState state);
+ }
+
+ public enum SoundTriggerDeviceState {
+ DISABLE, // The device state requires all SoundTrigger sessions are disabled
+ CRITICAL, // The device state requires all non-critical SoundTrigger sessions are disabled
+ ENABLE // The device state permits all SoundTrigger sessions
+ }
+
+ private final Object mLock = new Object();
+
+ private final EventLogger mEventLogger;
+
+ @GuardedBy("mLock")
+ SoundTriggerDeviceState mSoundTriggerDeviceState = SoundTriggerDeviceState.ENABLE;
+
+ // Individual components of the SoundTriggerDeviceState
+ @GuardedBy("mLock")
+ private int mSoundTriggerPowerSaveMode = SOUND_TRIGGER_MODE_ALL_ENABLED;
+
+ @GuardedBy("mLock")
+ private boolean mIsPhoneCallOngoing = false;
+
+ // There can only be one pending notify at any given time.
+ // If any phone state change comes in between, we will cancel the previous pending
+ // task.
+ @GuardedBy("mLock")
+ private NotificationTask mPhoneStateChangePendingNotify = null;
+
+ private Set<DeviceStateListener> mCallbackSet = ConcurrentHashMap.newKeySet(4);
+
+ private final Executor mDelayedNotificationExecutor = Executors.newSingleThreadExecutor();
+
+ private final Executor mCallbackExecutor;
+
+ public void onPowerModeChanged(int soundTriggerPowerSaveMode) {
+ mEventLogger.enqueue(new SoundTriggerPowerEvent(soundTriggerPowerSaveMode));
+ synchronized (mLock) {
+ if (soundTriggerPowerSaveMode == mSoundTriggerPowerSaveMode) {
+ // No state change, nothing to do
+ return;
+ }
+ mSoundTriggerPowerSaveMode = soundTriggerPowerSaveMode;
+ evaluateStateChange();
+ }
+ }
+
+ @Override
+ public void onPhoneCallStateChanged(boolean isInPhoneCall) {
+ mEventLogger.enqueue(new PhoneCallEvent(isInPhoneCall));
+ synchronized (mLock) {
+ if (mIsPhoneCallOngoing == isInPhoneCall) {
+ // no change, nothing to do
+ return;
+ }
+ // Clear any pending notification
+ if (mPhoneStateChangePendingNotify != null) {
+ mPhoneStateChangePendingNotify.cancel();
+ mPhoneStateChangePendingNotify = null;
+ }
+ mIsPhoneCallOngoing = isInPhoneCall;
+ if (!mIsPhoneCallOngoing) {
+ // State has changed from call to no call, delay notification
+ mPhoneStateChangePendingNotify = new NotificationTask(
+ new Runnable() {
+ @Override
+ public void run() {
+ synchronized (mLock) {
+ if (mPhoneStateChangePendingNotify != null &&
+ mPhoneStateChangePendingNotify.runnableEquals(this)) {
+
+ mPhoneStateChangePendingNotify = null;
+ evaluateStateChange();
+ }
+ }
+ }
+ },
+ CALL_INACTIVE_MSG_DELAY_MS);
+ mDelayedNotificationExecutor.execute(mPhoneStateChangePendingNotify);
+ } else {
+ evaluateStateChange();
+ }
+ }
+ }
+
+ /** Note, we expect initial callbacks immediately following construction */
+ public DeviceStateHandler(Executor callbackExecutor, EventLogger eventLogger) {
+ mCallbackExecutor = Objects.requireNonNull(callbackExecutor);
+ mEventLogger = Objects.requireNonNull(eventLogger);
+ }
+
+ public SoundTriggerDeviceState getDeviceState() {
+ synchronized (mLock) {
+ return mSoundTriggerDeviceState;
+ }
+ }
+
+ public void registerListener(DeviceStateListener callback) {
+ final var state = getDeviceState();
+ mCallbackExecutor.execute(
+ () -> callback.onSoundTriggerDeviceStateUpdate(state));
+ mCallbackSet.add(callback);
+ }
+
+ public void unregisterListener(DeviceStateListener callback) {
+ mCallbackSet.remove(callback);
+ }
+
+ void dump(PrintWriter pw) {
+ synchronized (mLock) {
+ pw.println("DeviceState: " + mSoundTriggerDeviceState.name());
+ pw.println("PhoneState: " + mIsPhoneCallOngoing);
+ pw.println("PowerSaveMode: " + mSoundTriggerPowerSaveMode);
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void evaluateStateChange() {
+ // We should wait until any pending delays are complete to update.
+ // We will eventually get called by the notification task, or something which
+ // cancels it.
+ // Additionally, if there isn't a state change, there is nothing to update.
+ SoundTriggerDeviceState newState = computeState();
+ if (mPhoneStateChangePendingNotify != null || mSoundTriggerDeviceState == newState) {
+ return;
+ }
+
+ mSoundTriggerDeviceState = newState;
+ mEventLogger.enqueue(new DeviceStateEvent(mSoundTriggerDeviceState));
+ final var state = mSoundTriggerDeviceState;
+ for (var callback : mCallbackSet) {
+ mCallbackExecutor.execute(
+ () -> callback.onSoundTriggerDeviceStateUpdate(state));
+ }
+ }
+
+ @GuardedBy("mLock")
+ private SoundTriggerDeviceState computeState() {
+ if (mIsPhoneCallOngoing) {
+ return SoundTriggerDeviceState.DISABLE;
+ }
+ return switch (mSoundTriggerPowerSaveMode) {
+ case SOUND_TRIGGER_MODE_ALL_ENABLED -> SoundTriggerDeviceState.ENABLE;
+ case SOUND_TRIGGER_MODE_CRITICAL_ONLY -> SoundTriggerDeviceState.CRITICAL;
+ case SOUND_TRIGGER_MODE_ALL_DISABLED -> SoundTriggerDeviceState.DISABLE;
+ default -> throw new IllegalStateException(
+ "Received unexpected power state code" + mSoundTriggerPowerSaveMode);
+ };
+ }
+
+ /**
+ * One-shot, cancellable task which runs after a delay. Run must only be called once, from a
+ * single thread. Cancel can be called from any other thread.
+ */
+ private static class NotificationTask implements Runnable {
+ private final Runnable mRunnable;
+ private final long mWaitInMillis;
+
+ private final CountDownLatch mCancelLatch = new CountDownLatch(1);
+
+ NotificationTask(Runnable r, long waitInMillis) {
+ mRunnable = r;
+ mWaitInMillis = waitInMillis;
+ }
+
+ void cancel() {
+ mCancelLatch.countDown();
+ }
+
+ // Used for determining task equality.
+ boolean runnableEquals(Runnable runnable) {
+ return mRunnable == runnable;
+ }
+
+ public void run() {
+ try {
+ if (!mCancelLatch.await(mWaitInMillis, TimeUnit.MILLISECONDS)) {
+ mRunnable.run();
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new AssertionError("Unexpected InterruptedException", e);
+ }
+ }
+ }
+
+ private static class PhoneCallEvent extends EventLogger.Event {
+ final boolean mIsInPhoneCall;
+
+ PhoneCallEvent(boolean isInPhoneCall) {
+ mIsInPhoneCall = isInPhoneCall;
+ }
+
+ @Override
+ public String eventToString() {
+ return "PhoneCallChange - inPhoneCall: " + mIsInPhoneCall;
+ }
+ }
+
+ private static class SoundTriggerPowerEvent extends EventLogger.Event {
+ final int mSoundTriggerPowerState;
+
+ SoundTriggerPowerEvent(int soundTriggerPowerState) {
+ mSoundTriggerPowerState = soundTriggerPowerState;
+ }
+
+ @Override
+ public String eventToString() {
+ return "SoundTriggerPowerChange: " + stateToString();
+ }
+
+ private String stateToString() {
+ return switch (mSoundTriggerPowerState) {
+ case SOUND_TRIGGER_MODE_ALL_ENABLED -> "All enabled";
+ case SOUND_TRIGGER_MODE_CRITICAL_ONLY -> "Critical only";
+ case SOUND_TRIGGER_MODE_ALL_DISABLED -> "All disabled";
+ default -> "Unknown power state: " + mSoundTriggerPowerState;
+ };
+ }
+ }
+
+ private static class DeviceStateEvent extends EventLogger.Event {
+ final SoundTriggerDeviceState mSoundTriggerDeviceState;
+
+ DeviceStateEvent(SoundTriggerDeviceState soundTriggerDeviceState) {
+ mSoundTriggerDeviceState = soundTriggerDeviceState;
+ }
+
+ @Override
+ public String eventToString() {
+ return "DeviceStateChange: " + mSoundTriggerDeviceState.name();
+ }
+ }
+}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/PhoneCallStateHandler.java b/services/voiceinteraction/java/com/android/server/soundtrigger/PhoneCallStateHandler.java
new file mode 100644
index 000000000000..8773cabeeb92
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/PhoneCallStateHandler.java
@@ -0,0 +1,158 @@
+/**
+ * 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.soundtrigger;
+
+import android.telephony.Annotation;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Handles monitoring telephony call state across active subscriptions.
+ *
+ * @hide
+ */
+public class PhoneCallStateHandler {
+
+ public interface Callback {
+ void onPhoneCallStateChanged(boolean isInPhoneCall);
+ }
+
+ private final Object mLock = new Object();
+
+ // Actually never contended due to executor.
+ @GuardedBy("mLock")
+ private final List<MyCallStateListener> mListenerList = new ArrayList<>();
+
+ private final AtomicBoolean mIsPhoneCallOngoing = new AtomicBoolean(false);
+
+ private final SubscriptionManager mSubscriptionManager;
+ private final TelephonyManager mTelephonyManager;
+ private final Callback mCallback;
+
+ private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
+
+ public PhoneCallStateHandler(
+ SubscriptionManager subscriptionManager,
+ TelephonyManager telephonyManager,
+ Callback callback) {
+ mSubscriptionManager = Objects.requireNonNull(subscriptionManager);
+ mTelephonyManager = Objects.requireNonNull(telephonyManager);
+ mCallback = Objects.requireNonNull(callback);
+ mSubscriptionManager.addOnSubscriptionsChangedListener(
+ mExecutor,
+ new SubscriptionManager.OnSubscriptionsChangedListener() {
+ @Override
+ public void onSubscriptionsChanged() {
+ updateTelephonyListeners();
+ }
+
+ @Override
+ public void onAddListenerFailed() {
+ Slog.wtf(
+ "SoundTriggerPhoneCallStateHandler",
+ "Failed to add a telephony listener");
+ }
+ });
+ }
+
+ private final class MyCallStateListener extends TelephonyCallback
+ implements TelephonyCallback.CallStateListener {
+
+ final TelephonyManager mTelephonyManagerForSubId;
+
+ // Manager corresponding to the sub-id
+ MyCallStateListener(TelephonyManager telephonyManager) {
+ mTelephonyManagerForSubId = telephonyManager;
+ }
+
+ void cleanup() {
+ mExecutor.execute(() -> mTelephonyManagerForSubId.unregisterTelephonyCallback(this));
+ }
+
+ @Override
+ public void onCallStateChanged(int unused) {
+ updateCallStatus();
+ }
+ }
+
+ /** Compute the current call status, and dispatch callback if it has changed. */
+ private void updateCallStatus() {
+ boolean callStatus = checkCallStatus();
+ if (mIsPhoneCallOngoing.compareAndSet(!callStatus, callStatus)) {
+ mCallback.onPhoneCallStateChanged(callStatus);
+ }
+ }
+
+ /**
+ * Synchronously query the current telephony call state across all subscriptions
+ *
+ * @return - {@code true} if in call, {@code false} if not in call.
+ */
+ private boolean checkCallStatus() {
+ List<SubscriptionInfo> infoList = mSubscriptionManager.getActiveSubscriptionInfoList();
+ if (infoList == null) return false;
+ return infoList.stream()
+ .filter(s -> (s.getSubscriptionId() != SubscriptionManager.INVALID_SUBSCRIPTION_ID))
+ .anyMatch(s -> isCallOngoingFromState(
+ mTelephonyManager
+ .createForSubscriptionId(s.getSubscriptionId())
+ .getCallStateForSubscription()));
+ }
+
+ private void updateTelephonyListeners() {
+ synchronized (mLock) {
+ for (var listener : mListenerList) {
+ listener.cleanup();
+ }
+ mListenerList.clear();
+ List<SubscriptionInfo> infoList = mSubscriptionManager.getActiveSubscriptionInfoList();
+ if (infoList == null) return;
+ infoList.stream()
+ .filter(s -> s.getSubscriptionId()
+ != SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+ .map(s -> mTelephonyManager.createForSubscriptionId(s.getSubscriptionId()))
+ .forEach(manager -> {
+ synchronized (mLock) {
+ var listener = new MyCallStateListener(manager);
+ mListenerList.add(listener);
+ manager.registerTelephonyCallback(mExecutor, listener);
+ }
+ });
+ }
+ }
+
+ private static boolean isCallOngoingFromState(@Annotation.CallState int callState) {
+ return switch (callState) {
+ case TelephonyManager.CALL_STATE_IDLE, TelephonyManager.CALL_STATE_RINGING -> false;
+ case TelephonyManager.CALL_STATE_OFFHOOK -> true;
+ default -> throw new IllegalStateException(
+ "Received unexpected call state from Telephony Manager: " + callState);
+ };
+ }
+}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index 255db1e4db83..b4066ab1ff39 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -16,15 +16,12 @@
package com.android.server.soundtrigger;
+import static com.android.server.soundtrigger.DeviceStateHandler.SoundTriggerDeviceState;
import static com.android.server.soundtrigger.SoundTriggerEvent.SessionEvent.Type;
import static com.android.server.utils.EventLogger.Event.ALOGW;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.ModelParams;
import android.hardware.soundtrigger.SoundTrigger;
@@ -45,11 +42,7 @@ import android.os.DeadObjectException;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
-import android.os.PowerManager;
-import android.os.PowerManager.SoundTriggerPowerSaveMode;
import android.os.RemoteException;
-import android.telephony.PhoneStateListener;
-import android.telephony.TelephonyManager;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
@@ -99,37 +92,20 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
private SoundTriggerModule mModule;
private final Object mLock = new Object();
private final Context mContext;
- private final TelephonyManager mTelephonyManager;
- private final PhoneStateListener mPhoneStateListener;
- private final PowerManager mPowerManager;
// The SoundTriggerManager layer handles multiple recognition models of type generic and
// keyphrase. We store the ModelData here in a hashmap.
- private final HashMap<UUID, ModelData> mModelDataMap;
+ private final HashMap<UUID, ModelData> mModelDataMap = new HashMap<>();
// An index of keyphrase sound models so that we can reach them easily. We support indexing
// keyphrase sound models with a keyphrase ID. Sound model with the same keyphrase ID will
// replace an existing model, thus there is a 1:1 mapping from keyphrase ID to a voice
// sound model.
- private HashMap<Integer, UUID> mKeyphraseUuidMap;
-
- private boolean mCallActive = false;
- private @SoundTriggerPowerSaveMode int mSoundTriggerPowerSaveMode =
- PowerManager.SOUND_TRIGGER_MODE_ALL_ENABLED;
+ private final HashMap<Integer, UUID> mKeyphraseUuidMap = new HashMap<>();
// Whether ANY recognition (keyphrase or generic) has been requested.
private boolean mRecognitionRequested = false;
- private PowerSaveModeListener mPowerSaveModeListener;
-
-
- // Handler to process call state changes will delay to allow time for the audio
- // and sound trigger HALs to process the end of call notifications
- // before we re enable pending recognition requests.
- private final Handler mHandler;
- private static final int MSG_CALL_STATE_CHANGED = 0;
- private static final int CALL_INACTIVE_MSG_DELAY_MS = 1000;
-
// TODO(b/269366605) Temporary solution to query correct moduleProperties
private final int mModuleId;
private final Function<SoundTrigger.StatusListener, SoundTriggerModule> mModuleProvider;
@@ -139,16 +115,15 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
@GuardedBy("mLock")
private boolean mIsDetached = false;
+ @GuardedBy("mLock")
+ private SoundTriggerDeviceState mDeviceState = SoundTriggerDeviceState.DISABLE;
+
SoundTriggerHelper(Context context, EventLogger eventLogger,
@NonNull Function<SoundTrigger.StatusListener, SoundTriggerModule> moduleProvider,
int moduleId,
@NonNull Supplier<List<ModuleProperties>> modulePropertiesProvider) {
mModuleId = moduleId;
mContext = context;
- mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- mModelDataMap = new HashMap<UUID, ModelData>();
- mKeyphraseUuidMap = new HashMap<Integer, UUID>();
mModuleProvider = moduleProvider;
mEventLogger = eventLogger;
mModulePropertiesProvider = modulePropertiesProvider;
@@ -157,31 +132,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
} else {
mModule = mModuleProvider.apply(this);
}
- Looper looper = Looper.myLooper();
- if (looper == null) {
- looper = Looper.getMainLooper();
- }
- mPhoneStateListener = new MyCallStateListener(looper);
- if (looper != null) {
- mHandler = new Handler(looper) {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_CALL_STATE_CHANGED:
- synchronized (mLock) {
- onCallStateChangedLocked(
- TelephonyManager.CALL_STATE_OFFHOOK == msg.arg1);
- }
- break;
- default:
- Slog.e(TAG, "unknown message in handler:" + msg.what);
- break;
- }
- }
- };
- } else {
- mHandler = null;
- }
}
/**
@@ -373,7 +323,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
modelData.setSoundModel(soundModel);
if (!isRecognitionAllowedByDeviceState(modelData)) {
- initializeDeviceStateListeners();
return STATUS_OK;
}
@@ -497,11 +446,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
modelData.setLoaded();
modelData.clearCallback();
modelData.setRecognitionConfig(null);
-
- if (!computeRecognitionRequestedLocked()) {
- internalClearGlobalStateLocked();
- }
-
return status;
}
}
@@ -638,6 +582,17 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
}
+ public void onDeviceStateChanged(SoundTriggerDeviceState state) {
+ synchronized (mLock) {
+ if (mIsDetached || mDeviceState == state) {
+ // Nothing to update
+ return;
+ }
+ mDeviceState = state;
+ updateAllRecognitionsLocked();
+ }
+ }
+
public int getGenericModelState(UUID modelId) {
synchronized (mLock) {
MetricsLogger.count(mContext, "sth_get_generic_model_state", 1);
@@ -880,25 +835,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
}
- private void onCallStateChangedLocked(boolean callActive) {
- if (mCallActive == callActive) {
- // We consider multiple call states as being active
- // so we check if something really changed or not here.
- return;
- }
- mCallActive = callActive;
- updateAllRecognitionsLocked();
- }
-
- private void onPowerSaveModeChangedLocked(
- @SoundTriggerPowerSaveMode int soundTriggerPowerSaveMode) {
- if (mSoundTriggerPowerSaveMode == soundTriggerPowerSaveMode) {
- return;
- }
- mSoundTriggerPowerSaveMode = soundTriggerPowerSaveMode;
- updateAllRecognitionsLocked();
- }
-
private void onModelUnloadedLocked(int modelHandle) {
ModelData modelData = getModelDataForLocked(modelHandle);
if (modelData != null) {
@@ -1011,10 +947,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
return status;
}
status = startRecognitionLocked(model, notifyClientOnError);
- // Initialize power save, call active state monitoring logic.
- if (status == STATUS_OK) {
- initializeDeviceStateListeners();
- }
return status;
} else {
return stopRecognitionLocked(model, notifyClientOnError);
@@ -1040,7 +972,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
} finally {
internalClearModelStateLocked();
- internalClearGlobalStateLocked();
if (mModule != null) {
mModule.detach();
try {
@@ -1054,24 +985,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
}
- // internalClearGlobalStateLocked() cleans up the telephony and power save listeners.
- private void internalClearGlobalStateLocked() {
- // Unregister from call state changes.
- final long token = Binder.clearCallingIdentity();
- try {
- mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
-
- // Unregister from power save mode changes.
- if (mPowerSaveModeListener != null) {
- mContext.unregisterReceiver(mPowerSaveModeListener);
- mPowerSaveModeListener = null;
- }
- mRecognitionRequested = false;
- }
-
// Clears state for all models (generic and keyphrase).
private void internalClearModelStateLocked() {
for (ModelData modelData : mModelDataMap.values()) {
@@ -1079,67 +992,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
}
}
- class MyCallStateListener extends PhoneStateListener {
- MyCallStateListener(@NonNull Looper looper) {
- super(Objects.requireNonNull(looper));
- }
-
- @Override
- public void onCallStateChanged(int state, String arg1) {
-
- if (mHandler != null) {
- synchronized (mLock) {
- mHandler.removeMessages(MSG_CALL_STATE_CHANGED);
- Message msg = mHandler.obtainMessage(MSG_CALL_STATE_CHANGED, state, 0);
- mHandler.sendMessageDelayed(
- msg, (TelephonyManager.CALL_STATE_OFFHOOK == state) ? 0
- : CALL_INACTIVE_MSG_DELAY_MS);
- }
- }
- }
- }
-
- class PowerSaveModeListener extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (!PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(intent.getAction())) {
- return;
- }
- @SoundTriggerPowerSaveMode int soundTriggerPowerSaveMode =
- mPowerManager.getSoundTriggerPowerSaveMode();
- synchronized (mLock) {
- onPowerSaveModeChangedLocked(soundTriggerPowerSaveMode);
- }
- }
- }
-
- private void initializeDeviceStateListeners() {
- if (mRecognitionRequested) {
- return;
- }
- final long token = Binder.clearCallingIdentity();
- try {
- // Get the current call state synchronously for the first recognition.
- mCallActive = mTelephonyManager.getCallState() == TelephonyManager.CALL_STATE_OFFHOOK;
-
- // Register for call state changes when the first call to start recognition occurs.
- mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
-
- // Register for power saver mode changes when the first call to start recognition
- // occurs.
- if (mPowerSaveModeListener == null) {
- mPowerSaveModeListener = new PowerSaveModeListener();
- mContext.registerReceiver(mPowerSaveModeListener,
- new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
- }
- mSoundTriggerPowerSaveMode = mPowerManager.getSoundTriggerPowerSaveMode();
-
- mRecognitionRequested = true;
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
/**
* Stops and unloads all models. This is intended as a clean-up call with the expectation that
* this instance is not used after.
@@ -1153,7 +1005,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
forceStopAndUnloadModelLocked(model, null);
}
mModelDataMap.clear();
- internalClearGlobalStateLocked();
if (mModule != null) {
mModule.detach();
mModule = null;
@@ -1305,28 +1156,14 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
* @param modelData Model data to be used for recognition
* @return True if recognition is allowed to run at this time. False if not.
*/
+ @GuardedBy("mLock")
private boolean isRecognitionAllowedByDeviceState(ModelData modelData) {
- // if mRecognitionRequested is false, call and power state listeners are not registered so
- // we read current state directly from services
- if (!mRecognitionRequested) {
- mCallActive = mTelephonyManager.getCallState() == TelephonyManager.CALL_STATE_OFFHOOK;
- mSoundTriggerPowerSaveMode = mPowerManager.getSoundTriggerPowerSaveMode();
- }
-
- return !mCallActive && isRecognitionAllowedByPowerState(
- modelData);
- }
-
- /**
- * Helper function to validate if a recognition should run based on the current power state
- *
- * @param modelData Model data to be used for recognition
- * @return True if device state allows recognition to run, false if not.
- */
- private boolean isRecognitionAllowedByPowerState(ModelData modelData) {
- return mSoundTriggerPowerSaveMode == PowerManager.SOUND_TRIGGER_MODE_ALL_ENABLED
- || (mSoundTriggerPowerSaveMode == PowerManager.SOUND_TRIGGER_MODE_CRITICAL_ONLY
- && modelData.shouldRunInBatterySaverMode());
+ return switch (mDeviceState) {
+ case DISABLE -> false;
+ case CRITICAL -> modelData.shouldRunInBatterySaverMode();
+ case ENABLE -> true;
+ default -> throw new AssertionError("Enum changed between compile and runtime");
+ };
}
// A single routine that implements the start recognition logic for both generic and keyphrase
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 913535e06a21..3151781ff7ba 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -35,14 +35,18 @@ import static com.android.server.soundtrigger.SoundTriggerEvent.SessionEvent.Typ
import static com.android.server.utils.EventLogger.Event.ALOGW;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+import static com.android.server.soundtrigger.DeviceStateHandler.DeviceStateListener;
+import static com.android.server.soundtrigger.DeviceStateHandler.SoundTriggerDeviceState;
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityThread;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.PermissionChecker;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
@@ -85,6 +89,8 @@ import android.os.ServiceSpecificException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.SparseArray;
@@ -112,6 +118,8 @@ import java.util.Objects;
import java.util.TreeMap;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -131,8 +139,8 @@ public class SoundTriggerService extends SystemService {
private static final boolean DEBUG = true;
private static final int SESSION_MAX_EVENT_SIZE = 128;
- final Context mContext;
- private Object mLock;
+ private final Context mContext;
+ private final Object mLock = new Object();
private final SoundTriggerServiceStub mServiceStub;
private final LocalSoundTriggerService mLocalSoundTriggerService;
@@ -140,6 +148,7 @@ public class SoundTriggerService extends SystemService {
private SoundTriggerDbHelper mDbHelper;
private final EventLogger mServiceEventLogger = new EventLogger(256, "Service");
+ private final EventLogger mDeviceEventLogger = new EventLogger(256, "Device Event");
private final Set<EventLogger> mSessionEventLoggers = ConcurrentHashMap.newKeySet(4);
private final Deque<EventLogger> mDetachedSessionEventLoggers = new LinkedBlockingDeque<>(4);
@@ -223,13 +232,18 @@ public class SoundTriggerService extends SystemService {
@GuardedBy("mLock")
private final ArrayMap<String, NumOps> mNumOpsPerPackage = new ArrayMap<>();
+ private final DeviceStateHandler mDeviceStateHandler;
+ private final Executor mDeviceStateHandlerExecutor = Executors.newSingleThreadExecutor();
+ private PhoneCallStateHandler mPhoneCallStateHandler;
+
public SoundTriggerService(Context context) {
super(context);
mContext = context;
mServiceStub = new SoundTriggerServiceStub();
mLocalSoundTriggerService = new LocalSoundTriggerService(context);
- mLock = new Object();
mSoundModelStatTracker = new SoundModelStatTracker();
+ mDeviceStateHandler = new DeviceStateHandler(mDeviceStateHandlerExecutor,
+ mDeviceEventLogger);
}
@Override
@@ -243,6 +257,29 @@ public class SoundTriggerService extends SystemService {
Slog.d(TAG, "onBootPhase: " + phase + " : " + isSafeMode());
if (PHASE_THIRD_PARTY_APPS_CAN_START == phase) {
mDbHelper = new SoundTriggerDbHelper(mContext);
+ final PowerManager powerManager = mContext.getSystemService(PowerManager.class);
+ // Hook up power state listener
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (!PowerManager.ACTION_POWER_SAVE_MODE_CHANGED
+ .equals(intent.getAction())) {
+ return;
+ }
+ mDeviceStateHandler.onPowerModeChanged(
+ powerManager.getSoundTriggerPowerSaveMode());
+ }
+ }, new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
+ // Initialize the initial power state
+ // Do so after registering the listener so we ensure that we don't drop any events
+ mDeviceStateHandler.onPowerModeChanged(powerManager.getSoundTriggerPowerSaveMode());
+
+ // PhoneCallStateHandler initializes the original call state
+ mPhoneCallStateHandler = new PhoneCallStateHandler(
+ mContext.getSystemService(SubscriptionManager.class),
+ mContext.getSystemService(TelephonyManager.class),
+ mDeviceStateHandler);
}
mMiddlewareService = ISoundTriggerMiddlewareService.Stub.asInterface(
ServiceManager.waitForService(Context.SOUND_TRIGGER_MIDDLEWARE_SERVICE));
@@ -380,6 +417,9 @@ public class SoundTriggerService extends SystemService {
// Event loggers
pw.println("##Service-Wide logs:");
mServiceEventLogger.dump(pw, /* indent = */ " ");
+ pw.println("\n##Device state logs:");
+ mDeviceStateHandler.dump(pw);
+ mDeviceEventLogger.dump(pw, /* indent = */ " ");
pw.println("\n##Active Session dumps:\n");
for (var sessionLogger : mSessionEventLoggers) {
@@ -403,6 +443,7 @@ public class SoundTriggerService extends SystemService {
class SoundTriggerSessionStub extends ISoundTriggerSession.Stub {
private final SoundTriggerHelper mSoundTriggerHelper;
+ private final DeviceStateListener mListener;
// Used to detect client death.
private final IBinder mClient;
private final Identity mOriginatorIdentity;
@@ -424,6 +465,9 @@ public class SoundTriggerService extends SystemService {
} catch (RemoteException e) {
clientDied();
}
+ mListener = (SoundTriggerDeviceState state)
+ -> mSoundTriggerHelper.onDeviceStateChanged(state);
+ mDeviceStateHandler.registerListener(mListener);
}
@Override
@@ -874,6 +918,7 @@ public class SoundTriggerService extends SystemService {
}
private void detach() {
+ mDeviceStateHandler.unregisterListener(mListener);
mSoundTriggerHelper.detach();
detachSessionLogger(mEventLogger);
}
@@ -890,7 +935,8 @@ public class SoundTriggerService extends SystemService {
private void enforceDetectionPermissions(ComponentName detectionService) {
PackageManager packageManager = mContext.getPackageManager();
String packageName = detectionService.getPackageName();
- if (packageManager.checkPermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD, packageName)
+ if (packageManager.checkPermission(
+ Manifest.permission.CAPTURE_AUDIO_HOTWORD, packageName)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException(detectionService.getPackageName() + " does not have"
+ " permission " + Manifest.permission.CAPTURE_AUDIO_HOTWORD);
@@ -1576,6 +1622,7 @@ public class SoundTriggerService extends SystemService {
private final @NonNull IBinder mClient;
private final EventLogger mEventLogger;
private final Identity mOriginatorIdentity;
+ private final @NonNull DeviceStateListener mListener;
private final SparseArray<UUID> mModelUuid = new SparseArray<>(1);
@@ -1594,6 +1641,9 @@ public class SoundTriggerService extends SystemService {
} catch (RemoteException e) {
clientDied();
}
+ mListener = (SoundTriggerDeviceState state)
+ -> mSoundTriggerHelper.onDeviceStateChanged(state);
+ mDeviceStateHandler.registerListener(mListener);
}
@Override
@@ -1662,6 +1712,7 @@ public class SoundTriggerService extends SystemService {
private void detachInternal() {
mEventLogger.enqueue(new SessionEvent(Type.DETACH, null));
detachSessionLogger(mEventLogger);
+ mDeviceStateHandler.unregisterListener(mListener);
mSoundTriggerHelper.detach();
}
}
diff --git a/tests/FlickerTests/AndroidTest.xml b/tests/FlickerTests/AndroidTest.xml
index 7272abba897d..32ff243921ec 100644
--- a/tests/FlickerTests/AndroidTest.xml
+++ b/tests/FlickerTests/AndroidTest.xml
@@ -21,6 +21,9 @@
<option name="run-command" value="setprop ro.test_harness 1 ; am force-stop com.google.android.apps.nexuslauncher" />
<!-- Ensure output directory is empty at the start -->
<option name="run-command" value="rm -rf /sdcard/flicker" />
+ <!-- Increase trace size: 20mb for WM and 80mb for SF -->
+ <option name="run-command" value="cmd window tracing size 20480" />
+ <option name="run-command" value="su root service call SurfaceFlinger 1029 i32 81920" />
</target_preparer>
<target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
<option name="run-command" value="settings put secure show_ime_with_hard_keyboard 1" />