summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AconfigFlags.bp1
-rw-r--r--apct-tests/perftests/tracing/Android.bp1
-rw-r--r--apct-tests/perftests/tracing/src/com/android/internal/protolog/ProtoLogPerfTest.java37
-rw-r--r--apex/blobstore/OWNERS2
-rw-r--r--apex/jobscheduler/service/aconfig/job.aconfig7
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java12
-rw-r--r--config/dirty-image-objects3129
-rw-r--r--core/api/current.txt2
-rw-r--r--core/api/test-current.txt3
-rw-r--r--core/java/android/app/ActivityThread.java14
-rw-r--r--core/java/android/app/ApplicationPackageManager.java11
-rw-r--r--core/java/android/app/PropertyInvalidatedCache.java11
-rw-r--r--core/java/android/app/TaskInfo.java15
-rw-r--r--core/java/android/app/metrics.aconfig10
-rw-r--r--core/java/android/app/notification.aconfig9
-rw-r--r--core/java/android/content/Intent.java37
-rw-r--r--core/java/android/content/pm/flags.aconfig8
-rw-r--r--core/java/android/database/DatabaseUtils.java55
-rw-r--r--core/java/android/database/sqlite/SQLiteConnection.java15
-rw-r--r--core/java/android/database/sqlite/flags.aconfig16
-rw-r--r--core/java/android/hardware/biometrics/flags.aconfig8
-rw-r--r--core/java/android/hardware/display/AmbientDisplayConfiguration.java8
-rw-r--r--core/java/android/hardware/input/KeyGestureEvent.java7
-rw-r--r--core/java/android/hardware/soundtrigger/ConversionUtil.java20
-rw-r--r--core/java/android/hardware/soundtrigger/SoundTrigger.java33
-rw-r--r--core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java2
-rw-r--r--core/java/android/net/vcn/VcnManager.java8
-rw-r--r--core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java2
-rw-r--r--core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java2
-rw-r--r--core/java/android/os/BatteryUsageStats.java62
-rw-r--r--core/java/android/os/VibratorInfo.java7
-rw-r--r--core/java/android/provider/Settings.java114
-rw-r--r--core/java/android/security/forensic/ForensicEvent.aidl20
-rw-r--r--core/java/android/security/forensic/ForensicEvent.java84
-rw-r--r--core/java/android/security/forensic/IBackupTransport.aidl41
-rw-r--r--core/java/android/security/responsible_apis_flags.aconfig7
-rw-r--r--core/java/android/service/voice/AlwaysOnHotwordDetector.java23
-rw-r--r--core/java/android/telephony/PhoneStateListener.java5
-rw-r--r--core/java/android/telephony/TelephonyCallback.java40
-rw-r--r--core/java/android/telephony/TelephonyRegistryManager.java20
-rw-r--r--core/java/android/view/ViewRootImpl.java10
-rw-r--r--core/java/android/window/BackEvent.java9
-rw-r--r--core/java/android/window/flags/lse_desktop_experience.aconfig7
-rw-r--r--core/java/android/window/flags/windowing_frontend.aconfig8
-rw-r--r--core/java/com/android/internal/jank/FrameTracker.java106
-rw-r--r--core/java/com/android/internal/jank/flags.aconfig7
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHistory.java5
-rw-r--r--core/java/com/android/internal/os/LongArrayMultiStateCounter.java9
-rw-r--r--core/java/com/android/internal/os/ProcfsMemoryUtil.java (renamed from services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java)74
-rw-r--r--core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java48
-rw-r--r--core/java/com/android/internal/protolog/AutoClosableProtoInputStream.java56
-rw-r--r--core/java/com/android/internal/protolog/NoViewerConfigProtoLogImpl.java90
-rw-r--r--core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java208
-rw-r--r--core/java/com/android/internal/protolog/ProcessedPerfettoProtoLogImpl.java172
-rw-r--r--core/java/com/android/internal/protolog/ProtoLog.java8
-rw-r--r--core/java/com/android/internal/protolog/ProtoLogConfigurationServiceImpl.java2
-rw-r--r--core/java/com/android/internal/protolog/ProtoLogImpl.java53
-rw-r--r--core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java113
-rw-r--r--core/java/com/android/internal/protolog/UnprocessedPerfettoProtoLogImpl.java61
-rw-r--r--core/java/com/android/internal/protolog/Utils.java4
-rw-r--r--core/java/com/android/internal/protolog/ViewerConfigInputStreamProvider.java4
-rw-r--r--core/java/com/android/internal/telephony/IPhoneStateListener.aidl1
-rw-r--r--core/java/com/android/internal/telephony/ITelephonyRegistry.aidl1
-rw-r--r--core/jni/AndroidRuntime.cpp16
-rw-r--r--core/res/res/values/config.xml6
-rw-r--r--core/res/res/values/symbols.xml6
-rw-r--r--core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java1
-rw-r--r--core/tests/vibrator/src/android/os/VibratorInfoTest.java6
-rw-r--r--data/fonts/Android.bp15
-rw-r--r--data/fonts/font_fallback.xml950
-rw-r--r--data/fonts/font_fallback_cjkvf.xml966
-rw-r--r--data/fonts/fonts.xml140
-rw-r--r--data/fonts/fonts_cjkvf.xml1795
-rw-r--r--keystore/java/android/security/OWNERS2
-rw-r--r--keystore/tests/OWNERS5
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java99
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java36
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java12
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java4
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java8
-rw-r--r--libs/WindowManager/Shell/AndroidManifest.xml1
-rw-r--r--libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/UiEventSubject.kt40
-rw-r--r--libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/UiEventSubjectTest.kt147
-rw-r--r--libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java52
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandler.kt2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt112
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt15
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt130
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt15
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepository.kt13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java107
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java23
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java64
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java21
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java60
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java9
-rw-r--r--libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt36
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java17
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandlerTest.kt27
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt3
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt51
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt333
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepositoryTest.kt10
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java1
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt49
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java5
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java10
-rw-r--r--libs/hwui/tests/common/scenes/WindowBlurKawase.cpp141
-rw-r--r--libs/hwui/tests/common/scenes/WindowBlurSkia.cpp104
-rw-r--r--libs/hwui/utils/Color.cpp4
-rw-r--r--media/java/android/media/soundtrigger/SoundTriggerDetector.java13
-rw-r--r--packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml2
-rw-r--r--packages/SettingsLib/MainSwitchPreference/res/layout-v33/settingslib_main_switch_bar.xml2
-rw-r--r--packages/SettingsLib/MainSwitchPreference/res/layout-v35/settingslib_expressive_main_switch_layout.xml33
-rw-r--r--packages/SettingsLib/MainSwitchPreference/res/layout/settingslib_main_switch_bar.xml6
-rw-r--r--packages/SettingsLib/MainSwitchPreference/res/layout/settingslib_main_switch_layout.xml4
-rw-r--r--packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java6
-rw-r--r--packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceTypes.kt8
-rw-r--r--packages/SettingsLib/Preference/Android.bp1
-rw-r--r--packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindingFactory.kt2
-rw-r--r--packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt26
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java18
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioRepository.kt17
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java57
-rw-r--r--packages/SettingsProvider/Android.bp1
-rw-r--r--packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java9
-rw-r--r--packages/SystemUI/Android.bp20
-rw-r--r--packages/SystemUI/aconfig/systemui.aconfig27
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt16
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt10
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt10
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt16
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt11
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt48
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt63
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt9
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt65
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestReplaceOverlayTransition.kt109
-rw-r--r--packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt16
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt38
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekbarHapticPluginTest.kt7
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt242
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt57
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt16
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorTest.kt11
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractorTest.kt3
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardMediaKeyInteractorTest.kt171
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt5
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/IssueRecordingServiceSessionTest.kt4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/FakeScreenshotPolicy.kt40
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt35
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt185
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/PrivacyDotViewControllerTest.kt6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java128
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractorTest.kt99
-rw-r--r--packages/SystemUI/res/values/strings.xml4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIApplication.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/domain/startable/BouncerStartable.kt43
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModel.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/haptics/slider/SeekbarHapticPlugin.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProvider.kt46
-rw-r--r--packages/SystemUI/src/com/android/systemui/haptics/slider/compose/ui/SliderHapticsViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt88
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutCategoryUi.kt34
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutsUiState.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt86
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractor.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardMediaKeyInteractor.kt103
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt47
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceSession.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt51
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicyImpl.kt189
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/UserContextProvider.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/LockscreenHostedDreamGestureListener.kt72
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAware.kt33
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt118
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionCache.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/EnsureEnrViewsVisibility.kt61
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/icon/AppIconProvider.kt61
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/icon/NotificationIconStyleProvider.kt48
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationForwarder.kt31
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt49
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureRecognizer.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/GestureFlowAdapter.kt30
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/GestureRecognizer.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/HomeGestureRecognizer.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/RecentAppsGestureRecognizer.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractor.kt84
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/shared/model/VolumeDialogRingerModel.kt34
-rw-r--r--packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt36
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java39
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt200
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextViewTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt40
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/CallbackHandlerTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt356
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java5
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/FakeMSDLPlayer.kt9
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/haptics/slider/SliderHapticsViewModelFactoryKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt12
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardMediaKeyInteractorKosmos.kt29
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/settings/BrightnessSliderControllerKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt9
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/icon/AppIconProviderKosmos.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/icon/NotificationIconStyleProviderKosmos.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/window/FakeStatusBarWindowControllerFactory.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/AudioRepositoryKosmos.kt3
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt14
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractorKosmos.kt31
-rw-r--r--ravenwood/Android.bp4
-rw-r--r--ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodConfigState.java4
-rw-r--r--ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java12
-rw-r--r--ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java5
-rw-r--r--ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java9
-rw-r--r--ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java6
-rw-r--r--ravenwood/runtime-helper-src/framework/android/util/StatsEvent.java1035
-rw-r--r--ravenwood/runtime-helper-src/framework/android/util/StatsLog.java478
-rw-r--r--ravenwood/runtime-helper-src/libcore-fake/android/compat/Compatibility.java359
-rw-r--r--ravenwood/runtime-helper-src/libcore-fake/libcore/api/CorePlatformApi.java69
-rw-r--r--ravenwood/runtime-helper-src/libcore-fake/libcore/api/Hide.java47
-rw-r--r--ravenwood/runtime-helper-src/libcore-fake/libcore/api/IntraCoreApi.java45
-rw-r--r--ravenwood/runtime-helper-src/libcore-fake/libcore/util/NonNull.java48
-rw-r--r--ravenwood/runtime-helper-src/libcore-fake/libcore/util/Nullable.java48
-rw-r--r--ravenwood/texts/ravenwood-framework-policies.txt4
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java122
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java4
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java5
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java6
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java60
-rw-r--r--services/core/java/com/android/server/VcnManagementService.java23
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java8
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java15
-rw-r--r--services/core/java/com/android/server/am/ProcessErrorStateRecord.java4
-rw-r--r--services/core/java/com/android/server/display/BrightnessRangeController.java4
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java2
-rw-r--r--services/core/java/com/android/server/display/HighBrightnessModeController.java18
-rw-r--r--services/core/java/com/android/server/input/InputManagerInternal.java8
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java9
-rw-r--r--services/core/java/com/android/server/input/KeyGestureController.java13
-rw-r--r--services/core/java/com/android/server/input/PointerIconCache.java37
-rw-r--r--services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java61
-rw-r--r--services/core/java/com/android/server/notification/NotificationAttentionHelper.java50
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java8
-rw-r--r--services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java69
-rw-r--r--services/core/java/com/android/server/power/PowerManagerShellCommand.java22
-rw-r--r--services/core/java/com/android/server/power/stats/AccumulatedBatteryUsageStatsSection.java5
-rw-r--r--services/core/java/com/android/server/power/stats/BatteryStatsImpl.java3
-rw-r--r--services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java42
-rw-r--r--services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java11
-rw-r--r--services/core/java/com/android/server/power/stats/PowerStatsSpan.java15
-rw-r--r--services/core/java/com/android/server/power/stats/PowerStatsStore.java7
-rw-r--r--services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java12
-rw-r--r--services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java26
-rw-r--r--services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java9
-rw-r--r--services/core/java/com/android/server/security/forensic/BackupTransportConnection.java153
-rw-r--r--services/core/java/com/android/server/security/forensic/ForensicService.java14
-rw-r--r--services/core/java/com/android/server/stats/pull/StatsPullAtomService.java9
-rw-r--r--services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java2
-rw-r--r--services/core/java/com/android/server/vcn/Vcn.java2
-rw-r--r--services/core/java/com/android/server/vcn/VcnGatewayConnection.java2
-rw-r--r--services/core/java/com/android/server/vcn/VcnNetworkProvider.java2
-rw-r--r--services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java2
-rw-r--r--services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java2
-rw-r--r--services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java2
-rw-r--r--services/core/java/com/android/server/wm/ActivityStartController.java6
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java117
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskSupervisor.java13
-rw-r--r--services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java54
-rw-r--r--services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java27
-rw-r--r--services/core/java/com/android/server/wm/BackNavigationController.java19
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java56
-rw-r--r--services/core/java/com/android/server/wm/Task.java59
-rw-r--r--services/core/java/com/android/server/wm/TaskFragment.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java11
-rw-r--r--services/core/java/com/android/server/wm/utils/RegionUtils.java11
-rw-r--r--services/java/com/android/server/SystemServer.java13
-rw-r--r--services/tests/PackageManagerServiceTests/appenumeration/Android.bp1
-rw-r--r--services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java5
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java475
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/BackgroundUserSoundNotifierTest.java83
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java2
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java4
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsAtomTest.java11
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java36
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java13
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java40
-rw-r--r--services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java9
-rw-r--r--services/tests/security/forensic/src/com/android/server/security/forensic/ForensicServiceTest.java41
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java166
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java23
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java23
-rw-r--r--services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java92
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java7
-rw-r--r--services/tests/voiceinteractiontests/src/com/android/server/soundtrigger/ConversionUtilTest.java21
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java15
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java46
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java60
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java23
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteManager.java16
-rw-r--r--tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt7
-rw-r--r--tests/Input/Android.bp1
-rw-r--r--tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt21
-rw-r--r--tests/Input/src/com/android/server/input/PointerIconCacheTest.kt135
-rw-r--r--tests/Tracing/src/com/android/internal/protolog/ProcessedPerfettoProtoLogImplTest.java (renamed from tests/Tracing/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java)43
-rw-r--r--tests/Tracing/src/com/android/internal/protolog/ProtoLogTest.java10
-rw-r--r--tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java34
-rw-r--r--tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfaces.kt2
386 files changed, 11571 insertions, 8531 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index deb6f1393b0a..1ae9ada41338 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -789,7 +789,6 @@ java_aconfig_library {
min_sdk_version: "30",
apex_available: [
"//apex_available:platform",
- "com.android.healthfitness",
"com.android.permission",
"com.android.nfcservices",
],
diff --git a/apct-tests/perftests/tracing/Android.bp b/apct-tests/perftests/tracing/Android.bp
index 08e365be514a..8814216644d7 100644
--- a/apct-tests/perftests/tracing/Android.bp
+++ b/apct-tests/perftests/tracing/Android.bp
@@ -22,6 +22,7 @@ android_test {
"apct-perftests-utils",
"collector-device-lib",
"platform-test-annotations",
+ "perfetto_trace_java_protos",
],
test_suites: [
"device-tests",
diff --git a/apct-tests/perftests/tracing/src/com/android/internal/protolog/ProtoLogPerfTest.java b/apct-tests/perftests/tracing/src/com/android/internal/protolog/ProtoLogPerfTest.java
index f4759b8bd35c..7ef8c53d1d62 100644
--- a/apct-tests/perftests/tracing/src/com/android/internal/protolog/ProtoLogPerfTest.java
+++ b/apct-tests/perftests/tracing/src/com/android/internal/protolog/ProtoLogPerfTest.java
@@ -17,10 +17,12 @@ package com.android.internal.protolog;
import android.app.Activity;
import android.os.Bundle;
+import android.os.ServiceManager.ServiceNotFoundException;
import android.perftests.utils.Stats;
import androidx.test.InstrumentationRegistry;
+import com.android.internal.protolog.common.IProtoLog;
import com.android.internal.protolog.common.IProtoLogGroup;
import com.android.internal.protolog.common.LogLevel;
@@ -31,6 +33,8 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
+import perfetto.protos.ProtologCommon;
+
import java.util.ArrayList;
import java.util.Collection;
@@ -65,24 +69,48 @@ public class ProtoLogPerfTest {
};
}
+ private IProtoLog mProcessedProtoLogger;
+ private static final String MOCK_TEST_FILE_PATH = "mock/file/path";
+ private static final perfetto.protos.Protolog.ProtoLogViewerConfig VIEWER_CONFIG =
+ perfetto.protos.Protolog.ProtoLogViewerConfig.newBuilder()
+ .addGroups(
+ perfetto.protos.Protolog.ProtoLogViewerConfig.Group.newBuilder()
+ .setId(1)
+ .setName(TestProtoLogGroup.TEST_GROUP.toString())
+ .setTag(TestProtoLogGroup.TEST_GROUP.getTag())
+ ).addMessages(
+ perfetto.protos.Protolog.ProtoLogViewerConfig.MessageData.newBuilder()
+ .setMessageId(123)
+ .setMessage("My Test Debug Log Message %b")
+ .setLevel(ProtologCommon.ProtoLogLevel.PROTOLOG_LEVEL_DEBUG)
+ .setGroupId(1)
+ .setLocation("com/test/MyTestClass.java:123")
+ ).build();
+
@BeforeClass
public static void init() {
ProtoLog.init(TestProtoLogGroup.values());
}
@Before
- public void setUp() {
+ public void setUp() throws ServiceNotFoundException {
TestProtoLogGroup.TEST_GROUP.setLogToProto(mLogToProto);
TestProtoLogGroup.TEST_GROUP.setLogToLogcat(mLogToLogcat);
+
+ mProcessedProtoLogger = new ProcessedPerfettoProtoLogImpl(
+ MOCK_TEST_FILE_PATH,
+ () -> new AutoClosableProtoInputStream(VIEWER_CONFIG.toByteArray()),
+ () -> {},
+ TestProtoLogGroup.values()
+ );
}
@Test
public void log_Processed_NoArgs() {
- final var protoLog = ProtoLog.getSingleInstance();
final var perfMonitor = new PerfMonitor();
while (perfMonitor.keepRunning()) {
- protoLog.log(
+ mProcessedProtoLogger.log(
LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 123,
0, (Object[]) null);
}
@@ -90,11 +118,10 @@ public class ProtoLogPerfTest {
@Test
public void log_Processed_WithArgs() {
- final var protoLog = ProtoLog.getSingleInstance();
final var perfMonitor = new PerfMonitor();
while (perfMonitor.keepRunning()) {
- protoLog.log(
+ mProcessedProtoLogger.log(
LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 123,
0b1110101001010100,
new Object[]{"test", 1, 2, 3, 0.4, 0.5, 0.6, true});
diff --git a/apex/blobstore/OWNERS b/apex/blobstore/OWNERS
index 676cbc7eb2a3..f8208830d83e 100644
--- a/apex/blobstore/OWNERS
+++ b/apex/blobstore/OWNERS
@@ -1,4 +1,4 @@
-# Bug component: 25692
+# Bug component: 1628187
set noparent
sudheersai@google.com
diff --git a/apex/jobscheduler/service/aconfig/job.aconfig b/apex/jobscheduler/service/aconfig/job.aconfig
index 98e53ab97872..810be8fc4220 100644
--- a/apex/jobscheduler/service/aconfig/job.aconfig
+++ b/apex/jobscheduler/service/aconfig/job.aconfig
@@ -88,4 +88,11 @@ flag {
namespace: "backstage_power"
description: "Adjust quota default parameters"
bug: "347058927"
+}
+
+flag {
+ name: "enforce_quota_policy_to_top_started_jobs"
+ namespace: "backstage_power"
+ description: "Apply the quota policy to jobs started when the app was in TOP state"
+ bug: "374323858"
} \ No newline at end of file
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 885bad5e31c8..37e2fe2e46f1 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -619,7 +619,7 @@ public final class QuotaController extends StateController {
}
final int uid = jobStatus.getSourceUid();
- if (mTopAppCache.get(uid)) {
+ if (!Flags.enforceQuotaPolicyToTopStartedJobs() && mTopAppCache.get(uid)) {
if (DEBUG) {
Slog.d(TAG, jobStatus.toShortString() + " is top started job");
}
@@ -656,7 +656,9 @@ public final class QuotaController extends StateController {
timer.stopTrackingJob(jobStatus);
}
}
- mTopStartedJobs.remove(jobStatus);
+ if (!Flags.enforceQuotaPolicyToTopStartedJobs()) {
+ mTopStartedJobs.remove(jobStatus);
+ }
}
@Override
@@ -767,7 +769,7 @@ public final class QuotaController extends StateController {
/** @return true if the job was started while the app was in the TOP state. */
private boolean isTopStartedJobLocked(@NonNull final JobStatus jobStatus) {
- return mTopStartedJobs.contains(jobStatus);
+ return !Flags.enforceQuotaPolicyToTopStartedJobs() && mTopStartedJobs.contains(jobStatus);
}
/** Returns the maximum amount of time this job could run for. */
@@ -4379,11 +4381,13 @@ public final class QuotaController extends StateController {
@Override
public void dumpControllerStateLocked(final IndentingPrintWriter pw,
final Predicate<JobStatus> predicate) {
- pw.println("Flags: ");
+ pw.println("Aconfig Flags:");
pw.println(" " + Flags.FLAG_ADJUST_QUOTA_DEFAULT_CONSTANTS
+ ": " + Flags.adjustQuotaDefaultConstants());
pw.println(" " + Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_FGS_JOBS
+ ": " + Flags.enforceQuotaPolicyToFgsJobs());
+ pw.println(" " + Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS
+ + ": " + Flags.enforceQuotaPolicyToTopStartedJobs());
pw.println();
pw.println("Current elapsed time: " + sElapsedRealtimeClock.millis());
diff --git a/config/dirty-image-objects b/config/dirty-image-objects
index f2e2b82cd82a..d4913d8f70d7 100644
--- a/config/dirty-image-objects
+++ b/config/dirty-image-objects
@@ -1,5 +1,5 @@
#
-# Copyright (C) 2017 The Android Open Source Project
+# Copyright (C) 2024 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.
@@ -19,1710 +19,1435 @@
# The image writer will bin these objects together in the image.
# More info about dirty objects format and how to collect the data can be
# found in: art/imgdiag/dirty_image_objects.md
-# This particular file was generated by dumping all pre-installed apps.
+# This particular file was generated by:
+# https://android-build.corp.google.com/test_investigate/invocation/I55400010326683472/
#
-Landroid/text/style/URLSpan; 0
-Landroid/content/res/Resources$NotFoundException; 1
-Landroid/os/PowerManager$WakeLock; 2
-Landroid/os/BatterySaverPolicyConfig; 2
-Landroid/content/ContextWrapper; 2
-Landroid/app/WallpaperInfo; 2
-Landroid/content/pm/PackageManager; 2
-Landroid/app/IWallpaperManager; 2
-Ljava/lang/BootClassLoader; 2
-Ljava/time/Duration; 2
-Landroid/util/Printer; 2
-Landroid/app/WallpaperManager$OnColorsChangedListener; 2
-Landroid/app/WallpaperColors; 2
-Landroid/content/pm/ServiceInfo; 2
-Landroid/app/KeyguardManager$KeyguardDismissCallback; 2
-Ljava/lang/CharSequence; 3
-Landroid/widget/Switch; 4
-Lcom/android/internal/util/ContrastColorUtil; 4
-Landroid/view/SurfaceControl; 4
-Landroid/graphics/ColorMatrix;.dexCache:Ljava/lang/Object; 4
-Lcom/android/internal/widget/CachingIconView; 4
-Landroid/window/IRemoteTransition$Stub$Proxy; 4
-Landroid/app/trust/TrustManager$TrustListener; 4
-Landroid/view/NotificationHeaderView; 4
-Lcom/android/internal/widget/ImageResolver; 4
-Landroid/window/WindowContainerTransaction$Change; 4
-Lcom/android/internal/widget/MessagingLayout; 4
-Ljava/util/concurrent/ConcurrentLinkedQueue; 4
-Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry; 4
-Landroid/view/RemotableViewMethod; 4
-Landroid/app/IApplicationThread$Stub$Proxy; 4
-Landroid/os/FileUtils; 4
-Landroid/view/View;.SCALE_X:Landroid/util/Property; 4
-Landroid/widget/GridLayout;.UNDEFINED_ALIGNMENT:Landroid/widget/GridLayout$Alignment; 4
-Landroid/media/MediaPlayer$EventHandler; 4
-Landroid/widget/DateTimeView; 4
-Llibcore/util/ZoneInfo; 4
-Lcom/android/internal/statusbar/IStatusBarService; 4
-Ljava/lang/invoke/MethodType;.internTable:Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet;.stale:Ljava/lang/ref/ReferenceQueue; 4
-Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry; 4
-Lcom/android/internal/logging/UiEventLogger; 4
-Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry; 4
-Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry; 4
-Landroid/renderscript/RenderScript; 4
-Landroid/view/ViewTreeObserver$OnWindowVisibilityChangeListener; 4
-Lcom/android/internal/widget/RemeasuringLinearLayout; 4
-Landroid/widget/DateTimeView$ReceiverInfo$1; 4
-Landroid/view/View;.TRANSLATION_Y:Landroid/util/Property; 4
-Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry; 4
-Lcom/android/internal/widget/NotificationExpandButton; 4
-Lcom/android/internal/view/menu/ActionMenuItemView; 4
-Landroid/view/animation/AnimationSet; 4
-Landroid/hardware/biometrics/BiometricSourceType;.FINGERPRINT:Landroid/hardware/biometrics/BiometricSourceType; 4
-Landroid/window/WindowOrganizer;.IWindowOrganizerControllerSingleton:Landroid/util/Singleton; 4
-Ljava/lang/Runnable; 4
-Lorg/apache/harmony/dalvik/ddmc/DdmServer;.mHandlerMap:Ljava/util/HashMap; 4
-Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry; 4
-Lcom/android/internal/widget/ImageFloatingTextView; 4
-Landroid/window/IWindowContainerToken$Stub$Proxy; 4
-Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry; 4
-Landroid/content/res/ColorStateList; 4
-Landroid/view/View;.SCALE_Y:Landroid/util/Property; 4
-Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap; 4
-Lcom/android/internal/widget/ConversationLayout; 4
-Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry;.right:Ljava/util/TreeMap$TreeMapEntry; 4
-Lcom/android/internal/colorextraction/ColorExtractor$OnColorsChangedListener; 4
-Landroid/hardware/face/FaceManager$FaceDetectionCallback; 4
-Landroid/widget/RemoteViews;.sLookupKey:Landroid/widget/RemoteViews$MethodKey; 4
-Landroid/widget/ViewSwitcher;.dexCache:Ljava/lang/Object; 4
-Lcom/android/internal/widget/NotificationActionListLayout; 4
-Ljava/util/concurrent/ConcurrentLinkedQueue$Node; 4
-Landroid/hardware/biometrics/BiometricSourceType;.FACE:Landroid/hardware/biometrics/BiometricSourceType; 4
-Landroid/hardware/biometrics/BiometricSourceType;.IRIS:Landroid/hardware/biometrics/BiometricSourceType; 4
-Landroid/view/NotificationTopLineView; 4
-Lcom/android/internal/protolog/BaseProtoLogImpl;.LOG_GROUPS:Ljava/util/TreeMap;.root:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry;.left:Ljava/util/TreeMap$TreeMapEntry; 4
-Landroid/widget/RemoteViews;.sMethods:Landroid/util/ArrayMap; 4
-Lcom/android/internal/os/BinderInternal$BinderProxyLimitListener; 5
-Landroid/app/AppOpsManager$OnOpNotedInternalListener; 5
-Lcom/android/internal/R$styleable;.WindowAnimation:[I 5
-Lcom/android/internal/logging/UiEventLogger$UiEventEnum; 5
-Lcom/android/internal/policy/AttributeCache; 5
-Landroid/app/Notification$CallStyle; 5
-Landroid/app/AppOpsManager$OnOpNotedListener; 5
-Lcom/android/internal/protolog/BaseProtoLogImpl; 5
-Landroid/app/AppOpsManager$OnOpStartedListener; 5
-Lcom/android/internal/util/ScreenshotHelper$1; 5
-Landroid/app/Notification$DecoratedCustomViewStyle; 5
-Landroid/view/DisplayCutout; 5
-Landroid/view/InputEvent;.mNextSeq:Ljava/util/concurrent/atomic/AtomicInteger; 5
-Lcom/android/internal/statusbar/NotificationVisibility; 5
-Landroid/telephony/DataSpecificRegistrationInfo; 6
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle; 7
-Landroid/telephony/VoiceSpecificRegistrationInfo; 8
-Landroid/telephony/AnomalyReporter; 8
-Landroid/telephony/TelephonyRegistryManager;.sCarrierPrivilegeCallbacks:Ljava/util/WeakHashMap; 8
-Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.1:Ljava/util/WeakHashMap$Entry; 8
-Landroid/app/LoadedApk$ServiceDispatcher$InnerConnection; 8
-Landroid/content/ContentProvider$Transport; 8
-Landroid/telephony/NetworkRegistrationInfo; 8
-Landroid/net/MatchAllNetworkSpecifier; 8
-Landroid/telephony/TelephonyRegistryManager;.sCarrierPrivilegeCallbacks:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry; 8
-Landroid/app/PropertyInvalidatedCache;.sInvalidates:Ljava/util/HashMap; 9
-Landroid/app/PropertyInvalidatedCache$NoPreloadHolder; 9
-Landroid/app/PropertyInvalidatedCache;.sDisabledKeys:Ljava/util/HashSet;.map:Ljava/util/HashMap; 10
-Landroid/media/AudioSystem$AudioRecordingCallback; 11
-Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedString; 11
-Landroid/net/metrics/IpManagerEvent; 11
-Lcom/android/internal/os/ProcessCpuTracker$FilterStats; 11
-Lcom/android/internal/infra/AbstractRemoteService$AsyncRequest; 11
-Landroid/content/pm/RegisteredServicesCache$3; 11
-Lcom/android/internal/os/LooperStats; 11
-Lcom/android/server/AppWidgetBackupBridge; 11
-Landroid/hardware/display/DisplayManagerInternal; 11
-Landroid/content/pm/PackageInfo; 11
-Landroid/hardware/soundtrigger/SoundTriggerModule$EventHandlerDelegate; 11
-Landroid/app/servertransaction/ResumeActivityItem; 11
-Lcom/android/internal/widget/AlertDialogLayout; 11
-Landroid/content/pm/FallbackCategoryProvider;.sFallbacks:Landroid/util/ArrayMap; 11
-Landroid/os/RemoteCallback$1; 11
-Landroid/content/pm/SharedLibraryInfo; 11
-Landroid/util/MemoryIntArray; 11
-Landroid/net/metrics/DhcpErrorEvent; 11
-Lcom/android/internal/util/function/DodecConsumer; 11
-Landroid/provider/Settings; 11
-Landroid/app/PropertyInvalidatedCache;.sCorkLock:Ljava/lang/Object; 11
-Lcom/android/internal/os/CachedDeviceState$Readonly; 11
-Landroid/app/job/JobServiceEngine$JobHandler; 11
-Landroid/app/SystemServiceRegistry; 11
-Lcom/android/internal/os/BinderInternal$CallStatsObserver; 11
-Lcom/android/internal/statusbar/IStatusBar$Stub$Proxy; 11
-Landroid/hardware/location/IActivityRecognitionHardwareClient; 11
-Landroid/telecom/Logging/EventManager$EventListener; 11
-Landroid/accounts/AccountManagerInternal; 11
-Lcom/android/internal/os/KernelCpuBpfTracking; 11
-Lcom/android/internal/statusbar/NotificationVisibility$NotificationLocation; 11
-Landroid/hardware/camera2/CameraManager$CameraManagerGlobal; 11
-Landroid/os/ServiceSpecificException; 11
-Landroid/net/Uri$PathPart;.NULL:Landroid/net/Uri$PathPart; 11
-Landroid/app/ActivityManagerInternal; 11
-Landroid/media/AudioSystem; 11
-Landroid/service/dreams/DreamManagerInternal; 11
-Landroid/debug/AdbManagerInternal; 11
-Landroid/graphics/Bitmap$CompressFormat; 11
-Landroid/hardware/location/NanoAppMessage; 11
-Landroid/os/storage/StorageManagerInternal; 11
-Landroid/app/AppOpsManagerInternal; 11
-Ljava/security/cert/CertificateException; 11
-Ldalvik/system/VMRuntime; 11
-Landroid/content/pm/SigningInfo; 11
-Landroid/view/KeyEvent; 11
-Lcom/android/internal/view/WindowManagerPolicyThread; 11
-Landroid/graphics/Region;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 11
-Landroid/content/res/ResourceTimer; 11
-Landroid/view/autofill/AutofillManagerInternal; 11
-Lcom/android/internal/util/Parcelling$Cache;.sCache:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object; 11
-Landroid/graphics/Region;.sPool:Landroid/util/Pools$SynchronizedPool; 11
-Landroid/app/LoadedApk$ReceiverDispatcher$Args$$ExternalSyntheticLambda0; 11
-Lcom/android/server/LocalServices;.sLocalServiceObjects:Landroid/util/ArrayMap; 11
-Landroid/app/admin/DevicePolicyManagerInternal$OnCrossProfileWidgetProvidersChangeListener; 11
-Landroid/accounts/AccountManagerInternal$OnAppPermissionChangeListener; 11
-Landroid/content/pm/PermissionInfo; 11
-Landroid/view/WindowManagerPolicyConstants$PointerEventListener; 11
-Landroid/os/UEventObserver; 11
-Landroid/media/AudioManagerInternal$RingerModeDelegate; 11
-Landroid/view/Display$HdrCapabilities; 11
-Landroid/service/notification/Condition; 11
-Landroid/content/pm/UserPackage; 11
-Landroid/app/AppOpsManager$SamplingStrategy; 11
-Landroid/telephony/ServiceState; 11
-Landroid/app/servertransaction/PauseActivityItem; 11
-Lcom/android/internal/util/function/pooled/PooledLambdaImpl;.sMessageCallbacksPool:Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool;.mLock:Ljava/lang/Object; 11
-Landroid/view/KeyCharacterMap$FallbackAction; 11
-Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringArray; 11
-Landroid/hardware/display/DeviceProductInfo; 11
-Lcom/android/internal/util/Parcelling$Cache;.sCache:Landroid/util/ArrayMap;.mHashes:[I 11
-Landroid/content/pm/RegisteredServicesCache$2; 11
-Landroid/content/pm/PackageManager;.sCacheAutoCorker:Landroid/app/PropertyInvalidatedCache$AutoCorker; 11
-Landroid/app/PropertyInvalidatedCache;.sCorks:Ljava/util/HashMap; 11
-Landroid/service/notification/StatusBarNotification; 11
-Landroid/app/servertransaction/ConfigurationChangeItem; 11
-Landroid/app/ActivityManager$RecentTaskInfo; 11
-Landroid/app/Notification; 11
-Landroid/app/servertransaction/DestroyActivityItem; 11
-Landroid/webkit/WebViewLibraryLoader$RelroFileCreator; 11
-Landroid/net/metrics/NetworkEvent; 11
-Landroid/media/AudioPlaybackConfiguration; 11
-Landroid/accessibilityservice/AccessibilityServiceInfo; 11
-Landroid/hardware/display/DeviceProductInfo$ManufactureDate; 11
-Landroid/os/storage/StorageVolume; 11
-Landroid/os/BatteryManagerInternal; 11
-Landroid/appwidget/AppWidgetManagerInternal; 11
-Landroid/app/servertransaction/NewIntentItem; 11
-Landroid/content/pm/ShortcutServiceInternal; 11
-Landroid/app/assist/ActivityId; 11
-Landroid/window/DisplayAreaAppearedInfo; 11
-Landroid/os/Process;.ZYGOTE_PROCESS:Landroid/os/ZygoteProcess;.mLock:Ljava/lang/Object; 11
-Landroid/app/usage/UsageStats; 11
-Landroid/app/Notification$MediaStyle; 11
-Landroid/media/AudioSystem$DynamicPolicyCallback; 11
-Landroid/content/pm/ProviderInfo; 11
-Landroid/os/PowerManagerInternal; 11
-Landroid/service/voice/VoiceInteractionManagerInternal; 11
-Landroid/content/pm/FeatureInfo; 11
-Landroid/app/servertransaction/TopResumedActivityChangeItem; 11
-Landroid/app/Notification$DecoratedMediaCustomViewStyle; 11
-Landroid/appwidget/AppWidgetProviderInfo; 11
-Landroid/app/AppOpsManager$NoteOpEvent; 11
-Landroid/graphics/GraphicsStatsService; 11
-Landroid/view/DisplayAddress$Physical; 11
-Landroid/content/ComponentName$WithComponentName; 11
-Landroid/app/admin/DevicePolicyManagerInternal; 11
-Landroid/os/ResultReceiver$MyResultReceiver; 11
-Landroid/content/ContentProviderClient; 11
-Landroid/content/pm/RegisteredServicesCache$1; 11
-Landroid/app/PendingIntent$FinishedDispatcher; 11
-Landroid/location/LocationManager; 11
-Landroid/hardware/location/ContextHubInfo; 11
-Landroid/content/pm/ShortcutServiceInternal$ShortcutChangeListener; 11
-Lcom/android/server/usage/AppStandbyInternal; 11
-Landroid/content/pm/RegisteredServicesCacheListener; 11
-Landroid/app/servertransaction/LaunchActivityItem; 11
-Landroid/content/pm/BaseParceledListSlice$1; 11
-Landroid/annotation/StringRes; 11
-Lcom/android/internal/R$styleable;.Window:[I 11
-Landroid/service/notification/ZenModeConfig; 11
-Landroid/telecom/Logging/SessionManager$ISessionListener; 11
-Landroid/app/time/TimeZoneConfiguration; 11
-Landroid/net/metrics/ValidationProbeEvent; 11
-Landroid/content/pm/PackageInstaller$SessionInfo; 11
-Landroid/content/pm/UserPackage;.sCache:Landroid/util/SparseArrayMap;.mData:Landroid/util/SparseArray; 11
-Landroid/content/pm/PermissionGroupInfo; 11
-Landroid/hardware/sidekick/SidekickInternal; 11
-Lcom/android/internal/widget/ButtonBarLayout; 11
-Landroid/content/pm/LauncherActivityInfoInternal; 11
-Lcom/android/internal/util/Parcelling$Cache;.sCache:Landroid/util/ArrayMap; 11
-Lcom/android/internal/widget/LockSettingsInternal; 11
-Landroid/media/AudioManagerInternal; 11
-Landroid/app/AppOpsManager$AttributedOpEntry; 11
-Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringList; 11
-Landroid/telecom/Log; 11
-Landroid/app/time/TimeZoneCapabilities; 11
-Landroid/attention/AttentionManagerInternal; 11
-Landroid/view/WindowManagerPolicyConstants; 11
-Landroid/content/pm/CrossProfileAppsInternal; 11
-Landroid/hardware/location/GeofenceHardwareService; 11
-Landroid/content/pm/dex/ArtManagerInternal; 11
-Landroid/net/metrics/IpReachabilityEvent; 11
-Landroid/content/pm/LauncherApps$ShortcutQuery$QueryFlags; 11
-Landroid/media/AudioAttributes; 11
-Landroid/app/PropertyInvalidatedCache$AutoCorker$1; 11
-Landroid/net/metrics/ApfProgramEvent; 11
-Landroid/content/pm/SigningDetails; 11
-Lcom/android/internal/protolog/ProtoLogImpl; 11
-Landroid/hardware/biometrics/ComponentInfoInternal; 11
-Lcom/android/internal/util/ToBooleanFunction; 11
-Landroid/app/ActivityThread$H; 11
-Landroid/hardware/location/GeofenceHardwareImpl; 11
-Landroid/net/wifi/nl80211/WifiNl80211Manager$ScanEventHandler; 11
-Landroid/util/NtpTrustedTime; 11
-Landroid/hardware/soundtrigger/SoundTrigger$StatusListener; 11
-Lcom/android/internal/app/procstats/AssociationState;.sTmpSourceKey:Lcom/android/internal/app/procstats/AssociationState$SourceKey; 11
-Ljava/util/zip/ZipFile$ZipFileInflaterInputStream; 11
-Landroid/app/job/JobInfo; 11
-Lcom/android/internal/content/om/OverlayConfig; 11
-Landroid/webkit/WebViewZygote; 11
-Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringSet; 11
-Lcom/android/internal/infra/AbstractRemoteService$VultureCallback; 11
-Landroid/permission/PermissionManagerInternal; 11
-Lcom/android/server/WidgetBackupProvider; 11
-Landroid/window/WindowOnBackInvokedDispatcher$OnBackInvokedCallbackWrapper; 11
-Landroid/app/PropertyInvalidatedCache;.sCorkedInvalidates:Ljava/util/HashMap; 11
-Landroid/media/AudioPlaybackConfiguration$PlayerDeathMonitor; 11
-Landroid/net/wifi/nl80211/WifiNl80211Manager$ScanEventCallback; 11
-Landroid/service/notification/NotificationListenerService$RankingMap; 11
-Landroid/os/UserHandle;.sExtraUserHandleCache:Landroid/util/SparseArray; 11
-Ljava/time/DateTimeException; 11
-Ljava/lang/NumberFormatException; 11
-Ljava/security/Provider;.knownEngines:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.125:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 11
-Landroid/app/LoadedApk$ServiceDispatcher$RunConnection; 11
-Landroid/view/RoundedCorners; 11
-Landroid/os/Process;.ZYGOTE_PROCESS:Landroid/os/ZygoteProcess; 11
-Landroid/media/audiopolicy/AudioVolumeGroup; 11
-Landroid/media/AudioSystem$ErrorCallback; 11
-Landroid/app/servertransaction/ActivityResultItem; 11
-Lcom/android/internal/widget/DialogTitle; 11
-Lcom/android/internal/os/StoragedUidIoStatsReader$Callback; 11
-Landroid/view/ViewRootImpl$W; 11
-Landroid/app/ServiceStartArgs; 11
-Landroid/window/TaskAppearedInfo; 11
-Lcom/android/internal/listeners/ListenerExecutor$FailureCallback; 11
-Landroid/app/ApplicationExitInfo; 11
-Landroid/content/pm/PackageManager;.sCacheAutoCorker:Landroid/app/PropertyInvalidatedCache$AutoCorker;.mLock:Ljava/lang/Object; 11
-Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringValueMap; 11
-Landroid/content/pm/ResolveInfo; 11
-Lcom/android/internal/display/BrightnessSynchronizer; 11
-Landroid/window/IOnBackInvokedCallback$Stub$Proxy; 12
-Landroid/graphics/drawable/PictureDrawable; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.126:Ljava/lang/Byte; 13
-Landroid/view/ViewDebug$ExportedProperty; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.41:Ljava/lang/Byte; 13
-Landroid/view/inputmethod/DeleteGesture; 13
-Landroid/view/ViewDebug$IntToString; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.56:Ljava/lang/Byte; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.65:Ljava/lang/Byte; 13
-Landroid/webkit/WebViewFactory;.sProviderLock:Ljava/lang/Object; 13
-Ljava/lang/IllegalAccessError; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.51:Ljava/lang/Byte; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.52:Ljava/lang/Byte; 13
-Landroid/view/inputmethod/DeleteRangeGesture; 13
-Landroid/window/WindowContext; 13
-Ljava/util/concurrent/ConcurrentSkipListMap$Node; 13
-Landroid/view/inputmethod/SelectRangeGesture; 13
-Landroid/util/MalformedJsonException; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.131:Ljava/lang/Byte; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.120:Ljava/lang/Byte; 13
-Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 13
-Ljava/nio/file/StandardOpenOption;.TRUNCATE_EXISTING:Ljava/nio/file/StandardOpenOption; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.121:Ljava/lang/Byte; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.16:Ljava/lang/Byte; 13
-Ljava/util/concurrent/ConcurrentSkipListMap$Index; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.139:Ljava/lang/Byte; 13
-Landroid/view/ViewDebug$FlagToString; 13
-Landroid/view/inputmethod/SelectGesture; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.20:Ljava/lang/Byte; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.94:Ljava/lang/Byte; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.64:Ljava/lang/Byte; 13
-Landroid/webkit/WebViewFactoryProvider$Statics; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.95:Ljava/lang/Byte; 13
-Landroid/service/media/MediaBrowserService$ServiceBinder$1; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.7:Ljava/lang/Byte; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.23:Ljava/lang/Byte; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.46:Ljava/lang/Byte; 13
-Landroid/provider/Settings$SettingNotFoundException; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.74:Ljava/lang/Byte; 13
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.8:Ljava/lang/Byte; 13
-Landroid/widget/TextView;.TEMP_POSITION:[F 13
-Ljava/io/ByteArrayInputStream; 14
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.93:Ljava/lang/Byte; 14
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.134:Ljava/lang/Byte; 14
-Landroid/text/style/ImageSpan; 14
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.154:Ljava/lang/Byte; 15
-Landroid/view/TextureView$SurfaceTextureListener; 16
-Landroid/media/AudioManager$OnAudioFocusChangeListener; 17
-Ljava/util/Locale;.JAPAN:Ljava/util/Locale; 18
-Ljava/util/Locale;.GERMANY:Ljava/util/Locale; 19
-Ljava/util/Locale;.CANADA_FRENCH:Ljava/util/Locale; 20
-Ljava/util/Locale;.ITALY:Ljava/util/Locale; 20
-Ljava/util/Locale;.FRANCE:Ljava/util/Locale; 20
-Ljava/util/Locale;.UK:Ljava/util/Locale; 21
-Ljava/util/Locale;.CANADA:Ljava/util/Locale; 21
-Ljava/util/Locale$Cache;.LOCALECACHE:Ljava/util/Locale$Cache;.map:Ljava/util/concurrent/ConcurrentMap; 22
-Ljava/lang/IllegalStateException; 23
-Lcom/android/internal/util/function/pooled/PooledLambdaImpl;.sMessageCallbacksPool:Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool; 24
-Lcom/android/internal/util/function/pooled/PooledLambdaImpl;.sMessageCallbacksPool:Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool;.mPool:[Ljava/lang/Object; 24
-Landroid/media/MediaRouter$WifiDisplayStatusChangedReceiver; 25
-Landroid/media/MediaRouter$VolumeChangeReceiver; 25
-Landroid/app/AppOpsManager$OnOpActiveChangedListener; 26
-Landroid/media/PlayerBase; 27
-Landroid/content/pm/Checksum$Type; 28
-Ljava/lang/Class; 29
-Landroid/widget/MediaController$MediaPlayerControl; 30
-Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.135:Ljava/lang/Long; 30
-Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.152:Ljava/lang/Long; 30
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.215:Ljava/lang/Byte; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.206:Ljava/lang/Byte; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.137:Ljava/lang/Byte; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.203:Ljava/lang/Byte; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.213:Ljava/lang/Byte; 31
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.549:Ljava/lang/Long; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.201:Ljava/lang/Byte; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.249:Ljava/lang/Byte; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.163:Ljava/lang/Byte; 31
-Ljava/util/HashMap; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.210:Ljava/lang/Byte; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.161:Ljava/lang/Byte; 31
-Landroid/icu/text/MeasureFormat;.hmsTo012:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.0:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.199:Ljava/lang/Byte; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.248:Ljava/lang/Byte; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.252:Ljava/lang/Byte; 31
-Lcom/android/ims/rcs/uce/UceDeviceState;.DEVICE_STATE_DESCRIPTION:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.3:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.159:Ljava/lang/Byte; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.217:Ljava/lang/Byte; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.200:Ljava/lang/Byte; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.240:Ljava/lang/Byte; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.198:Ljava/lang/Byte; 31
-Lcom/android/ims/rcs/uce/UceDeviceState;.DEVICE_STATE_DESCRIPTION:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.4:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 31
-Landroid/content/pm/PackageManager$OnChecksumsReadyListener; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.193:Ljava/lang/Byte; 31
-Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.228:Ljava/lang/Long; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.236:Ljava/lang/Byte; 31
-Landroid/telephony/ims/ImsService;.CAPABILITIES_LOG_MAP:Ljava/util/Map;.table:[Ljava/lang/Object;.2:Ljava/lang/Long; 31
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.211:Ljava/lang/Byte; 31
-Landroid/view/SurfaceView; 32
-Landroid/view/ViewStub$OnInflateListener; 33
-Landroid/graphics/drawable/DrawableInflater;.CONSTRUCTOR_MAP:Ljava/util/HashMap; 34
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.245:Ljava/lang/Byte; 35
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.232:Ljava/lang/Byte; 35
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.12:Ljava/lang/Byte; 35
-Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.170:Ljava/lang/Long; 35
-Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.183:Ljava/lang/Long; 35
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.246:Ljava/lang/Byte; 35
-Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.168:Ljava/lang/Long; 35
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.72:Ljava/lang/Byte; 35
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.243:Ljava/lang/Byte; 35
-Ljava/util/WeakHashMap;.NULL_KEY:Ljava/lang/Object; 35
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.235:Ljava/lang/Byte; 35
-Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.147:Ljava/lang/Long; 35
-Ljava/io/InterruptedIOException; 35
-Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.184:Ljava/lang/Long; 35
-Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.165:Ljava/lang/Long; 35
-Landroid/text/style/ForegroundColorSpan; 35
-Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.176:Ljava/lang/Long; 35
-Ljava/lang/Long$LongCache;.archivedCache:[Ljava/lang/Long;.173:Ljava/lang/Long; 35
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.181:Ljava/lang/Byte; 35
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.157:Ljava/lang/Byte; 35
-Landroid/content/res/AssetManager$AssetInputStream; 35
-Landroid/graphics/drawable/TransitionDrawable; 36
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1:Ljava/lang/Boolean; 37
-Landroid/view/ViewOverlay$OverlayViewGroup; 38
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.11:Ljava/lang/Boolean; 39
-Ljava/util/Observer; 40
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.129:Ljava/lang/Byte; 41
-[Ljava/lang/Byte; 41
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.144:Ljava/lang/Byte; 41
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.164:Ljava/lang/Byte; 42
-Landroid/view/OrientationEventListener; 43
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.195:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.233:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.229:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.128:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.242:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.196:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.208:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.212:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.228:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.205:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.197:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.204:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.207:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.223:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.244:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.174:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.194:Ljava/lang/Byte; 44
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.225:Ljava/lang/Byte; 45
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.239:Ljava/lang/Byte; 45
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.238:Ljava/lang/Byte; 45
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.227:Ljava/lang/Byte; 45
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.152:Ljava/lang/Byte; 46
-Landroid/app/RemoteAction; 46
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.168:Ljava/lang/Byte; 46
-Landroid/text/style/QuoteSpan; 46
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.54:Ljava/lang/Byte; 46
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.124:Ljava/lang/Byte; 46
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.142:Ljava/lang/Byte; 46
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.190:Ljava/lang/Byte; 46
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.114:Ljava/lang/Byte; 46
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.69:Ljava/lang/Byte; 46
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.30:Ljava/lang/Byte; 46
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.133:Ljava/lang/Byte; 46
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.49:Ljava/lang/Byte; 46
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.58:Ljava/lang/Byte; 46
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.143:Ljava/lang/Byte; 47
-Landroid/icu/text/RelativeDateTimeFormatter$AbsoluteUnit; 47
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.82:Ljava/lang/Byte; 47
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.140:Ljava/lang/Byte; 47
-Landroid/icu/text/RelativeDateTimeFormatter;.fallbackCache:[Landroid/icu/text/RelativeDateTimeFormatter$Style; 47
-Landroid/icu/text/RelativeDateTimeFormatter$Style; 47
-Landroid/icu/text/RelativeDateTimeFormatter;.cache:Landroid/icu/text/RelativeDateTimeFormatter$Cache;.cache:Landroid/icu/impl/CacheBase;.map:Ljava/util/concurrent/ConcurrentHashMap; 47
-Landroid/icu/text/RelativeDateTimeFormatter$RelativeUnit; 47
-Landroid/icu/text/RelativeDateTimeFormatter$Direction; 47
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.130:Ljava/lang/Byte; 47
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.43:Ljava/lang/Byte; 47
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.146:Ljava/lang/Byte; 47
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.138:Ljava/lang/Byte; 47
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.136:Ljava/lang/Byte; 48
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.0:Ljava/lang/Byte; 49
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.160:Ljava/lang/Byte; 49
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.169:Ljava/lang/Byte; 50
-Landroid/widget/Spinner; 50
-Landroid/widget/MultiAutoCompleteTextView; 50
-Ljava/util/ArrayList; 50
-Landroid/widget/CheckBox; 50
-Ljava/io/Serializable; 50
-Landroid/widget/RatingBar; 50
-Ljava/lang/Byte$ByteCache;.archivedCache:[Ljava/lang/Byte;.132:Ljava/lang/Byte; 50
-Landroid/widget/AutoCompleteTextView; 50
-Ljava/util/concurrent/ConcurrentLinkedDeque$Node; 50
-[Ljava/lang/Object; 50
-Landroid/widget/SeekBar; 51
-Ljava/lang/Void; 52
-Landroid/app/ActivityTaskManager;.sInstance:Landroid/util/Singleton; 53
-Landroid/view/ViewRootImpl$$ExternalSyntheticLambda11; 54
-Landroid/view/ViewTreeObserver$OnWindowFocusChangeListener; 55
-Landroid/view/InsetsAnimationThread; 56
-Lcom/android/internal/jank/InteractionJankMonitor$InstanceHolder; 57
-Lcom/android/internal/jank/InteractionJankMonitor; 57
-Landroid/hardware/camera2/CameraCharacteristics;.FLASH_INFO_AVAILABLE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 58
-Landroid/hardware/display/NightDisplayListener$Callback; 59
-Landroid/media/MediaRouter2Manager; 59
-Landroid/os/HandlerExecutor; 59
-Landroid/os/strictmode/LeakedClosableViolation; 60
-Lcom/android/internal/logging/MetricsLogger; 60
-Lcom/android/internal/os/PowerProfile;.sPowerItemMap:Ljava/util/HashMap; 61
-Lcom/android/internal/os/PowerProfile;.sPowerArrayMap:Ljava/util/HashMap; 61
-Lcom/android/internal/os/PowerProfile;.sModemPowerProfile:Lcom/android/internal/power/ModemPowerProfile;.mPowerConstants:Landroid/util/SparseDoubleArray;.mValues:Landroid/util/SparseLongArray; 61
-Landroid/content/IntentFilter; 62
-Landroid/telecom/TelecomManager; 63
-Ljava/lang/IllegalArgumentException; 64
-Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.1:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object; 65
-Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.1:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object;.mCache:Ljava/util/LinkedHashMap; 65
-Landroid/telephony/VisualVoicemailSmsFilterSettings;.DEFAULT_ORIGINATING_NUMBERS:Ljava/util/List; 66
-Ljava/util/AbstractList; 68
-Ljava/util/AbstractCollection; 68
-Ljava/util/Collections$EmptyList; 69
-Ljava/lang/StackTraceElement; 69
-[Ljava/lang/StackTraceElement; 69
-Landroid/os/strictmode/Violation; 70
-Ljava/util/List; 71
-Ljava/lang/String; 72
-Ljava/io/ObjectInputStream; 73
-Ljava/io/ObjectStreamClass$Caches;.localDescs:Ljava/util/concurrent/ConcurrentMap; 73
-Ljava/io/ObjectStreamClass$Caches;.reflectors:Ljava/util/concurrent/ConcurrentMap; 73
-Ljava/io/ObjectOutputStream; 73
-Ljava/lang/Number; 74
-Ljava/math/BigInteger; 75
-[B 76
-Landroid/os/Handler; 77
-Landroid/view/accessibility/AccessibilityManager; 78
+Landroid/content/ComponentCallbacks; 2
+Landroid/content/ComponentCallbacks2; 2
+Lcom/android/internal/app/ResolverActivity$ActionTitle;.HOME:Lcom/android/internal/app/ResolverActivity$ActionTitle;.name:Ljava/lang/String; 4
+Landroid/icu/text/MessageFormat;.typeList:[Ljava/lang/String;.1:Ljava/lang/String; 4
+Landroid/app/assist/AssistStructure$HtmlInfoNode; 4
+Landroid/app/ActivityManager$AppTask; 4
+Landroid/view/inputmethod/SurroundingText; 5
+Landroid/widget/ProgressBar$SavedState; 6
+Landroid/telephony/SignalStrength; 9
+Landroid/app/Notification$BigTextStyle; 10
+Landroid/app/AppOpsManager$OnOpNotedListener; 11
+Landroid/window/IRemoteTransition$Stub$Proxy; 11
+Lcom/android/internal/logging/UiEventLogger$UiEventEnum; 11
+Landroid/app/AppOpsManager$OnOpNotedInternalListener; 11
+Landroid/view/DisplayCutout; 11
+Lcom/android/internal/logging/MetricsLogger; 11
+Landroid/os/strictmode/LeakedClosableViolation; 11
+Lcom/android/internal/policy/AttributeCache; 11
+Lcom/android/internal/util/LatencyTracker$Action; 11
+Landroid/app/AppOpsManager$OnOpStartedListener; 11
+Landroid/app/Notification$DecoratedCustomViewStyle; 11
+Lcom/android/internal/R$styleable;.WindowAnimation:[I 11
+Landroid/app/Notification$CallStyle; 11
+Lcom/android/internal/statusbar/NotificationVisibility; 11
+Landroid/hardware/display/ColorDisplayManager$ColorDisplayManagerInternal; 12
+Landroid/graphics/ColorSpace$Model;.RGB:Landroid/graphics/ColorSpace$Model; 13
+Landroid/app/WallpaperManager; 13
+Landroid/text/TextUtils$TruncateAt; 14
+Landroid/app/smartspace/uitemplatedata/BaseTemplateData; 15
+Landroid/app/smartspace/SmartspaceTarget; 15
+Lcom/android/internal/os/SomeArgs; 16
+Landroid/widget/inline/InlinePresentationSpec; 17
+Landroid/media/AudioSystem; 18
+Lcom/android/internal/os/CachedDeviceState$Readonly; 18
+Landroid/service/notification/Condition; 18
+Landroid/os/BatteryManagerInternal; 18
+Landroid/content/pm/PermissionGroupInfo; 18
+Landroid/app/job/JobInfo; 18
+Landroid/hardware/location/IActivityRecognitionHardwareClient; 18
+Landroid/accessibilityservice/AccessibilityServiceInfo; 18
+Landroid/app/Notification$DecoratedMediaCustomViewStyle; 18
+Landroid/hardware/location/NanoAppMessage; 18
+Landroid/net/Uri$PathPart;.NULL:Landroid/net/Uri$PathPart; 18
+Landroid/hardware/soundtrigger/SoundTrigger$StatusListener; 18
+Landroid/util/EventLog; 18
+Landroid/app/ActivityManager$RecentTaskInfo; 18
+Lcom/android/internal/widget/LockSettingsInternal; 18
+Landroid/window/DisplayAreaAppearedInfo; 18
+Landroid/accounts/AuthenticatorException; 18
+Landroid/os/ResultReceiver; 18
+Landroid/content/pm/UserPackage;.sCacheLock:Ljava/lang/Object; 18
+Lcom/android/internal/view/WindowManagerPolicyThread; 18
+Landroid/content/pm/LauncherActivityInfoInternal; 18
+Landroid/webkit/WebViewLibraryLoader$RelroFileCreator; 18
+Landroid/hardware/biometrics/BiometricSourceType; 18
+Landroid/net/metrics/ValidationProbeEvent; 18
+Landroid/view/RoundedCorners; 18
+Landroid/os/Process;.ZYGOTE_PROCESS:Landroid/os/ZygoteProcess; 18
+Landroid/app/ServiceStartArgs; 18
+Landroid/telecom/Logging/EventManager$EventListener; 18
+Landroid/app/SystemServiceRegistry; 18
+Landroid/permission/PermissionManagerInternal; 18
+Landroid/service/notification/StatusBarNotification; 18
+Lcom/android/internal/os/ProcessCpuTracker$FilterStats; 18
+Lcom/android/internal/util/ToBooleanFunction; 18
+Landroid/content/pm/RegisteredServicesCache$3; 18
+Landroid/os/ServiceManager$ServiceNotFoundException; 18
+Landroid/app/ActivityManagerInternal; 18
+Landroid/app/assist/AssistStructure; 18
+Landroid/hardware/camera2/CameraManager$CameraManagerGlobal; 18
+Landroid/app/servertransaction/PauseActivityItem; 18
+Landroid/hardware/soundtrigger/SoundTriggerModule$EventHandlerDelegate; 18
+Landroid/media/AudioAttributes; 18
+Landroid/service/dreams/DreamManagerInternal; 18
+Lcom/android/internal/listeners/ListenerExecutor$FailureCallback; 18
+Landroid/net/metrics/DhcpErrorEvent; 18
+Landroid/app/servertransaction/ConfigurationChangeItem; 18
+Landroid/hardware/sidekick/SidekickInternal; 18
+Landroid/appwidget/AppWidgetManagerInternal; 18
+Landroid/hardware/display/DisplayManagerInternal; 18
+Landroid/telecom/PhoneAccountHandle; 18
+Landroid/view/WindowManagerPolicyConstants; 18
+Landroid/net/wifi/nl80211/WifiNl80211Manager$ScanEventCallback; 18
+Lcom/android/internal/app/procstats/AssociationState;.sTmpSourceKey:Lcom/android/internal/app/procstats/AssociationState$SourceKey; 18
+Landroid/content/pm/RegisteredServicesCache$2; 18
+Landroid/content/pm/UserPackage; 18
+Landroid/app/time/TimeZoneCapabilities; 18
+Lcom/android/internal/util/function/LongObjPredicate; 18
+Landroid/app/servertransaction/NewIntentItem; 18
+Landroid/app/PropertyInvalidatedCache;.sCorkedInvalidates:Ljava/util/HashMap; 18
+Lcom/android/internal/os/StatsdHiddenApiUsageLogger;.sInstance:Lcom/android/internal/os/StatsdHiddenApiUsageLogger; 18
+Landroid/app/admin/DevicePolicyManagerInternal$OnCrossProfileWidgetProvidersChangeListener; 18
+Landroid/app/usage/AppStandbyInfo; 18
+Landroid/graphics/GraphicsStatsService; 18
+Lcom/android/internal/os/LongArrayMultiStateCounter; 18
+Landroid/graphics/Bitmap$CompressFormat; 18
+Landroid/media/audiopolicy/AudioVolumeGroup; 18
+Landroid/content/pm/CrossProfileAppsInternal; 18
+Landroid/os/PowerManagerInternal; 18
+Landroid/hardware/location/GeofenceHardwareImpl; 18
+Landroid/app/AppOpsManager$AttributedOpEntry; 18
+Landroid/attention/AttentionManagerInternal; 18
+Landroid/telecom/Log; 18
+Landroid/accounts/AccountManagerInternal; 18
+Landroid/content/pm/ShortcutServiceInternal$ShortcutChangeListener; 18
+Landroid/os/PatternMatcher;.sParsedPatternScratch:[I 18
+Landroid/app/AppOpsManager$NoteOpEvent; 18
+Lcom/android/internal/R$styleable;.Window:[I 18
+Landroid/content/pm/dex/ArtManagerInternal; 18
+Landroid/content/pm/PackageInstaller$SessionInfo; 18
+Landroid/app/servertransaction/StartActivityItem; 18
+Landroid/content/pm/PackageManager;.sCacheAutoCorker:Landroid/app/PropertyInvalidatedCache$AutoCorker; 18
+Landroid/graphics/Region;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 18
+Landroid/app/Notification$MediaStyle; 18
+Landroid/app/time/TimeZoneConfiguration; 18
+Lcom/android/internal/os/LongMultiStateCounter; 18
+Landroid/service/voice/VoiceInteractionManagerInternal; 18
+Landroid/view/Display$HdrCapabilities; 18
+Landroid/media/AudioSystem$AudioRecordingCallback; 18
+Landroid/app/servertransaction/DestroyActivityItem; 18
+Lcom/android/internal/os/RuntimeInit$ApplicationWtfHandler; 18
+Landroid/net/metrics/IpManagerEvent; 18
+Landroid/net/metrics/NetworkEvent; 18
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.7:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object;.mLock:Ljava/lang/Object; 18
+Landroid/app/AppOpsManagerInternal; 18
+Landroid/content/res/ResourceTimer; 18
+Lcom/android/internal/infra/AbstractRemoteService$AsyncRequest; 18
+Lcom/android/internal/statusbar/NotificationVisibility$NotificationLocation; 18
+Landroid/app/servertransaction/ObjectPool;.sPoolSync:Ljava/lang/Object; 18
+Landroid/content/pm/PackageManager;.sCacheAutoCorker:Landroid/app/PropertyInvalidatedCache$AutoCorker;.mLock:Ljava/lang/Object; 18
+Landroid/app/admin/DevicePolicyManagerInternal; 18
+Landroid/webkit/WebViewZygote; 18
+Landroid/view/DisplayAddress$Physical; 18
+Landroid/accounts/AccountManagerInternal$OnAppPermissionChangeListener; 18
+Lcom/android/internal/os/BatteryStatsHistory$HistoryStepDetailsCalculator; 18
+Landroid/appwidget/AppWidgetProviderInfo; 18
+Landroid/provider/Settings; 18
+Lcom/android/server/AppWidgetBackupBridge; 18
+Landroid/content/pm/RegisteredServicesCacheListener; 18
+Landroid/window/IOnBackInvokedCallback$Stub$Proxy; 18
+Landroid/view/ViewDebug$ExportedProperty; 18
+Landroid/text/format/TimeFormatter; 18
+Landroid/content/ComponentName$WithComponentName; 18
+Landroid/hardware/location/ContextHubInfo; 18
+Landroid/app/servertransaction/ActivityResultItem; 18
+Landroid/hardware/display/DeviceProductInfo$ManufactureDate; 18
+Lcom/android/internal/util/function/DodecConsumer; 18
+Landroid/app/PropertyInvalidatedCache;.sCorks:Ljava/util/HashMap; 18
+Landroid/app/ApplicationExitInfo; 18
+Lcom/android/server/usage/AppStandbyInternal; 18
+Landroid/view/autofill/AutofillManagerInternal; 18
+Lcom/android/internal/infra/AbstractRemoteService$VultureCallback; 18
+Landroid/service/notification/NotificationListenerService$RankingMap; 18
+Landroid/service/notification/ConditionProviderService; 18
+Landroid/net/metrics/ApfProgramEvent; 18
+Lcom/android/internal/infra/AndroidFuture$1; 18
+Landroid/app/servertransaction/StopActivityItem; 18
+Landroid/app/PropertyInvalidatedCache$AutoCorker$1; 18
+Landroid/util/NtpTrustedTime; 18
+Landroid/content/pm/parsing/ApkLite; 18
+Lcom/android/server/LocalServices;.sLocalServiceObjects:Landroid/util/ArrayMap; 18
+Landroid/app/PropertyInvalidatedCache;.sCorkLock:Ljava/lang/Object; 18
+Landroid/app/PendingIntent$FinishedDispatcher; 18
+Landroid/os/ResultReceiver$MyResultReceiver; 18
+Landroid/os/ServiceSpecificException; 18
+Landroid/os/UEventObserver; 18
+Landroid/os/SharedMemory; 18
+Lcom/android/internal/util/function/DodecFunction; 18
+Landroid/content/pm/BaseParceledListSlice$1; 18
+Landroid/content/pm/FallbackCategoryProvider;.sFallbacks:Landroid/util/ArrayMap; 18
+Lcom/android/internal/content/om/OverlayConfig$PackageProvider; 18
+Landroid/util/ArrayMap;.sBaseCacheLock:Ljava/lang/Object; 18
+Landroid/debug/AdbManagerInternal; 18
+Landroid/view/WindowManagerPolicyConstants$PointerEventListener; 18
+Landroid/telephony/ServiceState; 18
+Lcom/android/internal/os/LooperStats; 18
+Landroid/content/pm/LauncherApps$ShortcutQuery$QueryFlags; 18
+Landroid/app/ActivityManager; 18
+Landroid/app/assist/ActivityId; 18
+Landroid/hardware/display/DeviceProductInfo; 18
+Lcom/android/internal/os/LongArrayMultiStateCounter;.sTmpArrayContainer:Ljava/util/concurrent/atomic/AtomicReference; 18
+Lcom/android/internal/os/LongArrayMultiStateCounter$LongArrayContainer; 18
+Landroid/service/notification/ZenPolicy; 18
+Landroid/content/pm/PackageManager$Property; 18
+Lcom/android/internal/content/om/OverlayConfig; 18
+Landroid/content/pm/ResolveInfo; 18
+Lcom/android/internal/os/KernelCpuBpfTracking; 18
+Landroid/content/pm/RegisteredServicesCache$1; 18
+Landroid/telecom/Logging/SessionManager$ISessionListener; 18
+Landroid/media/AudioPlaybackConfiguration$PlayerDeathMonitor; 18
+Landroid/service/autofill/FillContext; 18
+Landroid/graphics/Region;.sPool:Landroid/util/Pools$SynchronizedPool; 18
+Landroid/util/MemoryIntArray; 18
+Lcom/android/internal/config/appcloning/AppCloningDeviceConfigHelper; 18
+Landroid/os/storage/StorageManagerInternal; 18
+Landroid/media/AudioSystem$ErrorCallback; 18
+Landroid/service/notification/ZenModeConfig; 18
+Landroid/media/AudioPlaybackConfiguration; 18
+Landroid/content/pm/UserPackage;.sCache:Landroid/util/SparseArrayMap;.mData:Landroid/util/SparseArray; 18
+Landroid/app/AppOpsManager$SamplingStrategy; 18
+Landroid/app/servertransaction/ActivityConfigurationChangeItem; 18
+Landroid/hardware/location/GeofenceHardwareService; 18
+Landroid/os/RemoteCallback$1; 18
+Landroid/os/FileUtils$ProgressListener; 18
+Landroid/annotation/StringRes; 18
+Lcom/android/server/WidgetBackupProvider; 18
+Landroid/media/AudioManagerInternal$RingerModeDelegate; 18
+Landroid/hardware/biometrics/ComponentInfoInternal; 18
+Landroid/media/AudioManagerInternal; 18
+Landroid/media/AudioSystem$DynamicPolicyCallback; 18
+Landroid/os/DeadObjectException; 18
+Landroid/content/pm/ShortcutServiceInternal; 18
+Landroid/view/ViewDebug$FlagToString; 18
+Landroid/os/storage/StorageVolume; 18
+Landroid/window/TaskAppearedInfo; 18
+Lcom/android/internal/display/BrightnessSynchronizer; 18
+Lcom/android/internal/infra/ServiceConnector$Impl$CompletionAwareJob; 18
+Landroid/os/strictmode/UnbufferedIoViolation; 19
+Landroid/app/usage/UsageStats; 20
+Landroid/app/usage/CacheQuotaHint; 21
+Landroid/service/watchdog/ExplicitHealthCheckService$PackageConfig; 21
+Landroid/os/BaseBundle; 22
+Landroid/os/Parcel$ReadWriteHelper; 23
+Landroid/util/SparseArray; 24
+Landroid/app/Instrumentation; 25
+Landroid/content/pm/PathPermission; 26
+[Landroid/content/pm/ConfigurationInfo; 26
+Landroid/content/pm/ActivityInfo; 26
+Landroid/content/pm/Attribution; 26
+Landroid/content/pm/ConfigurationInfo; 26
+Landroid/content/pm/ActivityInfo$WindowLayout; 26
+Landroid/os/PatternMatcher; 26
+Landroid/content/pm/ServiceInfo; 26
+[Landroid/content/pm/FeatureInfo; 26
+[Landroid/content/pm/FeatureGroupInfo; 26
+Landroid/content/pm/SigningInfo; 26
+[Landroid/content/pm/InstrumentationInfo; 26
+[Landroid/content/pm/ServiceInfo; 26
+[Landroid/os/PatternMatcher; 26
+Landroid/content/pm/ComponentInfo; 26
+[Landroid/content/pm/PermissionInfo; 26
+[Landroid/content/pm/ActivityInfo; 26
+[Landroid/content/pm/Attribution; 26
+Landroid/content/pm/SharedLibraryInfo; 26
+Landroid/content/pm/FeatureGroupInfo; 26
+Landroid/content/pm/InstrumentationInfo; 26
+[Landroid/content/pm/Signature; 26
+[Landroid/content/pm/ProviderInfo; 26
+[Landroid/content/pm/PathPermission; 26
+Landroid/content/pm/Signature; 26
+Landroid/graphics/drawable/NinePatchDrawable; 28
+Landroid/hardware/camera2/CameraCharacteristics;.LENS_INFO_AVAILABLE_APERTURES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 29
+Landroid/hardware/camera2/CameraCharacteristics;.LENS_INFO_AVAILABLE_FOCAL_LENGTHS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 30
+Landroid/hardware/camera2/params/StreamConfigurationDuration; 31
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/params/StreamConfiguration; 31
+Landroid/hardware/camera2/CameraCharacteristics;.REQUEST_AVAILABLE_CAPABILITIES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.HEIC_AVAILABLE_HEIC_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/params/HighSpeedVideoConfiguration; 31
+Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 31
+Landroid/hardware/camera2/CameraCharacteristics;.LENS_FACING:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 32
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 33
+Landroid/hardware/camera2/marshal/MarshalRegistry;.sMarshalerMap:Ljava/util/HashMap; 33
+Landroid/hardware/devicestate/DeviceStateManagerGlobal; 34
+Lgov/nist/javax/sip/header/AuthenticationHeader;.SIGNATURE:Ljava/lang/String; 40
+Landroid/app/slice/Slice;.SUBTYPE_SOURCE:Ljava/lang/String; 41
+Ljavax/sip/message/Request;.INFO:Ljava/lang/String; 41
+Lgov/nist/javax/sip/header/extensions/ReferencesHeader;.SERVICE:Ljava/lang/String; 42
+Landroid/icu/impl/locale/LocaleValidityChecker$SpecialCase;.normal:Landroid/icu/impl/locale/LocaleValidityChecker$SpecialCase;.name:Ljava/lang/String; 42
+Lgov/nist/javax/sip/address/NetObject;.PHONE:Ljava/lang/String; 42
+Landroid/icu/impl/ValidIdentifiers$Datatype;.language:Landroid/icu/impl/ValidIdentifiers$Datatype;.name:Ljava/lang/String; 42
+Landroid/icu/text/MessageFormat;.dateModifierList:[Ljava/lang/String;.3:Ljava/lang/String; 42
+Landroid/view/translation/UiTranslationManager;.EXTRA_PACKAGE_NAME:Ljava/lang/String; 42
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.140:Ljava/lang/String; 43
+Landroid/icu/impl/units/UnitPreferences;.measurementSystem:Ljava/util/Map;.m:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.15:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 44
+Lcom/android/i18n/timezone/TimeZoneFinder;.COUNTRY_ELEMENT:Ljava/lang/String; 45
+Landroid/app/usage/UsageEvents$Event;.DEVICE_EVENT_PACKAGE_NAME:Ljava/lang/String; 46
+Landroid/icu/text/MessageFormat;.rootLocale:Ljava/util/Locale;.baseLocale:Lsun/util/locale/BaseLocale;.language:Ljava/lang/String; 47
+Landroid/graphics/Bitmap; 68
+Landroid/view/inputmethod/IInputMethodManagerGlobalInvoker; 69
+Landroid/view/SurfaceControlRegistry; 70
+Lcom/android/internal/inputmethod/ImeTracing; 70
+Lcom/android/internal/policy/DecorView; 71
+Landroid/view/ViewTreeObserver; 71
+Landroid/view/accessibility/AccessibilityNodeIdManager; 71
+Landroid/view/ViewRootImpl; 71
+Landroid/widget/FrameLayout; 71
+Landroid/view/ViewStub; 71
+Landroid/window/SurfaceSyncGroup; 72
+Landroid/view/Choreographer; 73
+Landroid/os/SystemProperties;.sChangeCallbacks:Ljava/util/ArrayList; 74
+Landroid/app/ActivityClient;.sInstance:Landroid/util/Singleton; 75
+Landroid/app/ActivityClient;.INTERFACE_SINGLETON:Landroid/app/ActivityClient$ActivityClientControllerSingleton; 75
+Landroid/view/autofill/AutofillId; 76
+Landroid/os/StrictMode$InstanceTracker;.sInstanceCounts:Ljava/util/HashMap; 77
+Landroid/widget/LinearLayout; 78
Landroid/view/ViewConfiguration;.sConfigurations:Landroid/util/SparseArray;.mKeys:[I 79
Landroid/view/ViewConfiguration;.sConfigurations:Landroid/util/SparseArray;.mValues:[Ljava/lang/Object; 79
Landroid/view/ViewConfiguration;.sConfigurations:Landroid/util/SparseArray; 79
-Landroid/widget/FrameLayout; 80
-Lcom/android/internal/inputmethod/ImeTracing; 80
-Lcom/android/internal/policy/DecorView; 80
-Landroid/view/accessibility/AccessibilityNodeIdManager; 80
-Landroid/view/ViewTreeObserver; 80
-Landroid/view/ViewRootImpl; 80
-Landroid/os/SystemProperties;.sChangeCallbacks:Ljava/util/ArrayList; 80
-Landroid/transition/ChangeTransform; 80
-Landroid/window/SurfaceSyncGroup; 80
-Landroid/transition/ChangeClipBounds; 80
-Landroid/view/SurfaceControlRegistry; 80
-Landroid/transition/ChangeImageTransform; 80
-Landroid/widget/LinearLayout; 80
-Landroid/view/ViewStub; 81
-Landroid/text/TextLine;.sCached:[Landroid/text/TextLine; 82
-Landroid/text/TextUtils; 82
-Landroid/graphics/TemporaryBuffer; 82
-Landroid/content/res/ColorStateList;.sCache:Landroid/util/SparseArray; 83
-Landroid/text/Layout;.sTempRect:Landroid/graphics/Rect; 84
-Landroid/widget/ImageView; 85
-Landroid/graphics/drawable/ColorDrawable; 86
-Landroid/os/StrictMode$InstanceTracker;.sInstanceCounts:Ljava/util/HashMap; 87
-Landroid/app/ActivityClient;.INTERFACE_SINGLETON:Landroid/app/ActivityClient$ActivityClientControllerSingleton; 88
-Landroid/app/ActivityClient;.sInstance:Landroid/util/Singleton; 88
-Landroid/view/AbsSavedState$1; 89
-Landroid/app/FragmentManagerState; 90
-Landroid/window/OnBackAnimationCallback; 91
-Landroid/animation/AnimatorInflater;.sTmpTypedValue:Landroid/util/TypedValue; 92
-Landroid/graphics/drawable/RippleDrawable; 93
-Landroid/view/inputmethod/IInputMethodManagerGlobalInvoker; 94
-Landroid/app/ActivityTaskManager;.IActivityTaskManagerSingleton:Landroid/util/Singleton; 95
-Landroid/view/Choreographer; 96
-Lcom/android/internal/os/SomeArgs; 97
-Landroid/graphics/Bitmap; 98
-Landroid/view/autofill/AutofillId; 99
-Landroid/view/inputmethod/BaseInputConnection;.COMPOSING:Ljava/lang/Object; 100
-Landroid/text/Selection;.SELECTION_MEMORY:Ljava/lang/Object; 101
-Landroid/text/Selection;.SELECTION_END:Ljava/lang/Object; 101
-Landroid/text/Selection;.SELECTION_START:Ljava/lang/Object; 101
-Landroid/text/SpannableStringBuilder;.sCachedIntBuffer:[[I 102
-Landroid/text/Selection$MemoryTextWatcher; 103
-Landroid/text/SpanWatcher; 104
-Lcom/android/internal/util/ArrayUtils;.sCache:[Ljava/lang/Object; 105
-Ljava/lang/Integer;.SMALL_NEG_VALUES:[Ljava/lang/String; 106
-Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 107
-Lsun/nio/ch/SharedFileLockTable;.lockMap:Ljava/util/concurrent/ConcurrentHashMap; 108
-Lsun/nio/ch/FileChannelImpl; 108
-Landroid/database/sqlite/SQLiteDatabase$CursorFactory; 109
-Landroid/database/sqlite/SQLiteDebug$NoPreloadHolder; 110
-Landroid/database/sqlite/SQLiteCompatibilityWalFlags; 110
-Landroid/database/sqlite/SQLiteGlobal; 110
-Landroid/database/CursorWindow; 111
-Landroid/content/ContentResolver; 112
-Ljava/nio/charset/Charset; 113
-Landroid/app/ContextImpl; 114
-Ljava/util/concurrent/Executors$DefaultThreadFactory;.poolNumber:Ljava/util/concurrent/atomic/AtomicInteger; 115
-Landroid/content/pm/PackageManager;.sPackageInfoCache:Landroid/app/PropertyInvalidatedCache;.mCache:Ljava/util/LinkedHashMap; 116
-Landroid/content/pm/PackageManager;.sApplicationInfoCache:Landroid/app/PropertyInvalidatedCache;.mCache:Ljava/util/LinkedHashMap; 117
-Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager;.systemContext:Ljava/util/logging/LogManager$LoggerContext;.namedLoggers:Ljava/util/Hashtable;.table:[Ljava/util/Hashtable$HashtableEntry; 118
-Landroid/ddm/DdmHandleAppName; 118
-Landroid/provider/DeviceConfigInitializer; 118
-Lsun/misc/Cleaner; 118
-Ldalvik/system/CloseGuard; 118
-Landroid/graphics/Typeface; 118
-Landroid/os/BinderProxy;.sProxyMap:Landroid/os/BinderProxy$ProxyMap;.mMainIndexKeys:[[Ljava/lang/Long; 118
-Landroid/permission/PermissionManager; 118
-Landroid/media/MediaFrameworkPlatformInitializer; 118
-Ljava/util/TimeZone; 118
-Landroid/os/Environment; 118
-Landroid/compat/Compatibility; 118
-Landroid/os/ServiceManager; 118
-Landroid/content/pm/PackageManager;.sApplicationInfoCache:Landroid/app/PropertyInvalidatedCache; 118
-Ljava/util/Locale$NoImagePreloadHolder; 118
-Ljava/lang/System; 118
-Lcom/android/internal/os/RuntimeInit; 118
-Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager;.systemContext:Ljava/util/logging/LogManager$LoggerContext;.namedLoggers:Ljava/util/Hashtable; 118
-Ldalvik/system/VMRuntime;.THE_ONE:Ldalvik/system/VMRuntime; 118
-Landroid/view/View; 118
-Landroid/hardware/display/DisplayManagerGlobal; 118
-Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager; 118
-Landroid/telephony/TelephonyFrameworkInitializer; 118
-Landroid/se/omapi/SeFrameworkInitializer; 118
-Landroid/app/LoadedApk;.sApplications:Landroid/util/ArrayMap;.mHashes:[I 118
-Landroid/security/net/config/SystemCertificateSource$NoPreloadHolder; 118
-Landroid/security/net/config/ApplicationConfig; 118
-Landroid/content/res/Resources;.sResourcesHistory:Ljava/util/Set;.c:Ljava/util/Collection;.m:Ljava/util/Map; 118
-Ljava/util/Locale; 118
-Landroid/content/res/Resources;.sResourcesHistory:Ljava/util/Set;.c:Ljava/util/Collection;.m:Ljava/util/Map;.table:[Ljava/util/WeakHashMap$Entry; 118
-Ljava/security/Provider; 118
-Ldalvik/system/ZygoteHooks; 118
-Landroid/os/Message; 118
-Landroid/app/LoadedApk;.sApplications:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object; 118
-Landroid/app/LoadedApk;.sApplications:Landroid/util/ArrayMap; 118
-Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap; 118
-Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager;.userContext:Ljava/util/logging/LogManager$LoggerContext;.namedLoggers:Ljava/util/Hashtable; 118
-Ljava/lang/ThreadGroup;.mainThreadGroup:Ljava/lang/ThreadGroup; 118
-Ldalvik/system/RuntimeHooks; 118
-Landroid/nfc/NfcFrameworkInitializer; 118
-Landroid/os/Looper; 118
-Landroid/os/LocaleList; 118
-Ldalvik/system/SocketTagger; 118
-Landroid/icu/util/TimeZone; 118
-Landroid/util/ArraySet; 118
-Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager;.systemContext:Ljava/util/logging/LogManager$LoggerContext;.root:Ljava/util/logging/LogManager$LogNode; 118
-Landroid/os/BinderProxy;.sProxyMap:Landroid/os/BinderProxy$ProxyMap;.mMainIndexValues:[Ljava/util/ArrayList; 118
-Ljava/util/Random;.seedUniquifier:Ljava/util/concurrent/atomic/AtomicLong; 118
-Landroid/app/ActivityThread; 118
-Landroid/os/Binder; 118
-Ljava/lang/ThreadLocal;.nextHashCode:Ljava/util/concurrent/atomic/AtomicInteger; 119
-Landroid/os/Parcel; 120
-Landroid/system/UnixSocketAddress; 120
-Ljava/lang/ThreadGroup;.systemThreadGroup:Ljava/lang/ThreadGroup; 120
-Ljava/lang/Daemons$FinalizerDaemon;.INSTANCE:Ljava/lang/Daemons$FinalizerDaemon; 120
-Landroid/os/Parcel;.sPairedCreators:Ljava/util/HashMap; 120
-Ljava/lang/Thread; 120
-Landroid/os/Parcel;.mCreators:Ljava/util/HashMap; 120
-Ljava/lang/Daemons$FinalizerDaemon;.INSTANCE:Ljava/lang/Daemons$FinalizerDaemon;.progressCounter:Ljava/util/concurrent/atomic/AtomicInteger; 120
-Landroid/system/StructPollfd; 120
-Ljava/lang/Daemons$HeapTaskDaemon;.INSTANCE:Ljava/lang/Daemons$HeapTaskDaemon; 120
-Landroid/system/StructTimeval; 120
-Ldalvik/system/VMRuntime;.THE_ONE:Ldalvik/system/VMRuntime;.allocationCount:Ljava/util/concurrent/atomic/AtomicInteger; 120
-Ljava/lang/Daemons$ReferenceQueueDaemon;.INSTANCE:Ljava/lang/Daemons$ReferenceQueueDaemon;.progressCounter:Ljava/util/concurrent/atomic/AtomicInteger; 120
-Landroid/os/GraphicsEnvironment;.sInstance:Landroid/os/GraphicsEnvironment; 120
-Ljava/lang/Daemons$FinalizerWatchdogDaemon;.INSTANCE:Ljava/lang/Daemons$FinalizerWatchdogDaemon; 120
-Ljava/lang/ref/FinalizerReference; 120
-Landroid/os/Process; 120
-Ljava/lang/Daemons$ReferenceQueueDaemon;.INSTANCE:Ljava/lang/Daemons$ReferenceQueueDaemon; 120
-Lcom/android/internal/os/BinderInternal; 120
-Landroid/app/ApplicationLoaders;.gApplicationLoaders:Landroid/app/ApplicationLoaders;.mLoaders:Landroid/util/ArrayMap; 121
-Landroid/app/DexLoadReporter;.INSTANCE:Landroid/app/DexLoadReporter;.mDataDirs:Ljava/util/Set;.map:Ljava/util/HashMap; 122
-Ldalvik/system/BaseDexClassLoader; 122
-Landroid/renderscript/RenderScriptCacheDir; 122
-Landroid/graphics/Compatibility; 123
-Llibcore/io/Libcore; 123
-Landroid/provider/FontsContract; 123
-Ljava/security/Security;.version:Ljava/util/concurrent/atomic/AtomicInteger; 123
-Llibcore/net/NetworkSecurityPolicy; 123
-Lsun/security/jca/Providers; 123
-Landroid/graphics/Canvas; 123
-Landroid/os/StrictMode; 124
-Landroid/content/pm/PackageManager;.sPackageInfoCache:Landroid/app/PropertyInvalidatedCache; 125
-Lcom/android/internal/os/StatsdHiddenApiUsageLogger;.sInstance:Lcom/android/internal/os/StatsdHiddenApiUsageLogger; 126
-Ljava/util/logging/LogManager;.manager:Ljava/util/logging/LogManager;.loggerRefQueue:Ljava/lang/ref/ReferenceQueue; 127
-Landroid/view/WindowManagerGlobal; 128
-Lcom/android/internal/util/function/pooled/PooledLambdaImpl;.sPool:Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool; 129
-Lcom/android/internal/util/function/pooled/PooledLambdaImpl;.sPool:Lcom/android/internal/util/function/pooled/PooledLambdaImpl$Pool;.mPool:[Ljava/lang/Object; 129
-Landroid/view/inputmethod/InputMethodManager; 130
-Landroid/media/MediaRouter; 131
-Landroid/hardware/SensorPrivacyManager; 132
-Landroid/os/storage/StorageManager; 133
-Landroid/view/contentcapture/ContentCaptureManager; 134
-Landroid/hardware/input/InputManager; 134
-Landroid/app/people/PeopleManager; 134
-Landroid/media/session/MediaSessionManager; 134
-Landroid/security/attestationverification/AttestationVerificationManager; 134
-Landroid/net/vcn/VcnManager; 134
-Landroid/os/RecoverySystem; 134
-Landroid/net/NetworkPolicyManager; 134
-Landroid/net/wifi/sharedconnectivity/app/SharedConnectivityManager; 134
-Landroid/permission/PermissionControllerManager; 134
-Landroid/app/tare/EconomyManager; 134
-Landroid/view/translation/TranslationManager; 134
-Landroid/view/textclassifier/TextClassificationManager; 134
-Landroid/view/autofill/AutofillManager; 134
-Landroid/os/SystemConfigManager; 134
-Landroid/view/LayoutInflater; 134
-Landroid/credentials/CredentialManager; 134
-Landroid/service/persistentdata/PersistentDataBlockManager; 134
-Landroid/view/textservice/TextServicesManager; 134
-Landroid/app/admin/DevicePolicyManager; 134
-Ljava/lang/StackStreamFactory; 134
-Landroid/view/WindowManager; 134
-Landroid/app/contentsuggestions/ContentSuggestionsManager; 134
-Landroid/media/tv/tunerresourcemanager/TunerResourceManager; 134
-Landroid/telephony/SubscriptionManager; 134
-Landroid/os/HardwarePropertiesManager; 134
-Landroid/media/AudioManager; 135
-Landroid/telephony/TelephonyManager; 136
-Landroid/util/ArrayMap; 137
-Landroid/app/QueuedWork; 138
-Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.0:Ljava/util/WeakHashMap$Entry; 139
-Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap; 140
-Ljava/util/concurrent/ScheduledThreadPoolExecutor;.sequencer:Ljava/util/concurrent/atomic/AtomicLong; 141
-Landroid/util/Log; 142
-Ljava/util/Collections$SynchronizedCollection; 143
-Ljava/util/Set; 143
-Ljava/util/Collections$SynchronizedSet; 143
-Ljava/util/Collection; 143
-Ljava/lang/Integer;.SMALL_NONNEG_VALUES:[Ljava/lang/String; 144
-Landroid/content/ComponentName; 145
-Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle; 146
-Landroid/os/PersistableBundle;.EMPTY:Landroid/os/PersistableBundle; 147
-Landroid/icu/impl/locale/BaseLocale;.CACHE:Landroid/icu/impl/locale/BaseLocale$Cache;._map:Ljava/util/concurrent/ConcurrentHashMap; 148
-Ljava/util/GregorianCalendar; 149
-Ljava/text/DontCareFieldPosition;.INSTANCE:Ljava/text/FieldPosition; 150
-Landroid/app/UiModeManager; 151
-Ljdk/internal/access/SharedSecrets; 152
-Landroid/icu/impl/ZoneMeta;.CANONICAL_ID_CACHE:Landroid/icu/impl/ICUCache; 153
-Landroid/icu/impl/ZoneMeta;.SYSTEM_ZONE_CACHE:Landroid/icu/impl/ZoneMeta$SystemTimeZoneCache;.map:Ljava/util/concurrent/ConcurrentHashMap; 154
-Ljava/time/ZoneOffset;.ID_CACHE:Ljava/util/concurrent/ConcurrentMap; 155
-Ljava/time/ZoneOffset;.ID_CACHE:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node; 155
-Ljava/time/ZoneOffset;.SECONDS_CACHE:Ljava/util/concurrent/ConcurrentMap; 155
-Ljava/time/ZoneOffset;.SECONDS_CACHE:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.0:Ljava/util/concurrent/ConcurrentHashMap$Node;.next:Ljava/util/concurrent/ConcurrentHashMap$Node; 155
-Ljava/time/ZoneOffset;.SECONDS_CACHE:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node; 155
-Landroid/widget/TextView; 156
-Landroid/view/ViewGroup$ChildListForAutoFillOrContentCapture;.sPool:Landroid/util/Pools$SimplePool;.mPool:[Ljava/lang/Object; 157
-Landroid/view/ViewGroup$ChildListForAutoFillOrContentCapture;.sPool:Landroid/util/Pools$SimplePool; 157
-Landroid/view/ViewGroup; 158
-Landroid/graphics/Rect; 159
-Landroid/view/View$BaseSavedState; 160
-Landroid/widget/Button; 161
-Landroid/widget/ImageButton; 162
-Landroid/view/View$OnHoverListener; 163
-Landroid/widget/Toolbar; 164
-Landroid/hardware/display/ColorDisplayManager$ColorDisplayManagerInternal; 165
-Landroid/app/WallpaperManager; 166
-Landroid/graphics/ColorSpace$Model;.RGB:Landroid/graphics/ColorSpace$Model; 166
-Landroid/graphics/drawable/AdaptiveIconDrawable; 167
-Landroid/animation/ValueAnimator$DurationScaleChangeListener; 168
-Landroid/widget/Toast; 168
-Landroid/app/smartspace/SmartspaceSession$OnTargetsAvailableListener; 168
-Landroid/view/CrossWindowBlurListeners; 168
-Landroid/app/servertransaction/ActivityRelaunchItem; 169
-[Ljava/util/concurrent/ForkJoinTask; 169
-Landroid/view/WindowManager$LayoutParams; 169
-Ljava/util/concurrent/ForkJoinPool$WorkQueue; 169
-Landroid/app/prediction/AppTargetEvent; 169
-Lorg/xmlpull/v1/XmlPullParserException; 169
-Landroid/app/servertransaction/ObjectPool;.sPoolMap:Ljava/util/Map; 170
-Landroid/app/servertransaction/ClientTransaction; 170
-Landroid/app/servertransaction/StopActivityItem; 170
-Landroid/system/ErrnoException; 171
-Landroid/hardware/location/ContextHubTransaction$OnCompleteListener; 172
-Landroid/app/PendingIntent$OnFinished; 172
-Ljava/lang/NullPointerException; 173
-Landroid/os/strictmode/DiskReadViolation; 174
-Lorg/apache/http/params/HttpParams; 175
-Landroid/nfc/cardemulation/CardEmulation; 176
-Ljava/io/FileDescriptor; 177
-Landroid/content/pm/PackageManager$OnPermissionsChangedListener; 178
-Landroid/security/keystore2/KeyStoreCryptoOperationUtils; 179
-Landroid/app/ActivityTaskManager; 180
-Landroid/util/EventLog; 181
-Ljava/net/URLConnection; 181
-Ljava/net/SocketException; 181
-Ljava/lang/reflect/InvocationTargetException; 181
-Ljava/lang/Enum; 182
-Landroid/widget/AbsListView$SelectionBoundsAdjuster; 183
-Ljava/lang/ClassNotFoundException; 183
-Landroid/content/SyncStatusObserver; 184
-Landroid/content/AsyncTaskLoader$LoadTask; 185
-Landroid/app/LoaderManager$LoaderCallbacks; 185
-Landroid/webkit/CookieSyncManager; 186
-Landroid/webkit/WebViewProvider$ViewDelegate; 187
-Landroid/webkit/WebView; 187
-Landroid/webkit/WebViewProvider$ScrollDelegate; 187
-Landroid/webkit/WebViewProvider; 187
-Landroid/webkit/WebViewFactory;.sTimestamps:Landroid/webkit/WebViewFactory$StartupTimestamps; 188
-Landroid/webkit/WebViewFactoryProvider; 189
-Landroid/webkit/WebViewFactory; 190
-Landroid/os/PowerManager$OnThermalStatusChangedListener; 191
-Landroid/os/Bundle; 192
-Landroid/widget/ProgressBar; 193
-Landroid/graphics/Bitmap$Config;.ALPHA_8:Landroid/graphics/Bitmap$Config; 194
-Landroid/graphics/Bitmap$Config;.RGB_565:Landroid/graphics/Bitmap$Config; 194
-Landroid/graphics/Bitmap$Config;.RGBA_1010102:Landroid/graphics/Bitmap$Config; 194
-Landroid/renderscript/Allocation;.mBitmapOptions:Landroid/graphics/BitmapFactory$Options;.inPreferredConfig:Landroid/graphics/Bitmap$Config; 194
-Landroid/graphics/Bitmap$Config;.RGBA_F16:Landroid/graphics/Bitmap$Config; 194
-Landroid/graphics/Bitmap$Config;.ARGB_4444:Landroid/graphics/Bitmap$Config; 194
-Landroid/graphics/Bitmap$Config;.HARDWARE:Landroid/graphics/Bitmap$Config; 194
-Landroid/graphics/drawable/StateListDrawable; 195
-Landroid/view/PointerIcon;.gSystemIconsByDisplay:Landroid/util/SparseArray; 196
-Landroid/view/PointerIcon; 196
-Ljavax/net/ssl/SSLServerSocketFactory; 197
-Ljavax/net/ssl/SSLSocketFactory; 198
-Ljavax/net/ssl/HttpsURLConnection$NoPreloadHolder; 198
-Ljavax/net/ssl/SSLSessionContext; 199
-Lcom/android/org/bouncycastle/crypto/CryptoServicesRegistrar; 200
-Lsun/security/x509/PKIXExtensions;.KeyUsage_Id:Lsun/security/util/ObjectIdentifier; 201
-Lsun/security/x509/PKIXExtensions;.PolicyConstraints_Id:Lsun/security/util/ObjectIdentifier; 201
-Ljava/security/cert/PKIXRevocationChecker$Option;.ONLY_END_ENTITY:Ljava/security/cert/PKIXRevocationChecker$Option; 201
-Lsun/security/x509/PKIXExtensions;.ExtendedKeyUsage_Id:Lsun/security/util/ObjectIdentifier; 201
-Lsun/security/provider/X509Factory;.certCache:Lsun/security/util/Cache; 201
-Lsun/security/x509/PKIXExtensions;.CertificatePolicies_Id:Lsun/security/util/ObjectIdentifier; 201
-Lsun/security/x509/PKIXExtensions;.NameConstraints_Id:Lsun/security/util/ObjectIdentifier; 201
-Lsun/security/x509/PKIXExtensions;.AuthorityKey_Id:Lsun/security/util/ObjectIdentifier; 201
-Lsun/security/provider/X509Factory;.certCache:Lsun/security/util/Cache;.cacheMap:Ljava/util/Map; 201
-Ljava/security/cert/PKIXRevocationChecker$Option;.NO_FALLBACK:Ljava/security/cert/PKIXRevocationChecker$Option; 201
-Lsun/security/x509/PKIXExtensions;.SubjectAlternativeName_Id:Lsun/security/util/ObjectIdentifier; 201
-Lsun/security/x509/PKIXExtensions;.PolicyMappings_Id:Lsun/security/util/ObjectIdentifier; 202
-Lsun/security/x509/PKIXExtensions;.InhibitAnyPolicy_Id:Lsun/security/util/ObjectIdentifier; 202
-Lsun/security/x509/PKIXExtensions;.BasicConstraints_Id:Lsun/security/util/ObjectIdentifier; 202
-Ljava/security/Security;.spiMap:Ljava/util/Map; 203
-Lsun/security/x509/X500Name;.commonName_oid:Lsun/security/util/ObjectIdentifier; 204
-Lsun/security/x509/X500Name;.countryName_oid:Lsun/security/util/ObjectIdentifier; 204
-Lsun/security/x509/X500Name;.orgName_oid:Lsun/security/util/ObjectIdentifier; 204
-Ljava/nio/charset/Charset;.cache2:Ljava/util/HashMap; 205
-Ljava/net/URL;.handlers:Ljava/util/Hashtable;.table:[Ljava/util/Hashtable$HashtableEntry; 206
-Ljava/net/URL;.handlers:Ljava/util/Hashtable; 206
-Ljava/net/Inet6AddressImpl;.addressCache:Ljava/net/AddressCache;.cache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap; 207
-Ljava/net/Proxy$Type;.DIRECT:Ljava/net/Proxy$Type; 208
-Ljava/net/ProxySelector;.theProxySelector:Ljava/net/ProxySelector; 208
-Lcom/android/okhttp/okio/SegmentPool; 209
-Lcom/android/okhttp/internal/http/AuthenticatorAdapter;.INSTANCE:Lcom/android/okhttp/Authenticator; 209
-Lcom/android/okhttp/HttpsHandler;.HTTP_1_1_ONLY:Ljava/util/List;.element:Ljava/lang/Object; 209
-Lcom/android/okhttp/ConfigAwareConnectionPool;.instance:Lcom/android/okhttp/ConfigAwareConnectionPool;.networkEventDispatcher:Llibcore/net/event/NetworkEventDispatcher;.listeners:Ljava/util/List; 210
-Lcom/android/okhttp/Dns;.SYSTEM:Lcom/android/okhttp/Dns; 210
-Lcom/android/okhttp/ConfigAwareConnectionPool;.instance:Lcom/android/okhttp/ConfigAwareConnectionPool; 210
-Lcom/android/okhttp/okio/AsyncTimeout; 211
-Ljava/lang/IllegalAccessException; 212
-Ljavax/net/ssl/SSLContext; 213
-Ljavax/net/ssl/HttpsURLConnection; 213
-Ljava/security/Security;.props:Ljava/util/Properties;.map:Ljava/util/concurrent/ConcurrentHashMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.12:Ljava/util/concurrent/ConcurrentHashMap$Node;.next:Ljava/util/concurrent/ConcurrentHashMap$Node; 214
-Ljava/security/Security;.props:Ljava/util/Properties;.map:Ljava/util/concurrent/ConcurrentHashMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.30:Ljava/util/concurrent/ConcurrentHashMap$Node; 214
-Landroid/database/sqlite/SQLiteTransactionListener; 215
-Landroid/accounts/OnAccountsUpdateListener; 216
-Landroid/accounts/AccountManager$20; 217
-Lsun/nio/ch/FileChannelImpl$Unmapper; 218
-Landroid/content/res/Resources;.sResourcesHistory:Ljava/util/Set;.c:Ljava/util/Collection;.m:Ljava/util/Map;.queue:Ljava/lang/ref/ReferenceQueue; 219
-Landroid/text/method/SingleLineTransformationMethod; 220
-Landroid/widget/RelativeLayout; 221
-Landroid/graphics/drawable/BitmapDrawable; 222
-Landroid/graphics/drawable/GradientDrawable; 223
-Landroid/animation/PropertyValuesHolder;.sGetterPropertyMap:Ljava/util/HashMap; 224
-Landroid/animation/PropertyValuesHolder$FloatPropertyValuesHolder;.sJNISetterPropertyMap:Ljava/util/HashMap; 225
-Landroid/graphics/drawable/Drawable;.DEFAULT_TINT_MODE:Landroid/graphics/PorterDuff$Mode; 226
-Landroid/text/StaticLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool; 227
-Landroid/text/StaticLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 227
-Ljava/util/concurrent/ThreadLocalRandom; 228
-Landroid/widget/Space; 229
-Landroid/widget/ScrollView; 230
-Landroid/text/style/LineHeightSpan; 231
-Landroid/text/style/TabStopSpan; 232
-Landroid/text/style/ReplacementSpan; 233
-Landroid/text/style/MetricAffectingSpan; 233
-Landroid/text/style/LeadingMarginSpan; 233
+Landroid/view/WindowManagerImpl; 80
+Landroid/view/accessibility/AccessibilityManager; 81
+Landroid/app/ActivityTaskManager;.IActivityTaskManagerSingleton:Landroid/util/Singleton; 82
+Landroid/os/Handler; 83
+Landroid/transition/ChangeImageTransform; 109
+Landroid/transition/ChangeClipBounds; 109
+Landroid/transition/ChangeTransform; 109
+Landroid/graphics/drawable/ColorDrawable; 110
+Landroid/text/TextUtils; 111
+Landroid/graphics/TemporaryBuffer; 112
+Landroid/text/TextLine;.sCached:[Landroid/text/TextLine; 113
+Landroid/text/Layout;.sTempRect:Landroid/graphics/Rect; 114
+Landroid/widget/ImageView; 115
+Landroid/content/res/ColorStateList;.sCache:Landroid/util/SparseArray; 116
+Landroid/graphics/Bitmap;.sAllBitmaps:Ljava/util/WeakHashMap; 117
+Landroid/icu/impl/locale/BaseLocale;.CACHE:Landroid/icu/impl/locale/BaseLocale$Cache;._map:Ljava/util/concurrent/ConcurrentHashMap; 118
+Landroid/database/sqlite/SQLiteGlobal; 125
+Landroid/database/sqlite/SQLiteDebug$NoPreloadHolder; 125
+Landroid/database/sqlite/SQLiteCompatibilityWalFlags; 125
+Landroid/database/CursorWindow; 126
+Landroid/content/SharedPreferences; 127
+Landroid/app/AppOpsManager; 132
+Landroid/app/LoadedApk;.sApplications:Landroid/util/ArrayMap;.mHashes:[I 133
+Landroid/media/MediaFrameworkPlatformInitializer; 133
+Lcom/android/internal/os/RuntimeInit; 133
+Landroid/os/Message; 133
+Landroid/content/res/Resources;.sResourcesHistory:Ljava/util/Set;.c:Ljava/util/Collection;.m:Ljava/util/Map; 133
+Landroid/os/ServiceManager; 133
+Landroid/se/omapi/SeFrameworkInitializer; 133
+Landroid/ddm/DdmHandleAppName; 133
+Landroid/security/net/config/ApplicationConfig; 133
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.7:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object; 133
+Landroid/os/Environment; 133
+Landroid/os/Looper; 133
+Landroid/content/res/Resources;.sResourcesHistory:Ljava/util/Set;.c:Ljava/util/Collection;.m:Ljava/util/Map;.table:[Ljava/util/WeakHashMap$Entry; 133
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.7:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object;.mCache:Ljava/util/LinkedHashMap; 133
+Landroid/os/StrictMode; 133
+Landroid/provider/DeviceConfigInitializer; 133
+Landroid/graphics/Typeface; 133
+Landroid/app/ActivityThread; 133
+Landroid/view/View; 133
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap; 133
+Landroid/app/LoadedApk;.sApplications:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object; 133
+Landroid/telephony/TelephonyFrameworkInitializer; 133
+Landroid/util/ArraySet; 133
+Landroid/os/Binder; 133
+Landroid/os/LocaleList; 133
+Landroid/hardware/display/DisplayManagerGlobal; 133
+Landroid/app/LoadedApk;.sApplications:Landroid/util/ArrayMap; 133
+Landroid/security/net/config/SystemCertificateSource$NoPreloadHolder; 133
+Landroid/os/DdmSyncState; 133
+Landroid/os/GraphicsEnvironment;.sInstance:Landroid/os/GraphicsEnvironment; 134
+Landroid/os/Parcel;.mCreators:Ljava/util/HashMap; 134
+Landroid/os/Parcel; 134
+Landroid/app/ApplicationLoaders;.gApplicationLoaders:Landroid/app/ApplicationLoaders;.mLoaders:Landroid/util/ArrayMap; 134
+Landroid/os/Process; 134
+Landroid/os/Parcel;.sPairedCreators:Ljava/util/HashMap; 134
+Landroid/graphics/Compatibility; 135
+Landroid/app/DexLoadReporter;.INSTANCE:Landroid/app/DexLoadReporter;.mDataDirs:Ljava/util/Set;.map:Ljava/util/HashMap; 135
+Landroid/renderscript/RenderScriptCacheDir; 135
+Landroid/graphics/Canvas; 135
+Landroid/provider/FontsContract; 135
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.4:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object;.mCache:Ljava/util/LinkedHashMap; 136
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.4:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object; 136
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.9:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object; 139
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.9:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object;.mCache:Ljava/util/LinkedHashMap; 140
+Lcom/android/internal/os/BinderInternal; 141
+Landroid/app/servertransaction/ClientTransactionListenerController; 142
+Landroid/app/QueuedWork; 143
+Landroid/view/WindowManagerGlobal; 144
+Landroid/view/WindowManager; 145
+Landroid/view/inputmethod/InputMethodManager; 146
+Landroid/telephony/TelephonyManager; 147
+Landroid/content/Context; 151
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.4:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object;.mSkips:[J 152
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.9:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object;.mSkips:[J 153
+Landroid/app/NotificationManager; 154
+Landroid/content/pm/VersionedPackage; 155
+Landroid/content/ContentResolver; 156
+Landroid/content/SharedPreferences$OnSharedPreferenceChangeListener; 160
+Landroid/app/UiModeManager; 162
+Landroid/webkit/WebViewFactory; 163
+Landroid/webkit/WebViewFactory;.sTimestamps:Landroid/webkit/WebViewFactory$StartupTimestamps; 164
+Landroid/webkit/WebViewFactoryProvider; 165
+Landroid/webkit/WebViewProvider$ViewDelegate; 166
+Landroid/webkit/WebViewProvider; 166
+Landroid/webkit/WebViewProvider$ScrollDelegate; 166
+Landroid/webkit/CookieSyncManager; 167
+Landroid/media/MediaCodecList; 168
+Landroid/media/MediaCodecInfo$CodecCapabilities$FeatureList; 168
+Landroid/media/MediaCodec; 169
+Landroid/view/KeyEvent; 170
+Landroid/webkit/HttpAuthHandler; 171
+Landroid/webkit/WebResourceResponse; 171
+Landroid/webkit/WebViewClient; 171
+Landroid/webkit/WebResourceError; 171
+Landroid/webkit/WebView; 171
+Landroid/view/InputEvent; 171
+Landroid/webkit/RenderProcessGoneDetail; 171
+Landroid/webkit/WebResourceRequest; 172
+Landroid/view/PointerIcon;.SYSTEM_ICONS:Landroid/util/SparseArray; 173
+Landroid/content/ClipboardManager$OnPrimaryClipChangedListener; 174
+Landroid/hardware/input/InputManager$InputDeviceListener; 175
+Landroid/hardware/input/InputManagerGlobal; 176
+Landroid/window/WindowTokenClientController; 177
+Landroid/os/PowerManager$OnThermalStatusChangedListener; 178
+Landroid/webkit/WebViewFactoryProvider$Statics; 179
+Landroid/webkit/DownloadListener; 180
+Landroid/webkit/ConsoleMessage; 181
+Landroid/webkit/GeolocationPermissions$Callback; 181
+Landroid/webkit/PermissionRequest; 181
+Landroid/webkit/WebChromeClient$CustomViewCallback; 181
+Landroid/webkit/WebChromeClient; 181
+Landroid/webkit/ValueCallback; 182
+Landroid/view/View$OnDragListener; 183
+Landroid/view/autofill/Helper; 184
+Landroid/icu/impl/ICUResourceBundleReader;.CACHE:Landroid/icu/impl/ICUResourceBundleReader$ReaderCache;.map:Ljava/util/concurrent/ConcurrentHashMap; 185
+Landroid/icu/impl/ZoneMeta;.CANONICAL_ID_CACHE:Landroid/icu/impl/ICUCache; 186
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.10:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object; 187
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.10:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object;.mCache:Ljava/util/LinkedHashMap; 188
+Landroid/graphics/fonts/Font$NoImagePreloadHolder; 189
+Landroid/icu/text/DecimalFormatSymbols;.cachedLocaleData:Landroid/icu/impl/CacheBase;.map:Ljava/util/concurrent/ConcurrentHashMap; 198
+Landroid/icu/impl/CurrencyData;.provider:Landroid/icu/impl/CurrencyData$CurrencyDisplayInfoProvider; 199
+Landroid/icu/text/DateFormatSymbols;.DFSCACHE:Landroid/icu/impl/CacheBase;.map:Ljava/util/concurrent/ConcurrentHashMap; 204
+Landroid/icu/util/ULocale; 205
+Landroid/graphics/Paint;.sMinikinLocaleListIdCache:Ljava/util/HashMap; 206
+Landroid/os/Parcelable$Creator; 207
+Landroid/graphics/drawable/Drawable; 215
+Landroid/graphics/Bitmap$Config;.RGB_565:Landroid/graphics/Bitmap$Config; 218
+Landroid/graphics/Bitmap$Config;.RGBA_F16:Landroid/graphics/Bitmap$Config; 218
+Landroid/renderscript/Allocation;.mBitmapOptions:Landroid/graphics/BitmapFactory$Options;.inPreferredConfig:Landroid/graphics/Bitmap$Config; 218
+Landroid/graphics/Bitmap$Config;.HARDWARE:Landroid/graphics/Bitmap$Config; 218
+Landroid/graphics/Bitmap$Config;.RGBA_1010102:Landroid/graphics/Bitmap$Config; 218
+Landroid/graphics/Bitmap$Config;.ALPHA_8:Landroid/graphics/Bitmap$Config; 218
+Landroid/graphics/Bitmap$Config;.ARGB_4444:Landroid/graphics/Bitmap$Config; 218
+Landroid/os/ParcelFileDescriptor; 219
+Landroid/content/ComponentName; 224
+Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle; 225
+Landroid/database/sqlite/SQLiteDatabase$CursorFactory; 226
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.7:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object;.mSkips:[J 227
+Landroid/util/ArrayMap; 229
+Landroid/media/AudioManager; 230
+Landroid/content/res/Resources;.sResourcesHistory:Ljava/util/Set;.c:Ljava/util/Collection;.m:Ljava/util/Map;.queue:Ljava/lang/ref/ReferenceQueue; 231
+Lcom/android/internal/util/ArrayUtils;.sCache:[Ljava/lang/Object; 232
+Landroid/text/SpanWatcher; 233
Landroid/text/style/LineBackgroundSpan; 234
-Landroid/text/style/CharacterStyle; 235
-Landroid/text/style/SuggestionSpan; 236
-Landroid/widget/TextView$ChangeWatcher; 237
-Landroid/text/DynamicLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 238
-Landroid/text/DynamicLayout; 238
-Landroid/text/DynamicLayout$ChangeWatcher; 238
-Landroid/text/style/WrapTogetherSpan; 238
-Landroid/text/DynamicLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool; 238
-Landroid/text/method/LinkMovementMethod; 239
+Landroid/text/style/LeadingMarginSpan; 235
+Landroid/text/style/TabStopSpan; 236
+Landroid/text/style/LineBreakConfigSpan; 237
+Landroid/text/style/MetricAffectingSpan; 238
+Landroid/text/style/LineHeightSpan; 239
Landroid/text/style/ClickableSpan; 240
-Ljava/util/logging/LogRecord;.globalSequenceNumber:Ljava/util/concurrent/atomic/AtomicLong; 241
-Ljava/lang/Runtime;.currentRuntime:Ljava/lang/Runtime; 242
-Landroid/content/pm/LauncherActivityInfo; 243
-Landroid/database/sqlite/SQLiteMisuseException; 243
-Landroid/speech/tts/TextToSpeech$Connection$SetupConnectionAsyncTask; 243
-Landroid/database/sqlite/SQLiteCantOpenDatabaseException; 243
-Landroid/database/sqlite/SQLiteDatabaseCorruptException; 243
-Landroid/database/sqlite/SQLiteDatabaseLockedException; 243
-Ljava/util/Map$Entry; 243
-Ljava/util/zip/ZipException; 243
-Landroid/database/sqlite/SQLiteAccessPermException; 243
-Landroid/speech/tts/TextToSpeech$OnInitListener; 243
-Landroid/app/Notification$MessagingStyle; 244
-Landroid/text/TextUtils$TruncateAt; 245
-Landroid/app/smartspace/SmartspaceTarget; 246
-Landroid/app/prediction/AppTarget; 246
-Landroid/app/smartspace/uitemplatedata/BaseTemplateData; 246
-Landroid/location/LocationManager;.sLocationListeners:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry; 247
-Landroid/location/LocationManager;.sLocationListeners:Ljava/util/WeakHashMap; 247
-Landroid/service/notification/ConditionProviderService; 248
-Landroid/os/WorkSource; 249
-Landroid/security/keystore2/AndroidKeyStoreProvider; 249
-Ljava/net/Socket; 249
-Lcom/android/internal/listeners/ListenerTransport; 249
-Landroid/os/ParcelUuid; 250
-Landroid/telephony/emergency/EmergencyNumber; 251
-Lcom/android/internal/telephony/uicc/UiccProfile$4; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$IncomingSms; 251
-Lcom/android/internal/telephony/SmsStorageMonitor$1; 251
-Lcom/android/internal/telephony/TelephonyDevController; 251
-Lcom/android/internal/telephony/uicc/UiccController; 251
-Lcom/android/internal/telephony/emergency/EmergencyNumberTracker$1; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$DataCallSession; 251
-Lcom/android/internal/telephony/TelephonyDevController;.mSims:Ljava/util/ArrayList; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$RcsAcsProvisioningStats; 251
-Ljava/lang/UnsupportedOperationException; 251
-Landroid/database/CursorToBulkCursorAdaptor; 251
-Lcom/android/internal/telephony/satellite/PointingAppController; 251
-Landroid/telephony/ModemActivityInfo; 251
-Lcom/android/internal/telephony/imsphone/ImsPhone; 251
-Lcom/android/internal/telephony/ServiceStateTracker; 251
-Lcom/android/internal/telephony/IccSmsInterfaceManager; 251
-Lcom/android/internal/telephony/util/NotificationChannelController$1; 251
-Lcom/android/internal/telephony/RilWakelockInfo; 251
-Lcom/android/internal/telephony/gsm/GsmInboundSmsHandler$GsmCbTestBroadcastReceiver; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SipTransportFeatureTagStats; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$UceEventStats; 251
-Lcom/android/internal/telephony/euicc/EuiccConnector$BindingState; 251
-Lcom/android/internal/telephony/ims/ImsResolver$3; 251
-Landroid/net/NetworkPolicyManager$SubscriptionCallbackProxy; 251
-Lcom/android/internal/telephony/TelephonyDevController;.mModems:Ljava/util/ArrayList; 251
-Landroid/telephony/ims/aidl/IImsServiceController$Stub$Proxy; 251
-Lcom/android/internal/telephony/CarrierPrivilegesTracker$1; 251
-Lcom/android/internal/telephony/CommandException; 251
-Lcom/android/ims/FeatureConnector$1; 251
-Lcom/android/internal/telephony/IWapPushManager; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SipDelegateStats; 251
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker; 251
-Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mTtyModeReceivedRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
-Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mClassLoader:Ljava/lang/ClassLoader; 251
-Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mMmiCompleteRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
-Lcom/android/i18n/timezone/TelephonyLookup; 251
-Landroid/telephony/BarringInfo$BarringServiceInfo; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$NetworkRequests; 251
-Lcom/android/internal/telephony/euicc/EuiccConnector$ConnectedState$14; 251
-Lcom/android/internal/telephony/SmsBroadcastUndelivered; 251
-Lcom/android/internal/telephony/LocaleTracker; 251
-Lcom/android/internal/telephony/PhoneSubInfoController; 251
-Lcom/android/internal/telephony/CarrierKeyDownloadManager$1; 251
-Lcom/android/internal/telephony/GsmCdmaCallTracker$1; 251
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.339:[Ljava/lang/String; 251
-Lcom/android/internal/telephony/ServiceStateTracker$1; 251
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.353:[Ljava/lang/String; 251
-Lcom/android/internal/telephony/euicc/EuiccCardController$SimSlotStatusChangedBroadcastReceiver; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$PresenceNotifyEvent; 251
-Lcom/android/internal/telephony/SimActivationTracker$1; 251
-Landroid/telephony/ModemInfo; 251
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1393:[Ljava/lang/String; 251
-Landroid/telephony/CellSignalStrengthWcdma; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteProvision; 251
-Lcom/android/internal/telephony/PhoneConfigurationManager; 251
-Lcom/android/internal/telephony/SmsApplication$SmsPackageMonitor; 251
-Landroid/telephony/TelephonyRegistryManager$3; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$VoiceCallSession; 251
-Landroid/os/Handler$MessengerImpl; 251
-Lcom/android/internal/telephony/LocaleTracker$1; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$CellularDataServiceSwitch; 251
-Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mInCallVoicePrivacyOffRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteSosMessageRecommender; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationServiceDescStats; 251
-Lcom/android/internal/telephony/uicc/UiccPkcs15$Pkcs15Selector; 251
-Lcom/android/internal/telephony/CarrierResolver$2; 251
-Lcom/android/internal/telephony/CarrierActionAgent$1; 251
-Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mPhones:Ljava/util/ArrayList; 251
-Lcom/android/internal/telephony/SmsController; 251
-Lcom/android/internal/telephony/uicc/euicc/EuiccCardException; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationTermination; 251
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1125:[Ljava/lang/String; 251
-Lcom/android/internal/telephony/NetworkTypeController$1; 251
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.803:[Ljava/lang/String; 251
-Lcom/android/internal/telephony/uicc/asn1/TagNotFoundException; 251
-Lcom/android/internal/telephony/CarrierServiceBindHelper$1; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$CellularServiceState; 251
-Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager; 251
-Lcom/android/internal/telephony/InboundSmsHandler$NewMessageNotificationActionReceiver; 251
-Lcom/android/internal/telephony/CarrierActionAgent; 251
-Lcom/android/i18n/timezone/TimeZoneFinder; 251
-Lcom/android/internal/telephony/RILRequest; 251
-Lcom/android/internal/telephony/RIL;.sRilTimeHistograms:Landroid/util/SparseArray; 251
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.33:[Ljava/lang/String; 251
-Lcom/android/internal/telephony/MccTable; 251
-Lcom/android/internal/telephony/uicc/UiccProfile$2; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$CarrierIdMismatch; 251
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1235:[Ljava/lang/String; 251
-Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules; 251
-Landroid/telephony/CellSignalStrengthTdscdma; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsDedicatedBearerListenerEvent; 251
-Lcom/android/internal/telephony/SmsDispatchersController; 251
-Landroid/timezone/TelephonyLookup; 251
-Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteOutgoingDatagram; 251
-Lcom/android/internal/telephony/SMSDispatcher$1; 251
-Lcom/android/internal/telephony/AppSmsManager; 251
-Landroid/timezone/TimeZoneFinder; 251
-Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mBackgroundCalls:Ljava/util/ArrayList; 251
-Lcom/android/ims/rcs/uce/eab/EabProvider; 251
-Lcom/android/internal/telephony/uicc/PinStorage$1; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsDedicatedBearerEvent; 251
-Landroid/telephony/CellSignalStrengthLte; 251
-Landroid/telephony/ims/ProvisioningManager$Callback$CallbackBinder; 251
-Lcom/android/ims/ImsManager;.IMS_STATS_CALLBACKS:Landroid/util/SparseArray;.mKeys:[I 251
-Landroid/telephony/CellSignalStrengthNr; 251
-Lcom/android/internal/telephony/SomeArgs; 251
-Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mInCallVoicePrivacyOnRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
-Lcom/android/internal/telephony/StateMachine$SmHandler; 251
-Lcom/android/internal/telephony/PackageChangeReceiver; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$OutgoingShortCodeSms; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$NetworkRequestsV2; 251
-Lcom/android/internal/telephony/nano/TelephonyProto$RilDataCall; 251
-Lcom/android/internal/telephony/euicc/EuiccConnector$AvailableState; 251
-Lcom/android/ims/internal/IImsServiceFeatureCallback$Stub$Proxy; 251
-Landroid/telephony/data/ApnSetting;.APN_TYPE_INT_MAP:Ljava/util/Map; 251
-Lcom/android/internal/telephony/RadioInterfaceCapabilityController; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationStats; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$VoiceCallRatUsage; 251
-Lcom/android/internal/telephony/metrics/TelephonyMetrics; 251
-Lcom/android/internal/telephony/nano/TelephonyProto$TelephonyCallSession$Event$RilCall; 251
-Lcom/android/internal/telephony/NetworkRegistrationManager$NetworkRegStateCallback; 251
-Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler; 251
-Lcom/android/internal/telephony/euicc/EuiccConnector$ConnectedState; 251
-Lcom/android/internal/telephony/RadioConfig; 251
-Lcom/android/internal/telephony/euicc/EuiccConnector$DisconnectedState; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteSession; 251
-Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mDisplayInfoRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
-Lcom/android/phone/ecc/nano/ProtobufEccData$EccInfo; 251
-Lcom/android/internal/telephony/GsmCdmaPhone; 251
-Lcom/android/internal/telephony/TelephonyTester$1; 251
-Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler$CdmaScpTestBroadcastReceiver; 251
-Lcom/android/internal/telephony/NetworkTypeController$DefaultState; 251
-Landroid/net/TelephonyNetworkSpecifier; 251
-Lcom/android/internal/telephony/NitzStateMachine; 251
-Landroid/app/timezonedetector/TimeZoneDetector; 251
-Lcom/android/internal/telephony/IntentBroadcaster$1; 251
-Lcom/android/internal/telephony/uicc/UiccStateChangedLauncher; 251
-Lcom/android/internal/telephony/ims/ImsResolver$1; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$OutgoingSms; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$UnmeteredNetworks; 251
-Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mClassLoader:Ljava/lang/ClassLoader;.packages:Ljava/util/Map;.m:Ljava/util/Map; 251
-Lcom/android/internal/telephony/euicc/EuiccController; 251
-Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mForegroundCalls:Ljava/util/ArrayList; 251
-Lcom/android/internal/telephony/satellite/SatelliteModemInterface; 251
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.531:[Ljava/lang/String; 251
-Lcom/android/ims/ImsManager;.IMS_STATS_CALLBACKS:Landroid/util/SparseArray; 251
-Lcom/android/internal/telephony/euicc/EuiccConnector$1; 251
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.467:[Ljava/lang/String; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SipMessageResponse; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SipTransportSession; 251
-Lcom/android/internal/telephony/euicc/EuiccConnector$UnavailableState; 251
-Lcom/android/internal/telephony/DeviceStateMonitor$3; 251
-Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mSignalInfoRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
-Lcom/android/ims/ImsManager;.IMS_STATS_CALLBACKS:Landroid/util/SparseArray;.mValues:[Ljava/lang/Object; 251
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager; 251
-Lcom/android/internal/telephony/DisplayInfoController; 251
-Lcom/android/internal/telephony/ims/ImsResolver$2; 251
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1377:[Ljava/lang/String; 251
-Lcom/android/internal/telephony/nano/TelephonyProto$TelephonyServiceState$NetworkRegistrationInfo; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteController; 251
-Landroid/telephony/ims/RegistrationManager$RegistrationCallback$RegistrationBinder; 251
-Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$EmergencyNumbersInfo; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$GbaEvent; 251
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.23:[Ljava/lang/String; 251
-Landroid/telephony/CellSignalStrengthCdma; 251
-Landroid/telephony/TelephonyLocalConnection; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteIncomingDatagram; 251
-Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker$2; 251
-Lcom/android/internal/telephony/ims/ImsResolver; 251
-Lcom/android/internal/telephony/SmsStorageMonitor; 251
-Lcom/android/internal/telephony/uicc/UiccProfile; 251
-Landroid/telephony/ims/ImsMmTelManager$CapabilityCallback$CapabilityBinder; 251
-Lcom/android/internal/telephony/euicc/EuiccCardController; 251
-Lcom/android/internal/telephony/SmsBroadcastUndelivered$1; 251
-Lcom/android/internal/telephony/GsmCdmaCallTracker; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$RcsClientProvisioningStats; 251
-Lcom/android/internal/telephony/cat/CatService; 251
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.761:[Ljava/lang/String; 251
-Lcom/android/internal/telephony/SmsApplication; 251
-Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mDisconnectRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
-Lcom/android/internal/telephony/PhoneFactory; 251
-Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mHandlerMap:Ljava/util/HashMap; 251
-Landroid/os/AsyncResult; 251
-Lcom/android/internal/telephony/ProxyController; 251
-Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler$CdmaCbTestBroadcastReceiver; 251
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.453:[Ljava/lang/String; 251
-Lcom/android/internal/telephony/MultiSimSettingController; 251
-Ljava/io/BufferedReader; 251
-Landroid/telephony/CellSignalStrengthGsm; 251
-Lcom/android/internal/telephony/SimActivationTracker; 251
-Lcom/android/internal/telephony/CellBroadcastServiceManager; 251
-Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mRingingCalls:Ljava/util/ArrayList; 251
-Lcom/android/internal/telephony/IntentBroadcaster; 251
-Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationFeatureTagStats; 251
-Lcom/android/internal/telephony/euicc/EuiccConnector$EuiccPackageMonitor; 251
-Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mSuppServiceFailedRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 251
-Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mClassLoader:Ljava/lang/ClassLoader;.packages:Ljava/util/Map;.m:Ljava/util/Map;.table:[Ljava/util/HashMap$Node; 251
-Lcom/android/internal/telephony/CarrierServiceBindHelper$CarrierServicePackageMonitor; 251
-Lcom/android/internal/telephony/TelephonyComponentFactory; 251
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.637:[Ljava/lang/String; 251
-Lcom/android/phone/ecc/nano/ProtobufEccData$CountryInfo; 251
-Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.651:[Ljava/lang/String; 251
-Lcom/android/internal/telephony/SmsUsageMonitor; 251
-Lcom/android/internal/telephony/CommandException$Error;.INVALID_SIM_STATE:Lcom/android/internal/telephony/CommandException$Error; 251
-Landroid/hardware/display/DisplayManagerGlobal$DisplayManagerCallback; 252
-Landroid/app/ActivityThread$ApplicationThread; 252
-Landroid/app/ActivityManager$MyUidObserver; 253
-Landroid/media/browse/MediaBrowser$ServiceCallbacks; 253
-Landroid/media/session/MediaController$CallbackStub; 253
-Landroid/media/session/MediaSessionManager$OnMediaKeyEventSessionChangedListener; 253
-Landroid/app/PendingIntent$CancelListener; 253
-Landroid/media/AudioManager$2; 253
-Landroid/database/ContentObserver$Transport; 253
-Landroid/media/session/MediaSessionManager$SessionsChangedWrapper$1; 253
-Landroid/content/ContentProvider$PipeDataWriter; 254
-Landroid/security/net/config/UserCertificateSource$NoPreloadHolder; 255
-Landroid/view/Window$Callback; 256
-Landroid/transition/TransitionManager;.sDefaultTransition:Landroid/transition/Transition;.mTransitions:Ljava/util/ArrayList;.elementData:[Ljava/lang/Object;.1:Landroid/transition/ChangeBounds;.mCurrentAnimators:Ljava/util/ArrayList; 256
-Landroid/transition/TransitionManager;.sDefaultTransition:Landroid/transition/Transition;.mTransitions:Ljava/util/ArrayList;.elementData:[Ljava/lang/Object;.2:Landroid/transition/Fade;.mCurrentAnimators:Ljava/util/ArrayList; 256
-Landroid/transition/TransitionManager;.sPendingTransitions:Ljava/util/ArrayList; 256
-Landroid/transition/TransitionManager;.sDefaultTransition:Landroid/transition/Transition;.mTransitions:Ljava/util/ArrayList;.elementData:[Ljava/lang/Object;.0:Landroid/transition/Fade;.mCurrentAnimators:Ljava/util/ArrayList; 256
-Landroid/view/AttachedSurfaceControl$OnBufferTransformHintChangedListener; 257
-Landroid/webkit/ValueCallback; 258
-Landroid/webkit/WebResourceRequest; 258
-Landroid/webkit/WebChromeClient$CustomViewCallback; 258
-Landroid/hardware/camera2/CameraCharacteristics;.INFO_SUPPORTED_HARDWARE_LEVEL:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 258
-Landroid/accounts/Account; 258
-Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 258
-Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DYNAMIC_DEPTH_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/CameraCharacteristics;.HEIC_AVAILABLE_HEIC_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/CameraCharacteristics;.JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/params/StreamConfigurationDuration; 259
-Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DYNAMIC_DEPTH_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/CameraCharacteristics;.JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/CameraCharacteristics;.CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/CameraCharacteristics;.HEIC_AVAILABLE_HEIC_STALL_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/CameraCharacteristics;.JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/CameraCharacteristics;.HEIC_AVAILABLE_HEIC_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/params/HighSpeedVideoConfiguration; 259
-Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/CameraCharacteristics;.DEPTH_AVAILABLE_DYNAMIC_DEPTH_STREAM_CONFIGURATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-I 259
-Landroid/hardware/camera2/CameraCharacteristics;.REQUEST_AVAILABLE_CAPABILITIES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 259
-Landroid/hardware/camera2/params/StreamConfiguration; 259
-Z 260
-Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_PIXEL_ARRAY_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.LENS_FOCAL_LENGTH:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.LENS_INFO_AVAILABLE_APERTURES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.DISTORTION_CORRECTION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.EXTENSION_STRENGTH:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-J 260
-Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_PHYSICAL_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.TONEMAP_PRESET_CURVE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-B 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_AF_TRIGGER:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_EXPOSURE_COMPENSATION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-[D 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_AWB_REGIONS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.REQUEST_AVAILABLE_SESSION_KEYS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.SENSOR_EXPOSURE_TIME:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_CALIBRATION_TRANSFORM2:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_TRANSFORM:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/content/res/Resources$Theme; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_LOCK:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-F 260
-Landroid/hardware/camera2/CaptureRequest;.LENS_FILTER_DENSITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.LENS_OPTICAL_STABILIZATION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.NOISE_REDUCTION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.SENSOR_FRAME_DURATION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_REGIONS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_EXTENDED_SCENE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.STATISTICS_OIS_DATA_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.SENSOR_TEST_PATTERN_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.HOT_PIXEL_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_ANTIBANDING_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.STATISTICS_LENS_SHADING_MAP_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.SCALER_CROP_REGION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.LENS_FOCUS_DISTANCE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.TONEMAP_GAMMA:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_REFERENCE_ILLUMINANT2:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_REFERENCE_ILLUMINANT1:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-[F 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_ZOOM_RATIO:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_ABERRATION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.TONEMAP_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.REQUEST_AVAILABLE_REQUEST_KEYS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.SCALER_ROTATE_AND_CROP:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_GAINS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_COLOR_TRANSFORM1:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_AF_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.SENSOR_SENSITIVITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.LENS_INFO_AVAILABLE_FOCAL_LENGTHS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_OPTICAL_BLACK_REGIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.JPEG_QUALITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.FLASH_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_POST_RAW_SENSITIVITY_BOOST:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_WHITE_LEVEL:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_SETTINGS_OVERRIDE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-[Landroid/hardware/camera2/params/MeteringRectangle; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_AWB_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.LOGICAL_MULTI_CAMERA_PHYSICAL_IDS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_EXPOSURE_TIME_RANGE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Ljava/lang/Float; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_ENABLE_ZSL:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.INFO_DEVICE_STATE_ORIENTATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_CALIBRATION_TRANSFORM1:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.EDGE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_CAPTURE_INTENT:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_ORIENTATION:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.JPEG_ORIENTATION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_COLOR_TRANSFORM2:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-[J 260
-Landroid/hardware/camera2/CameraCharacteristics;.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Ljava/util/concurrent/Phaser; 260
-Landroid/hardware/camera2/CaptureRequest;.BLACK_LEVEL_LOCK:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_SCENE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.JPEG_THUMBNAIL_SIZE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.SHADING_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.STATISTICS_FACE_DETECT_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.STATISTICS_HOT_PIXEL_MAP_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_AUTOFRAMING:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_TARGET_FPS_RANGE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_AWB_LOCK:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.SENSOR_TEST_PATTERN_DATA:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_PRECAPTURE_TRIGGER:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.FLASH_STRENGTH_LEVEL:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_VIDEO_STABILIZATION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.REPROCESS_EFFECTIVE_EXPOSURE_FACTOR:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Ljava/lang/Boolean; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_EFFECT_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.LENS_APERTURE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.JPEG_THUMBNAIL_QUALITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Landroid/hardware/camera2/CaptureRequest;.CONTROL_AF_REGIONS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-Ljava/lang/Long; 260
-Landroid/hardware/camera2/CaptureRequest;.SENSOR_PIXEL_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 260
-[Ljava/lang/String; 261
-[Z 262
-Ljava/lang/Class$Caches;.genericInterfaces:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap; 263
-Ljava/util/Map; 264
-Ljava/nio/Bits; 265
-Ljava/nio/DirectByteBuffer; 266
-Ljava/io/File; 267
-Ljava/nio/ByteBuffer; 268
-Ljava/io/InputStream; 269
-Landroid/os/ParcelFileDescriptor; 270
-Landroid/os/BinderProxy;.sProxyMap:Landroid/os/BinderProxy$ProxyMap; 271
-Landroid/app/PendingIntent; 272
-Landroid/content/Intent; 273
-Landroid/net/Uri$HierarchicalUri; 274
-Landroid/net/Uri$StringUri; 275
-Landroid/net/Uri$PathPart;.EMPTY:Landroid/net/Uri$PathPart; 276
-Lcom/android/internal/telephony/MccTable;.FALLBACKS:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.6:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 277
-Landroid/icu/text/DecimalFormatSymbols;.cachedLocaleData:Landroid/icu/impl/CacheBase;.map:Ljava/util/concurrent/ConcurrentHashMap; 278
-Llibcore/icu/DecimalFormatData;.CACHE:Ljava/util/concurrent/ConcurrentHashMap; 279
-Landroid/icu/impl/CurrencyData;.provider:Landroid/icu/impl/CurrencyData$CurrencyDisplayInfoProvider; 280
-Lcom/android/internal/infra/AndroidFuture; 281
-Lcom/android/internal/util/LatencyTracker$Action; 282
-Landroid/app/AppOpsManager$Mode; 283
-Landroid/view/accessibility/AccessibilityManager$AccessibilityServicesStateChangeListener; 284
-Landroid/annotation/IdRes; 285
-Landroid/content/pm/PackageItemInfo; 286
-Ljava/util/Random; 287
-Landroid/widget/RadioButton; 288
-Lcom/android/internal/policy/PhoneWindow$PanelFeatureState$SavedState; 289
-Landroid/graphics/Insets; 290
-Landroid/view/View;.sNextGeneratedId:Ljava/util/concurrent/atomic/AtomicInteger; 291
-Landroid/graphics/drawable/LayerDrawable; 292
-Landroid/animation/LayoutTransition; 293
-Llibcore/reflect/AnnotationFactory;.cache:Ljava/util/Map; 294
-Llibcore/reflect/AnnotationFactory;.cache:Ljava/util/Map;.table:[Ljava/util/WeakHashMap$Entry; 294
-Ljava/lang/reflect/Proxy;.proxyClassCache:Ljava/lang/reflect/WeakCache;.reverseMap:Ljava/util/concurrent/ConcurrentMap; 295
-Ljava/lang/reflect/Proxy$ProxyClassFactory;.nextUniqueNumber:Ljava/util/concurrent/atomic/AtomicLong; 295
-Ljava/lang/reflect/Proxy;.proxyClassCache:Ljava/lang/reflect/WeakCache;.map:Ljava/util/concurrent/ConcurrentMap; 296
-Ljava/lang/Object; 297
-Ljava/lang/invoke/MethodType;.internTable:Ljava/lang/invoke/MethodType$ConcurrentWeakInternSet;.map:Ljava/util/concurrent/ConcurrentMap; 298
-Ljava/nio/channels/SocketChannel;.dexCache:Ljava/lang/Object; 298
-Ljava/lang/invoke/MethodType;.objectOnlyTypes:[Ljava/lang/invoke/MethodType; 299
-Ljava/util/concurrent/ForkJoinTask; 300
-Ljava/util/concurrent/CompletableFuture; 301
-Landroid/app/Notification$BigTextStyle; 302
-Landroid/content/pm/ApplicationInfo; 303
-Ljava/security/Signature;.signatureInfo:Ljava/util/Map;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.13:Ljava/util/concurrent/ConcurrentHashMap$Node;.next:Ljava/util/concurrent/ConcurrentHashMap$Node;.next:Ljava/util/concurrent/ConcurrentHashMap$Node; 304
-Lsun/security/x509/X500Name;.stateName_oid:Lsun/security/util/ObjectIdentifier; 305
-Lsun/security/x509/X500Name;.localityName_oid:Lsun/security/util/ObjectIdentifier; 306
-Lsun/security/x509/X500Name;.orgUnitName_oid:Lsun/security/util/ObjectIdentifier; 306
-Ljava/util/UUID; 307
-Landroid/app/slice/Slice; 308
-Ljava/util/Locale;.FRENCH:Ljava/util/Locale; 308
-Landroid/os/NullVibrator; 308
-Ldalvik/system/CloseGuard;.MESSAGE:Ljava/lang/String; 308
-Lsun/util/locale/BaseLocale$Cache;.CACHE:Lsun/util/locale/BaseLocale$Cache;.map:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.22:Ljava/util/concurrent/ConcurrentHashMap$Node;.val:Ljava/lang/Object;.referent:Ljava/lang/Object; 308
-Ljava/util/Locale$Cache;.LOCALECACHE:Ljava/util/Locale$Cache;.map:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.24:Ljava/util/concurrent/ConcurrentHashMap$Node;.val:Ljava/lang/Object;.referent:Ljava/lang/Object; 308
-Landroid/app/Activity$$ExternalSyntheticLambda0; 308
-Landroid/icu/impl/locale/BaseLocale;.CACHE:Landroid/icu/impl/locale/BaseLocale$Cache;._map:Ljava/util/concurrent/ConcurrentHashMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.0:Ljava/util/concurrent/ConcurrentHashMap$Node; 308
-Ljava/util/Locale;.ITALIAN:Ljava/util/Locale; 308
-Landroid/media/MediaRouter2Manager$Callback; 308
-Lsun/util/locale/BaseLocale$Cache;.CACHE:Lsun/util/locale/BaseLocale$Cache;.map:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.29:Ljava/util/concurrent/ConcurrentHashMap$Node;.val:Ljava/lang/Object;.referent:Ljava/lang/Object; 308
-Ljava/util/Locale;.GERMAN:Ljava/util/Locale; 309
-Landroid/icu/impl/StandardPlural; 310
-Landroid/icu/impl/number/range/StandardPluralRanges; 311
-Landroid/icu/impl/PluralRulesLoader;.loader:Landroid/icu/impl/PluralRulesLoader; 311
-Landroid/icu/impl/PluralRulesLoader;.loader:Landroid/icu/impl/PluralRulesLoader;.pluralRulesCache:Ljava/util/Map; 311
-Landroid/icu/text/PluralRules$Operand; 311
-Landroid/icu/util/Calendar;.PATTERN_CACHE:Landroid/icu/impl/ICUCache; 312
-Landroid/icu/impl/DateNumberFormat;.CACHE:Landroid/icu/impl/SimpleCache; 313
-Landroid/text/format/DateFormat; 314
-Landroid/view/View$OnDragListener; 315
-Landroid/hardware/input/InputManager$InputDeviceListener; 316
-Landroid/hardware/input/InputManagerGlobal; 317
-Landroid/hardware/SystemSensorManager; 318
-Lcom/android/internal/os/BackgroundThread; 319
-Ljava/lang/Throwable; 320
-Landroid/app/NotificationManager; 321
-Landroid/app/NotificationChannel; 322
-Landroid/content/SharedPreferences$OnSharedPreferenceChangeListener; 323
-Landroid/content/pm/VersionedPackage; 324
-Landroid/app/AppOpsManager; 325
-Ldalvik/system/ZipPathValidator; 326
-Landroid/content/pm/PackageManager;.sPackageInfoCache:Landroid/app/PropertyInvalidatedCache;.mSkips:[J 327
-Landroid/content/pm/PackageManager;.sApplicationInfoCache:Landroid/app/PropertyInvalidatedCache;.mSkips:[J 328
-Lsun/util/locale/BaseLocale$Cache;.CACHE:Lsun/util/locale/BaseLocale$Cache;.map:Ljava/util/concurrent/ConcurrentMap; 329
-Landroid/content/Context; 330
-Ljava/util/concurrent/Executor; 331
-Ljava/util/concurrent/ScheduledExecutorService; 332
-Ljava/util/concurrent/ExecutorService; 332
-Landroid/view/Window$OnFrameMetricsAvailableListener; 333
-Ljava/lang/annotation/Annotation; 334
-Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 335
-Ljava/util/concurrent/CancellationException; 336
-Ljava/lang/NoSuchMethodException; 337
-Landroid/os/strictmode/CustomViolation; 338
-Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.3:Ljava/util/WeakHashMap$Entry; 339
-Lcom/android/internal/policy/PhoneWindow; 340
-Landroid/view/autofill/AutofillValue; 340
-Landroid/widget/TextView$SavedState; 341
-Landroid/text/method/MetaKeyKeyListener;.SYM:Ljava/lang/Object; 342
-Landroid/text/method/MetaKeyKeyListener;.ALT:Ljava/lang/Object; 342
-Landroid/text/method/MetaKeyKeyListener;.SELECTING:Ljava/lang/Object; 342
-Landroid/text/method/MetaKeyKeyListener;.CAP:Ljava/lang/Object; 342
-Landroid/widget/PopupWindow$PopupBackgroundView; 343
-Landroid/widget/TextView;.TEMP_RECTF:Landroid/graphics/RectF; 343
-Landroid/text/method/ScrollingMovementMethod; 343
-Landroid/icu/impl/locale/UnicodeLocaleExtension;.EMPTY_SORTED_SET:Ljava/util/SortedSet;.m:Ljava/util/NavigableMap; 343
-Landroid/widget/PopupWindow$PopupDecorView; 343
-Landroid/widget/Editor$TextRenderNode; 343
-Landroid/widget/Editor$PositionListener; 344
-Landroid/text/style/SpellCheckSpan; 345
-Landroid/text/method/ArrowKeyMovementMethod; 346
-Landroid/text/method/TextKeyListener;.sInstance:[Landroid/text/method/TextKeyListener; 346
-Landroid/text/TextUtils$TruncateAt;.MARQUEE:Landroid/text/TextUtils$TruncateAt; 347
-Landroid/view/autofill/Helper; 348
-Lcom/android/internal/util/LatencyTracker; 349
-Lcom/android/internal/util/LatencyTracker$SLatencyTrackerHolder; 349
-Landroid/graphics/drawable/Icon; 350
-Landroid/text/style/AlignmentSpan; 351
-Landroid/text/MeasuredParagraph;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 352
-Landroid/text/MeasuredParagraph;.sPool:Landroid/util/Pools$SynchronizedPool; 352
-Landroid/icu/impl/ICUResourceBundleReader;.CACHE:Landroid/icu/impl/ICUResourceBundleReader$ReaderCache;.map:Ljava/util/concurrent/ConcurrentHashMap; 353
-Landroid/location/ILocationManager$Stub;.dexCache:Ljava/lang/Object; 354
-Landroid/annotation/CurrentTimeMillisLong; 355
-Ljava/lang/reflect/Method; 356
-Lcom/android/internal/os/ZygoteInit; 356
-Landroid/database/DatabaseUtils; 356
-Landroid/os/HandlerThread; 356
-Ljava/security/Signature;.signatureInfo:Ljava/util/Map;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node; 357
-Ljava/security/Signature;.signatureInfo:Ljava/util/Map; 358
-Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.queue:Ljava/lang/ref/ReferenceQueue; 359
-Landroid/telephony/TelephonyRegistryManager; 360
-Landroid/graphics/HardwareRenderer; 361
-Landroid/os/BinderProxy; 362
-Landroid/app/compat/CompatChanges;.QUERY_CACHE:Landroid/app/compat/ChangeIdStateCache;.mCache:Ljava/util/LinkedHashMap; 363
-Landroid/app/compat/CompatChanges;.QUERY_CACHE:Landroid/app/compat/ChangeIdStateCache; 363
-Landroid/app/AlarmManager; 364
-Landroid/net/metrics/DhcpClientEvent; 365
-[I 366
-Landroid/media/MediaCodecList; 367
-Landroid/graphics/drawable/InsetDrawable; 368
-Landroid/widget/ProgressBar$SavedState; 369
-Landroid/widget/ScrollView$SavedState; 370
-Landroid/graphics/drawable/AnimatedVectorDrawable; 371
-Landroid/widget/ListView; 372
-Landroid/widget/AbsListView; 373
-Landroid/widget/AbsListView$SavedState; 373
-Landroid/widget/CompoundButton$SavedState; 374
-Landroid/widget/HorizontalScrollView$SavedState; 375
-Landroid/widget/HorizontalScrollView; 376
-Landroid/icu/text/MeasureFormat;.hmsTo012:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.1:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 377
-Landroid/icu/text/MeasureFormat;.hmsTo012:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.6:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 377
-Landroid/view/View$OnSystemUiVisibilityChangeListener; 378
-Ljava/util/AbstractMap; 379
-Landroid/telephony/euicc/EuiccCardManager$ResultCallback; 380
-Ljava/lang/Character$UnicodeBlock;.CJK_SYMBOLS_AND_PUNCTUATION:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.KANBUN:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.HANGUL_COMPATIBILITY_JAMO:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.KATAKANA:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.HANGUL_SYLLABLES:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.ENCLOSED_CJK_LETTERS_AND_MONTHS:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.HANGUL_JAMO:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.BOPOMOFO_EXTENDED:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.CJK_COMPATIBILITY_FORMS:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.BOPOMOFO:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.HIRAGANA:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.HALFWIDTH_AND_FULLWIDTH_FORMS:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.KANGXI_RADICALS:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.CJK_RADICALS_SUPPLEMENT:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.KATAKANA_PHONETIC_EXTENSIONS:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.CJK_COMPATIBILITY:Ljava/lang/Character$UnicodeBlock; 381
-Ljava/lang/Character$UnicodeBlock;.CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT:Ljava/lang/Character$UnicodeBlock; 382
-Ljava/lang/Character$UnicodeBlock;.CJK_COMPATIBILITY_IDEOGRAPHS:Ljava/lang/Character$UnicodeBlock; 382
-Ljava/lang/Character$UnicodeBlock;.CJK_UNIFIED_IDEOGRAPHS:Ljava/lang/Character$UnicodeBlock; 382
-Ljava/lang/Character$UnicodeBlock;.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A:Ljava/lang/Character$UnicodeBlock; 382
-Ljava/lang/Character$UnicodeBlock;.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B:Ljava/lang/Character$UnicodeBlock; 382
-Lcom/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry; 383
-Landroid/view/Window$DecorCallback; 383
-Landroid/view/inputmethod/EditorInfo; 383
-Landroid/view/MenuItem$OnActionExpandListener; 384
-Ljava/util/Locale;.JAPANESE:Ljava/util/Locale; 385
-Ljava/util/Locale;.KOREAN:Ljava/util/Locale; 385
-Lcom/android/internal/config/appcloning/AppCloningDeviceConfigHelper; 386
-Landroid/telecom/PhoneAccountHandle; 387
-Landroid/content/AsyncQueryHandler; 388
-Landroid/speech/RecognitionListener; 389
-Ljava/lang/InstantiationException; 390
-Ljava/util/concurrent/ExecutionException; 391
-Landroid/icu/text/DateIntervalInfo;.DIICACHE:Landroid/icu/impl/ICUCache; 392
-Landroid/text/format/DateIntervalFormat;.CACHED_FORMATTERS:Landroid/util/LruCache;.map:Ljava/util/LinkedHashMap; 392
-Landroid/icu/text/DateIntervalFormat;.LOCAL_PATTERN_CACHE:Landroid/icu/impl/ICUCache; 392
-Landroid/icu/impl/OlsonTimeZone; 392
-Landroid/text/format/DateIntervalFormat;.CACHED_FORMATTERS:Landroid/util/LruCache; 392
-Landroid/graphics/drawable/Drawable; 393
-Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 394
-Landroid/app/Activity; 395
-Landroid/icu/text/PluralRules$KeywordStatus;.INVALID:Landroid/icu/text/PluralRules$KeywordStatus;.name:Ljava/lang/String; 396
-Landroid/net/Uri; 396
-Lsun/util/calendar/CalendarSystem;.calendars:Ljava/util/concurrent/ConcurrentMap; 396
-Landroid/animation/PropertyValuesHolder$IntPropertyValuesHolder;.sJNISetterPropertyMap:Ljava/util/HashMap; 397
-Landroid/graphics/drawable/ShapeDrawable; 398
-Lcom/android/internal/widget/ActionBarContextView; 399
-Landroid/widget/Toolbar$SavedState; 399
-Lcom/android/internal/widget/ActionBarContainer; 399
-Lcom/android/internal/widget/ActionBarOverlayLayout; 399
-Lcom/android/internal/widget/ActionBarContainer$ActionBarBackgroundDrawable; 399
-Landroid/widget/ActionMenuPresenter$OverflowMenuButton; 400
-Landroid/widget/ActionMenuView; 401
-Landroid/content/res/Configuration; 402
-Ljava/util/IdentityHashMap;.NULL_KEY:Ljava/lang/Object; 403
-Ljava/util/concurrent/ForkJoinPool; 404
-Landroid/os/ResultReceiver; 405
-Ljava/util/concurrent/TimeoutException; 406
-Ljava/io/IOException; 407
-Landroid/accounts/AccountAuthenticatorResponse; 408
-Landroid/nfc/NfcAdapter; 409
-Landroid/nfc/NfcAdapter;.sNfcAdapters:Ljava/util/HashMap; 409
-Landroid/app/backup/BackupManager; 410
-Landroid/app/NotificationChannelGroup; 411
-Landroid/content/pm/ParceledListSlice; 411
-Landroid/os/FileObserver; 412
-Landroid/os/UserHandle; 413
-Landroid/content/pm/PackageManager$NameNotFoundException; 414
-[Ljava/lang/Integer; 415
-Landroid/animation/PropertyValuesHolder;.sSetterPropertyMap:Ljava/util/HashMap; 415
-Landroid/content/LocusId; 416
-Landroid/view/contentcapture/ContentCaptureContext; 416
-Landroid/telephony/ims/RegistrationManager;.IMS_REG_TO_ACCESS_TYPE_MAP:Ljava/util/Map;.table:[Ljava/lang/Object;.18:Ljava/lang/Integer; 417
-Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;.pool:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.4:Ljava/util/concurrent/ConcurrentHashMap$Node; 418
-Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;.pool:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node; 418
-Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;.pool:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.2:Ljava/util/concurrent/ConcurrentHashMap$Node;.next:Ljava/util/concurrent/ConcurrentHashMap$Node; 418
-Lcom/android/internal/telephony/cdnr/CarrierDisplayNameResolver;.EF_SOURCE_PRIORITY:Ljava/util/List;.a:[Ljava/lang/Object;.9:Ljava/lang/Integer; 418
-Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;.pool:Ljava/util/concurrent/ConcurrentMap;.table:[Ljava/util/concurrent/ConcurrentHashMap$Node;.56:Ljava/util/concurrent/ConcurrentHashMap$Node; 418
-Lcom/android/internal/telephony/cdnr/CarrierDisplayNameResolver;.EF_SOURCE_PRIORITY:Ljava/util/List;.a:[Ljava/lang/Object;.5:Ljava/lang/Integer; 418
-Lcom/android/org/bouncycastle/asn1/ASN1ObjectIdentifier;.pool:Ljava/util/concurrent/ConcurrentMap; 418
-Landroid/widget/EditText; 419
-Landroid/widget/CheckedTextView; 420
-Landroid/os/strictmode/UnsafeIntentLaunchViolation; 421
-Landroid/app/Service; 422
-Ldalvik/system/BlockGuard; 423
-Landroid/hardware/devicestate/DeviceStateManagerGlobal; 424
-Landroid/hardware/camera2/CameraCharacteristics;.SCALER_MULTI_RESOLUTION_STREAM_SUPPORTED:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 425
-Landroid/hardware/camera2/marshal/MarshalRegistry;.sMarshalerMap:Ljava/util/HashMap; 425
-Landroid/hardware/camera2/CameraCharacteristics;.LENS_FACING:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 425
-Landroid/content/ClipboardManager$OnPrimaryClipChangedListener; 426
-Landroid/icu/text/BreakIterator;.iterCache:[Landroid/icu/impl/CacheValue; 427
-Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.13:Ljava/util/WeakHashMap$Entry; 428
-Landroid/icu/text/Collator; 429
-Landroid/icu/impl/number/parse/NanMatcher;.DEFAULT:Landroid/icu/impl/number/parse/NanMatcher;.uniSet:Landroid/icu/text/UnicodeSet;.strings:Ljava/util/SortedSet;.c:Ljava/util/Collection;.m:Ljava/util/NavigableMap; 430
-Ljava/io/FileNotFoundException; 431
-Landroid/os/BaseBundle; 432
-Landroid/service/watchdog/ExplicitHealthCheckService$PackageConfig; 433
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.116:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.12:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.90:Ljava/lang/String; 434
-Landroid/icu/text/MessageFormat;.rootLocale:Ljava/util/Locale;.baseLocale:Lsun/util/locale/BaseLocale;.language:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.385:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.107:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.112:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.480:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.550:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.143:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._obsoleteLanguages:[Ljava/lang/String;.1:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.473:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.138:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.204:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.71:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._replacementCountries:[Ljava/lang/String;.12:Ljava/lang/String; 434
-Landroid/icu/impl/duration/impl/DataRecord$ETimeLimit;.names:[Ljava/lang/String;.1:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._replacementCountries:[Ljava/lang/String;.9:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.99:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages3:[Ljava/lang/String;.152:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.256:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.170:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.220:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.461:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._replacementLanguages:[Ljava/lang/String;.5:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.190:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.157:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._obsoleteCountries:[Ljava/lang/String;.4:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.196:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.117:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.5:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.499:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.199:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.18:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.324:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.101:Ljava/lang/String; 434
-Landroid/icu/impl/locale/UnicodeLocaleExtension;.CA_JAPANESE:Landroid/icu/impl/locale/UnicodeLocaleExtension;._keywords:Ljava/util/SortedMap;.root:Ljava/util/TreeMap$TreeMapEntry;.key:Ljava/lang/Object; 434
-Landroid/icu/impl/LocaleIDs;._replacementCountries:[Ljava/lang/String;.3:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.140:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.105:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.37:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._replacementCountries:[Ljava/lang/String;.5:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.22:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.103:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.412:Ljava/lang/String; 434
-Landroid/icu/impl/duration/impl/DataRecord$EMilliSupport;.names:[Ljava/lang/String;.1:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.124:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.232:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.219:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.179:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.523:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.75:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.486:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.166:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.112:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.119:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.160:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.298:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.257:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.182:Ljava/lang/String; 434
-Landroid/icu/impl/units/UnitPreferences;.measurementSystem:Ljava/util/Map;.m:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.5:Ljava/util/HashMap$Node;.next:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.47:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.180:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.111:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.358:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.96:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._obsoleteLanguages:[Ljava/lang/String;.0:Ljava/lang/String; 434
-Landroid/icu/text/DateFormat;.HOUR_GENERIC_TZ:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.67:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.254:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.222:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.55:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.349:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.16:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.352:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.443:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.478:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.19:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.401:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.137:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.65:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.474:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.168:Ljava/lang/String; 434
-Landroid/icu/impl/units/UnitPreferences;.measurementSystem:Ljava/util/Map;.m:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.15:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.111:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages3:[Ljava/lang/String;.545:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.30:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.469:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.21:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.69:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.56:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.519:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._replacementLanguages:[Ljava/lang/String;.4:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.107:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.290:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.59:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.220:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.186:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.516:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.181:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.199:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.396:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.117:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.227:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.331:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.447:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.151:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.144:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.132:Ljava/lang/String; 434
-Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.230:Ljava/lang/String; 434
-Landroid/icu/text/DateFormat;.MINUTE_SECOND:Ljava/lang/String; 434
-Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 435
-Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.head:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 436
-Ljava/lang/Enum;.sharedConstantsCache:Llibcore/util/BasicLruCache;.map:Ljava/util/LinkedHashMap;.tail:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry;.before:Ljava/util/LinkedHashMap$LinkedHashMapEntry; 437
-Landroid/graphics/drawable/ColorStateListDrawable; 438
-Ljava/lang/SecurityException; 439
-Ljava/lang/RuntimeException; 440
-Landroid/media/audiopolicy/AudioProductStrategy; 441
-Landroid/os/PersistableBundle; 442
-Landroid/content/pm/ShortcutInfo; 442
-Landroid/icu/text/TimeZoneFormat;._tzfCache:Landroid/icu/text/TimeZoneFormat$TimeZoneFormatCache;.map:Ljava/util/concurrent/ConcurrentHashMap; 443
-Landroid/graphics/LeakyTypefaceStorage;.sStorage:Ljava/util/ArrayList; 443
-Landroid/graphics/LeakyTypefaceStorage;.sTypefaceMap:Landroid/util/ArrayMap; 443
-Landroid/text/TextWatcher; 444
-Landroid/view/accessibility/AccessibilityManager$TouchExplorationStateChangeListener; 445
-Ljavax/net/SocketFactory; 446
-Ljava/util/Collections; 447
-Ljava/lang/Exception; 448
-Landroid/os/UserManager; 449
-Landroid/os/RemoteException; 450
-Landroid/content/AttributionSource; 451
-Lcom/android/okhttp/internalandroidapi/HttpURLConnectionFactory$DnsAdapter; 452
-Lcom/android/okhttp/Protocol;.HTTP_2:Lcom/android/okhttp/Protocol; 452
-Ljava/net/Inet4Address; 452
-Lcom/android/okhttp/Protocol;.SPDY_3:Lcom/android/okhttp/Protocol; 452
-Lcom/android/okhttp/OkHttpClient; 452
-Landroid/os/storage/VolumeInfo; 453
-Landroid/os/storage/DiskInfo; 453
-Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mMap:Landroid/util/ArrayMap; 454
-Ljava/nio/file/StandardOpenOption;.WRITE:Ljava/nio/file/StandardOpenOption; 455
-Ljava/nio/file/StandardOpenOption;.APPEND:Ljava/nio/file/StandardOpenOption; 456
-Ljava/util/logging/FileHandler; 457
-Ljava/nio/file/StandardOpenOption;.CREATE_NEW:Ljava/nio/file/StandardOpenOption; 457
-Ljava/util/logging/FileHandler;.locks:Ljava/util/Set;.map:Ljava/util/HashMap; 457
-Lsun/nio/ch/SharedFileLockTable;.queue:Ljava/lang/ref/ReferenceQueue; 458
-Ljavax/net/ServerSocketFactory; 458
-Landroid/os/AsyncTask; 459
-Landroid/os/strictmode/UnbufferedIoViolation; 460
-Landroid/app/usage/AppStandbyInfo; 461
-Landroid/text/format/DateUtils; 462
-Landroid/security/IKeyChainService; 463
-Landroid/util/Log$TerribleFailure; 464
-Lcom/android/internal/os/RuntimeInit$KillApplicationHandler; 464
-Ljava/util/Timer;.nextSerialNumber:Ljava/util/concurrent/atomic/AtomicInteger; 465
-Landroid/telephony/ims/stub/ImsConfigImplBase$ImsConfigStub; 466
-Landroid/telephony/ims/stub/ImsRegistrationImplBase$1; 466
-Landroid/telephony/ims/ImsUtListener; 466
-Landroid/telephony/ims/feature/MmTelFeature$1; 466
-Lcom/android/ims/ImsManager;.IMS_MANAGER_INSTANCES:Landroid/util/SparseArray;.mValues:[Ljava/lang/Object; 467
-Lcom/android/ims/ImsManager;.IMS_MANAGER_INSTANCES:Landroid/util/SparseArray; 467
-Lcom/android/ims/ImsManager;.IMS_MANAGER_INSTANCES:Landroid/util/SparseArray;.mKeys:[I 467
-Landroid/telephony/ims/aidl/IImsConfig$Stub$Proxy; 468
-Landroid/telephony/ims/aidl/IImsRegistration$Stub$Proxy; 468
-Landroid/telephony/NetworkService; 469
-Landroid/telephony/TelephonyCallback$ServiceStateListener; 470
-Landroid/telephony/TelephonyCallback$PhysicalChannelConfigListener; 471
-Landroid/telephony/TelephonyCallback$RadioPowerStateListener; 471
-Lsun/security/x509/X500Name;.internedOIDs:Ljava/util/Map; 472
-Lsun/security/x509/X500Name;.internedOIDs:Ljava/util/Map;.table:[Ljava/util/HashMap$Node; 472
-Landroid/media/MediaCodec; 473
-Ljava/nio/file/StandardOpenOption;.CREATE:Ljava/nio/file/StandardOpenOption; 474
-Ljava/nio/file/NoSuchFileException; 475
-Ljava/text/DateFormatSymbols;.cachedInstances:Ljava/util/concurrent/ConcurrentMap; 476
-Ljava/util/Currency;.instances:Ljava/util/concurrent/ConcurrentMap; 476
-Ljava/util/Calendar;.cachedLocaleData:Ljava/util/concurrent/ConcurrentMap; 476
-Ljava/text/SimpleDateFormat;.cachedNumberFormatData:Ljava/util/concurrent/ConcurrentMap; 476
-Landroid/app/UriGrantsManager;.IUriGrantsManagerSingleton:Landroid/util/Singleton; 477
-Landroid/content/ContentProviderProxy; 478
-Landroid/os/DeadObjectException; 479
-Landroid/app/slice/SliceSpec; 479
-Landroid/database/sqlite/SQLiteDatabase; 480
-Ljava/util/Locale;.CHINA:Ljava/util/Locale; 481
-Ljava/util/Locale;.TAIWAN:Ljava/util/Locale; 481
-Ljava/util/Locale;.KOREA:Ljava/util/Locale; 481
-Ljava/util/Scanner; 482
-Ljava/math/BigDecimal; 483
-Ljava/security/interfaces/RSAPrivateCrtKey; 483
-Ljava/security/interfaces/RSAPrivateKey; 483
-Lcom/android/server/backup/AccountSyncSettingsBackupHelper;.KEY_ACCOUNT_TYPE:Ljava/lang/String; 483
-Landroid/util/UtilConfig; 484
-Ljava/net/ResponseCache; 485
-Landroid/content/ReceiverCallNotAllowedException; 486
-Landroid/app/ReceiverRestrictedContext; 487
-Landroid/os/strictmode/CredentialProtectedWhileLockedViolation; 488
-Landroid/app/Application; 489
-Ljava/util/NoSuchElementException; 490
-Landroid/os/Messenger; 491
-Landroid/telephony/TelephonyCallback$DataEnabledListener; 491
-Landroid/system/StructLinger; 492
+Landroid/text/DynamicLayout$ChangeWatcher; 241
+Landroid/text/DynamicLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool; 242
+Landroid/text/DynamicLayout; 242
+Landroid/text/DynamicLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 242
+Landroid/text/style/WrapTogetherSpan; 243
+Landroid/widget/TextView$ChangeWatcher; 244
+Landroid/text/Selection$MemoryTextWatcher; 245
+Landroid/text/SpannableStringBuilder;.sCachedIntBuffer:[[I 246
+Landroid/text/style/SuggestionSpan; 247
+Landroid/text/style/ReplacementSpan; 248
+Landroid/text/TextUtils$TruncateAt;.MARQUEE:Landroid/text/TextUtils$TruncateAt; 249
+Landroid/text/style/SpellCheckSpan; 250
+Landroid/text/method/ArrowKeyMovementMethod; 251
+Landroid/text/method/TextKeyListener;.sInstance:[Landroid/text/method/TextKeyListener; 251
+Landroid/view/textclassifier/TextClassificationConstants; 252
+Landroid/text/Selection;.SELECTION_START:Ljava/lang/Object; 253
+Landroid/text/Selection;.SELECTION_END:Ljava/lang/Object; 253
+Landroid/text/Selection;.SELECTION_MEMORY:Ljava/lang/Object; 253
+Landroid/widget/EditText; 254
+Landroid/view/autofill/AutofillValue; 255
+Landroid/view/ViewGroup$ChildListForAutoFillOrContentCapture;.sPool:Landroid/util/Pools$SimplePool; 256
+Landroid/view/ViewGroup$ChildListForAutoFillOrContentCapture;.sPool:Landroid/util/Pools$SimplePool;.mPool:[Ljava/lang/Object; 256
+Landroid/view/ViewGroup; 257
+Landroid/widget/TextView; 258
+Landroid/animation/AnimatorInflater;.sTmpTypedValue:Landroid/util/TypedValue; 259
+Landroid/graphics/drawable/GradientDrawable; 260
+Landroid/text/method/SingleLineTransformationMethod; 261
+Landroid/text/StaticLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 262
+Landroid/text/StaticLayout$Builder;.sPool:Landroid/util/Pools$SynchronizedPool; 262
+Landroid/os/HandlerThread; 263
+Lcom/android/internal/os/ZygoteInit; 263
+Landroid/database/DatabaseUtils; 263
+Landroid/annotation/CurrentTimeMillisLong; 264
+Landroid/app/NotificationChannel; 265
+Landroid/os/AsyncTask; 267
+Landroid/graphics/Bitmap;.sAllBitmaps:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry; 285
+Lcom/android/internal/telephony/MccTable;.FALLBACKS:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.6:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 288
+Landroid/view/Window$OnFrameMetricsAvailableListener; 289
+Landroid/graphics/drawable/BitmapDrawable; 290
+Landroid/graphics/drawable/RippleDrawable; 291
+Landroid/animation/PropertyValuesHolder$FloatPropertyValuesHolder;.sJNISetterPropertyMap:Ljava/util/HashMap; 292
+Landroid/animation/PropertyValuesHolder;.sGetterPropertyMap:Ljava/util/HashMap; 293
+Landroid/graphics/drawable/LayerDrawable; 294
+Landroid/media/audiopolicy/AudioProductStrategy;.sLock:Ljava/lang/Object; 304
+Landroid/graphics/drawable/RotateDrawable; 304
+Landroid/opengl/EGLConfig; 307
+Landroid/icu/impl/ValidIdentifiers$Datasubtype;.unknown:Landroid/icu/impl/ValidIdentifiers$Datasubtype;.name:Ljava/lang/String; 308
+Lcom/android/ims/rcs/uce/UceDeviceState;.DEVICE_STATE_DESCRIPTION:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.4:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 308
+Lcom/android/ims/rcs/uce/UceDeviceState;.DEVICE_STATE_DESCRIPTION:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.3:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 309
+Landroid/icu/text/MeasureFormat;.hmsTo012:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.0:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 310
+Landroid/telephony/ims/ImsService;.CAPABILITIES_LOG_MAP:Ljava/util/Map;.table:[Ljava/lang/Object;.2:Ljava/lang/Long; 311
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.569:Ljava/lang/Long; 311
+Landroid/icu/text/MeasureFormat;.hmsTo012:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.6:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 312
+Landroid/icu/text/MeasureFormat;.hmsTo012:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.1:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 313
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.11:Ljava/lang/Boolean; 314
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1:Ljava/lang/Boolean; 315
+Landroid/os/SystemProperties; 325
+Landroid/app/job/JobParameters; 328
+Landroid/view/Window$DecorCallback; 329
+Landroid/view/MenuItem$OnActionExpandListener; 329
+Landroid/view/inputmethod/EditorInfo; 329
+Lcom/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry; 329
+Landroid/app/ActivityManager$OnUidImportanceListener; 331
+Landroid/os/strictmode/DiskReadViolation; 332
+Landroid/os/strictmode/CustomViolation; 333
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.4:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object;.mLock:Ljava/lang/Object; 334
+Landroid/location/Location; 337
+Landroid/database/sqlite/SQLiteConstraintException; 337
+Lcom/android/internal/listeners/ListenerTransport; 338
+Landroid/content/IntentFilter; 339
+Landroid/hardware/location/ContextHubTransaction$OnCompleteListener; 340
+Landroid/app/PendingIntent$OnFinished; 340
+Landroid/os/WorkSource; 340
+Landroid/content/pm/PackageManager$OnPermissionsChangedListener; 341
+Landroid/annotation/IdRes; 342
+Landroid/app/AppOpsManager$Mode; 343
+Landroid/view/accessibility/AccessibilityManager$AccessibilityServicesStateChangeListener; 344
+Landroid/telephony/DataSpecificRegistrationInfo; 345
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle; 346
+Landroid/telephony/TelephonyRegistryManager;.sCarrierPrivilegeCallbacks:Ljava/util/WeakHashMap; 347
+Landroid/telephony/NetworkRegistrationInfo; 347
+Lcom/android/internal/telephony/TelephonyPermissions;.sReportedDeviceIDPackages:Ljava/util/Map; 347
+Landroid/telephony/AnomalyReporter; 347
+Landroid/content/ContentProvider$Transport; 347
+Landroid/database/CursorToBulkCursorAdaptor; 347
+Landroid/telephony/TelephonyRegistryManager;.sCarrierPrivilegeCallbacks:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry; 347
+Landroid/telephony/VoiceSpecificRegistrationInfo; 347
+Landroid/net/MatchAllNetworkSpecifier; 347
+Landroid/app/PropertyInvalidatedCache$NoPreloadHolder; 348
+Landroid/app/PropertyInvalidatedCache;.sInvalidates:Ljava/util/HashMap; 348
+Landroid/app/PropertyInvalidatedCache;.sDisabledKeys:Ljava/util/HashSet;.map:Ljava/util/HashMap; 349
+Landroid/media/session/MediaSessionManager$SessionsChangedWrapper$1; 350
+Landroid/media/session/MediaSessionManager$OnMediaKeyEventSessionChangedListener; 350
+Landroid/media/AudioManager$2; 350
+Landroid/app/PendingIntent$CancelListener; 350
+Landroid/app/ActivityManager$MyUidObserver; 350
+Landroid/app/compat/CompatChanges;.QUERY_CACHE:Landroid/app/compat/ChangeIdStateCache;.mCache:Ljava/util/LinkedHashMap; 351
+Landroid/app/compat/CompatChanges;.QUERY_CACHE:Landroid/app/compat/ChangeIdStateCache; 351
+Landroid/app/AlarmManager; 352
+Landroid/os/UserManager; 353
+Landroid/text/MeasuredParagraph;.sPool:Landroid/util/Pools$SynchronizedPool; 355
+Landroid/text/MeasuredParagraph;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 355
+Landroid/database/sqlite/SQLiteTransactionListener; 357
+Landroid/text/format/DateFormat; 358
+Landroid/icu/util/Calendar;.PATTERN_CACHE:Landroid/icu/impl/ICUCache; 359
+Landroid/icu/impl/DateNumberFormat;.CACHE:Landroid/icu/impl/SimpleCache; 360
+Landroid/app/smartspace/SmartspaceSession$OnTargetsAvailableListener; 361
+Lcom/android/internal/util/PerfettoTrigger;.sLastInvocationPerTrigger:Landroid/util/SparseLongArray; 361
+Lcom/android/internal/util/PerfettoTrigger;.sLastInvocationPerTrigger:Landroid/util/SparseLongArray;.mValues:[J 361
+Landroid/window/WindowOrganizer;.IWindowOrganizerControllerSingleton:Landroid/util/Singleton; 361
+Landroid/window/WindowContainerTransaction$Change; 361
+Lcom/android/internal/util/PerfettoTrigger;.sLastInvocationPerTrigger:Landroid/util/SparseLongArray;.mKeys:[I 361
+Landroid/view/ViewTreeObserver$OnWindowVisibilityChangeListener; 361
+Landroid/view/CrossWindowBlurListeners; 362
+Landroid/widget/Toast; 363
+Landroid/view/ViewStub$OnInflateListener; 364
+Landroid/text/Spanned; 365
+Lcom/android/internal/policy/PhoneLayoutInflater; 365
+Landroid/content/MutableContextWrapper; 365
+Landroid/renderscript/RenderScript; 365
+Landroid/content/pm/IPackageManager$Stub$Proxy; 367
+Landroid/media/MediaPlayer$EventHandler; 368
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.220:Ljava/lang/String; 368
+Landroid/graphics/drawable/GradientDrawable$Orientation;.BOTTOM_TOP:Landroid/graphics/drawable/GradientDrawable$Orientation; 368
+Landroid/graphics/drawable/GradientDrawable$Orientation;.RIGHT_LEFT:Landroid/graphics/drawable/GradientDrawable$Orientation; 368
+Landroid/content/res/ResourcesImpl; 368
+Landroid/os/ResultReceiver$MyRunnable; 368
+Landroid/graphics/drawable/GradientDrawable$Orientation;.TL_BR:Landroid/graphics/drawable/GradientDrawable$Orientation; 368
+Landroid/view/animation/Animation$3; 368
+Landroid/view/ViewRootImpl$7; 368
+Landroid/view/animation/Animation$1; 368
+Landroid/graphics/drawable/GradientDrawable$Orientation;.BR_TL:Landroid/graphics/drawable/GradientDrawable$Orientation; 368
+Landroid/graphics/drawable/GradientDrawable$Orientation;.TOP_BOTTOM:Landroid/graphics/drawable/GradientDrawable$Orientation; 368
+Landroid/os/PowerManager$3$$ExternalSyntheticLambda0; 368
+Landroid/graphics/drawable/GradientDrawable$Orientation;.BL_TR:Landroid/graphics/drawable/GradientDrawable$Orientation; 368
+Landroid/graphics/drawable/GradientDrawable$Orientation;.LEFT_RIGHT:Landroid/graphics/drawable/GradientDrawable$Orientation; 368
+Landroid/graphics/drawable/GradientDrawable$Orientation;.TR_BL:Landroid/graphics/drawable/GradientDrawable$Orientation; 368
+Lcom/android/internal/policy/PhoneWindow$1; 368
+Landroid/hardware/SensorManager; 368
+Landroid/widget/SeekBar; 369
+Landroid/media/MediaRouter2Manager; 370
+Landroid/app/trust/TrustManager$TrustListener; 370
+Landroid/permission/PermissionManager;.INDICATOR_EXEMPTED_PACKAGES:[Ljava/lang/String; 370
+Landroid/media/session/MediaSessionManager$SessionsChangedWrapper$1$$ExternalSyntheticLambda0; 370
+Landroid/view/ViewOverlay$OverlayViewGroup; 370
+Landroid/hardware/display/NightDisplayListener$Callback; 370
+Lcom/android/internal/widget/NotificationOptimizedLinearLayout; 370
+Landroid/hardware/biometrics/BiometricSourceType;.IRIS:Landroid/hardware/biometrics/BiometricSourceType; 370
+Landroid/view/NotificationTopLineView; 370
+Landroid/permission/PermissionManager; 370
+Landroid/text/TextShaper$GlyphsConsumer; 370
+Lcom/android/internal/widget/RemeasuringLinearLayout; 370
+Landroid/os/HandlerExecutor; 370
+Landroid/hardware/biometrics/BiometricSourceType;.FACE:Landroid/hardware/biometrics/BiometricSourceType; 370
+Landroid/animation/ValueAnimator$DurationScaleChangeListener; 370
+Landroid/widget/RemoteViews;.sLookupKey:Landroid/widget/RemoteViews$MethodKey; 370
+Lcom/android/internal/logging/UiEventLogger; 370
+Lcom/android/internal/view/menu/ActionMenuItemView; 370
+Landroid/hardware/biometrics/BiometricSourceType;.FINGERPRINT:Landroid/hardware/biometrics/BiometricSourceType; 370
+Landroid/transition/TransitionManager;.sPendingTransitions:Ljava/util/ArrayList; 370
+Landroid/graphics/drawable/DrawableInflater;.CONSTRUCTOR_MAP:Ljava/util/HashMap; 370
+Lcom/android/internal/widget/ImageFloatingTextView; 370
+Lcom/android/internal/widget/CachingIconView; 370
+Lcom/android/internal/widget/MessagingLayout; 370
+Landroid/widget/DateTimeView$ReceiverInfo$1; 370
+Landroid/view/animation/AnimationSet; 370
+Landroid/hardware/face/FaceManager$FaceDetectionCallback; 370
+Landroid/view/SurfaceControl; 370
+Lcom/android/internal/widget/NotificationExpandButton; 370
+Landroid/widget/ViewSwitcher;.dexCache:Ljava/lang/Object; 370
+Lcom/android/internal/colorextraction/ColorExtractor$OnColorsChangedListener; 370
+Landroid/view/RemotableViewMethod; 370
+Landroid/view/View;.SCALE_Y:Landroid/util/Property; 370
+Landroid/view/View;.TRANSLATION_Y:Landroid/util/Property; 370
+Landroid/telephony/satellite/SatelliteManager;.sSatelliteSupportedStateCallbackMap:Ljava/util/concurrent/ConcurrentHashMap; 370
+Landroid/view/NotificationHeaderView; 370
+Lcom/android/internal/widget/ImageResolver; 370
+Landroid/hardware/display/DisplayManagerGlobal$DisplayListenerDelegate$$ExternalSyntheticLambda0; 370
+Lcom/android/internal/widget/ConversationLayout; 370
+Lcom/android/internal/util/ContrastColorUtil; 370
+Landroid/text/format/DateUtils; 370
+Landroid/widget/RemoteViews;.sMethods:Landroid/util/ArrayMap; 370
+Landroid/widget/DateTimeView; 370
+Lcom/android/internal/widget/NotificationActionListLayout; 370
+Landroid/view/View;.SCALE_X:Landroid/util/Property; 370
+Landroid/widget/GridLayout;.UNDEFINED_ALIGNMENT:Landroid/widget/GridLayout$Alignment; 372
+Landroid/database/CursorIndexOutOfBoundsException; 374
+Lcom/android/internal/policy/DecorView$2; 375
+Landroid/widget/Spinner; 376
+Landroid/security/keystore2/AndroidKeyStoreRSAPrivateKey; 376
+Landroid/security/keystore/KeyInfo; 377
+Landroid/security/keystore2/AndroidKeyStoreECPrivateKey; 378
+Landroid/text/method/TextKeyListener;.ACTIVE:Ljava/lang/Object; 379
+Landroid/text/method/PasswordTransformationMethod; 380
+Landroid/speech/tts/TextToSpeech$Connection$SetupConnectionAsyncTask; 382
+Landroid/speech/tts/TextToSpeech$OnInitListener; 383
+Lcom/android/internal/policy/PhoneWindow; 384
+Lcom/android/internal/policy/PhoneWindow$PanelFeatureState$SavedState; 385
+Landroid/content/res/Configuration; 386
+Landroid/window/WindowContext; 386
+Landroid/icu/impl/number/parse/NanMatcher;.DEFAULT:Landroid/icu/impl/number/parse/NanMatcher;.uniSet:Landroid/icu/text/UnicodeSet;.strings:Ljava/util/SortedSet;.c:Ljava/util/Collection;.m:Ljava/util/NavigableMap; 386
+Landroid/app/Dialog$$ExternalSyntheticLambda2; 386
+Landroid/app/prediction/AppTargetEvent; 386
+Landroid/app/prediction/AppTarget; 388
+Landroid/content/res/Resources$NotFoundException; 389
+Landroid/icu/text/Collator; 390
+Landroid/widget/TextView$SavedState; 391
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.4:Ljava/util/WeakHashMap$Entry; 393
+Lcom/android/internal/logging/AndroidHandler; 395
+Landroid/view/VelocityTracker;.sPool:Landroid/util/Pools$SynchronizedPool; 397
+Landroid/os/StrictMode$OnThreadViolationListener; 397
+Landroid/view/VelocityTracker;.sPool:Landroid/util/Pools$SynchronizedPool;.mPool:[Ljava/lang/Object; 397
+Landroid/content/Context;.ACCOUNT_SERVICE:Ljava/lang/String; 397
+Landroid/service/trust/TrustAgentService;.EXTRA_TOKEN:Ljava/lang/String; 397
+Ljavax/sip/header/AcceptEncodingHeader;.NAME:Ljava/lang/String; 397
+Landroid/widget/RadioGroup$OnCheckedChangeListener; 398
+Lcom/android/internal/widget/DialogTitle; 399
+Lcom/android/internal/widget/ButtonBarLayout; 399
+Lcom/android/internal/widget/AlertDialogLayout; 399
+Landroid/icu/text/DecimalFormatSymbols;.DEF_DIGIT_STRINGS_ARRAY:[Ljava/lang/String;.1:Ljava/lang/String; 401
+Landroid/widget/Editor$TextRenderNode; 402
+Landroid/view/inputmethod/DeleteGesture; 403
+Landroid/text/method/MetaKeyKeyListener;.ALT:Ljava/lang/Object; 403
+Landroid/view/inputmethod/SelectRangeGesture; 403
+Landroid/text/method/MetaKeyKeyListener;.CAP:Ljava/lang/Object; 403
+Landroid/view/inputmethod/DeleteRangeGesture; 403
+Landroid/text/method/MetaKeyKeyListener;.SYM:Ljava/lang/Object; 403
+Landroid/text/method/MetaKeyKeyListener;.SELECTING:Ljava/lang/Object; 403
+Landroid/view/inputmethod/SelectGesture; 403
+Landroid/widget/TextView;.TEMP_POSITION:[F 404
+Landroid/view/inputmethod/BaseInputConnection;.COMPOSING:Ljava/lang/Object; 405
+Lcom/android/internal/infra/AndroidFuture; 406
+Landroid/accounts/Account;.sAccessedAccounts:Ljava/util/Set; 407
+Landroid/os/Message;.sPoolSync:Ljava/lang/Object; 408
+Landroid/database/sqlite/SQLiteCantOpenDatabaseException; 409
+Landroid/accounts/Account; 409
+Landroid/os/VibrationEffect; 411
+Landroid/content/ServiceConnection; 411
+Landroid/app/ActivityManager$MemoryInfo; 411
+Landroid/util/DisplayMetrics; 411
+Landroid/view/Display; 411
+Landroid/telephony/TelephonyCallback$DataConnectionStateListener; 412
+Landroid/hardware/display/IDisplayManager; 414
+Lcom/android/icu/util/regex/PatternNative; 414
+Landroid/view/WindowInsets; 414
+Landroid/app/ActivityTaskManager$2; 414
+Landroid/view/View$AttachInfo; 414
+Landroid/media/AudioManager$ServiceEventHandlerDelegate$1; 414
+Landroid/view/ViewRootImpl$6; 414
+Landroid/webkit/WebViewDelegate; 414
+Landroid/os/IInterface; 415
+Landroid/content/pm/IPackageManager; 417
+Landroid/app/IActivityManager; 418
+Landroid/text/style/ImageSpan; 419
+Landroid/widget/RelativeLayout; 422
+Landroid/graphics/drawable/StateListDrawable; 423
+Landroid/view/TextureView$SurfaceTextureListener; 427
+Landroid/graphics/SurfaceTexture; 428
+Landroid/media/audiopolicy/AudioProductStrategy; 429
+Landroid/media/PlayerBase; 430
+Landroid/os/FileUtils; 431
+Landroid/media/MediaDrm$OnEventListener; 435
+Landroid/graphics/drawable/TransitionDrawable; 436
+Lcom/android/internal/telephony/WspTypeDecoder;.WELL_KNOWN_PARAMETERS:Ljava/util/HashMap;.table:[Ljava/util/HashMap$Node;.25:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 437
+Lcom/android/ims/rcs/uce/presence/pidfparser/omapres/Version;.ELEMENT_NAME:Ljava/lang/String; 442
+Landroid/view/Window$Callback; 442
+Landroid/provider/SyncStateContract$Columns;.DATA:Ljava/lang/String; 442
+Lcom/android/internal/util/Parcelling$Cache;.sCache:Landroid/util/ArrayMap;.mHashes:[I 444
+Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedString; 444
+Landroid/aconfig/nano/Aconfig$tracepoint; 444
+Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringArray; 444
+Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringSet; 444
+Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringValueMap; 444
+Lcom/android/internal/util/Parcelling$BuiltIn$ForInternedStringList; 444
+Lcom/android/internal/util/Parcelling$Cache;.sCache:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object; 444
+Landroid/app/ActivityTaskManager; 444
+Landroid/aconfig/nano/Aconfig$parsed_flag; 444
+Lcom/android/internal/util/Parcelling$Cache;.sCache:Landroid/util/ArrayMap; 444
+Landroid/app/servertransaction/TopResumedActivityChangeItem; 445
+Landroid/app/LoadedApk$ReceiverDispatcher$Args$$ExternalSyntheticLambda0; 446
+Landroid/app/LoadedApk$ServiceDispatcher$RunConnection; 447
+Landroid/view/Choreographer$FrameDisplayEventReceiver; 448
+Landroid/view/inputmethod/InputMethodManager$H; 448
+Landroid/graphics/HardwareRendererObserver$$ExternalSyntheticLambda0; 448
+Landroid/view/ViewRootImpl$ViewRootHandler; 449
+Landroid/view/Choreographer$FrameHandler; 450
+Landroid/view/View$$ExternalSyntheticLambda4; 451
+Landroid/app/IActivityTaskManager; 451
+Landroid/os/AsyncTask$InternalHandler; 452
+Landroid/app/job/JobServiceEngine$JobHandler; 452
+Landroid/app/servertransaction/PendingTransactionActions$StopInfo; 453
+Landroid/os/MessageQueue; 453
+Landroid/widget/PopupWindow$PopupDecorView; 453
+Landroid/view/WindowLeaked; 454
+Landroid/app/servertransaction/ClientTransaction; 455
+Landroid/content/res/Resources; 457
+Landroid/util/Pair; 458
+Landroid/widget/Switch; 460
+Landroid/view/ViewManager; 467
+Landroid/view/accessibility/AccessibilityEventSource; 467
+Landroid/view/KeyEvent$Callback; 467
+Landroid/view/ViewParent; 467
+Landroid/graphics/drawable/Drawable$Callback; 467
+Landroid/content/pm/SigningDetails; 468
+Landroid/content/pm/FeatureInfo; 468
+Landroid/content/pm/ProviderInfo; 468
+Landroid/content/pm/PermissionInfo; 468
+Landroid/content/pm/PackageItemInfo; 469
+Landroid/content/pm/PackageInfo; 470
+Landroid/app/IActivityManager$Stub$Proxy; 473
+Lcom/android/internal/os/PowerProfile;.sPowerItemMap:Ljava/util/HashMap; 474
+Lcom/android/internal/os/PowerProfile;.sPowerArrayMap:Ljava/util/HashMap; 474
+Lcom/android/internal/os/PowerProfile;.sModemPowerProfile:Lcom/android/internal/power/ModemPowerProfile;.mPowerConstants:Landroid/util/SparseDoubleArray;.mValues:Landroid/util/SparseLongArray; 474
+Landroid/widget/HorizontalScrollView; 475
+Landroid/view/ViewTreeObserver$OnWindowFocusChangeListener; 476
+Landroid/content/res/AssetManager$AssetInputStream; 477
+Landroid/os/Parcelable; 478
+Landroid/icu/util/Calendar;.WEEK_DATA_CACHE:Landroid/icu/util/Calendar$WeekDataCache;.map:Ljava/util/concurrent/ConcurrentHashMap; 480
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.10:Ljava/util/WeakHashMap$Entry; 482
+Landroid/view/InsetsAnimationThread; 483
+Lcom/android/internal/jank/InteractionJankMonitor$InstanceHolder; 484
+Lcom/android/internal/jank/InteractionJankMonitor; 484
+Landroid/view/View$OnSystemUiVisibilityChangeListener; 485
+Landroid/hardware/display/DisplayManager$DisplayListener; 486
+Landroid/view/View$OnApplyWindowInsetsListener; 486
+Landroid/view/Choreographer$FrameCallback; 487
+Landroid/os/Handler$Callback; 489
+Landroid/os/Build$VERSION; 490
+Landroid/view/View$OnLayoutChangeListener; 490
+Landroid/app/SharedPreferencesImpl$EditorImpl; 491
+Landroid/view/InputDevice; 492
+Landroid/preference/PreferenceManager; 492
+Landroid/os/Build; 493
+Landroid/app/ContextImpl$ApplicationContentResolver; 496
+Landroid/provider/Settings$Secure; 496
+Landroid/view/TextureView; 497
+Landroid/os/strictmode/NetworkViolation; 498
+Landroid/graphics/drawable/AnimatedVectorDrawable; 499
+Landroid/icu/util/MeasureUnit$Complexity;.MIXED:Landroid/icu/util/MeasureUnit$Complexity;.name:Ljava/lang/String; 500
+Landroid/media/MediaDrm; 500
+Lcom/android/internal/app/procstats/DumpUtils;.STATE_NAMES_CSV:[Ljava/lang/String;.12:Ljava/lang/String; 500
+Landroid/provider/DocumentsContract;.DOWNLOADS_PROVIDER_AUTHORITY:Ljava/lang/String; 500
+Landroid/annotation/SystemApi; 500
+Landroid/icu/text/MessagePattern;.argTypes:[Landroid/icu/text/MessagePattern$ArgType;.0:Landroid/icu/text/MessagePattern$ArgType;.name:Ljava/lang/String; 500
+Landroid/webkit/WebViewFactory;.sProviderLock:Ljava/lang/Object; 505
+Landroid/app/ActivityThread$H; 506
+Landroid/view/AttachedSurfaceControl$OnBufferTransformHintChangedListener; 508
+Landroid/widget/ViewFlipper; 517
+Landroid/app/IActivityTaskManager$Stub$Proxy; 519
+Landroid/app/ActivityThread$ProviderRefCount; 519
+Landroid/view/ViewRootImpl$W; 519
+Lcom/android/internal/telephony/ITelephony; 519
+Lcom/android/internal/os/PowerProfile; 521
+Landroid/view/View$VisibilityChangeForAutofillHandler; 521
+Landroid/view/View$ScrollabilityCache; 521
+Landroid/app/INotificationManager; 521
+Landroid/graphics/drawable/LevelListDrawable; 521
+Landroid/app/SharedPreferencesImpl$EditorImpl$$ExternalSyntheticLambda0; 522
+Landroid/window/SplashScreen; 526
+Landroid/media/AudioManager$OnAudioFocusChangeListener; 528
+Landroid/app/Application; 529
+Landroid/content/ContextWrapper; 530
+Landroid/view/SurfaceView; 531
+Landroid/hardware/camera2/CameraCharacteristics;.FLASH_INFO_AVAILABLE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 532
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_TARGET_FPS_RANGE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 533
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AWB_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 533
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_ZOOM_RATIO:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 533
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 533
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_EXPOSURE_COMPENSATION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 533
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 533
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AF_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 533
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_ENABLE_ZSL:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 533
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_TEST_PATTERN_DATA:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_REGIONS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.JPEG_QUALITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.STATISTICS_LENS_SHADING_MAP_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.LENS_FOCUS_DISTANCE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.REPROCESS_EFFECTIVE_EXPOSURE_FACTOR:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_TEST_PATTERN_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.LENS_APERTURE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.STATISTICS_HOT_PIXEL_MAP_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AF_REGIONS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.REQUEST_AVAILABLE_SESSION_KEYS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_REFERENCE_ILLUMINANT1:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AWB_LOCK:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.EFV_STABILIZATION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.LENS_OPTICAL_STABILIZATION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.LENS_FILTER_DENSITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AWB_REGIONS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.EFV_PADDING_ZOOM_FACTOR:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.BLACK_LEVEL_LOCK:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.STATISTICS_FACE_DETECT_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.LOGICAL_MULTI_CAMERA_PHYSICAL_IDS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.JPEG_THUMBNAIL_SIZE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.SCALER_ROTATE_AND_CROP:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_COLOR_FILTER_ARRANGEMENT:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_OPTICAL_BLACK_REGIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.FLASH_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AF_TRIGGER:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.EFV_MAX_PADDING_ZOOM_FACTOR:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_PIXEL_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_WHITE_LEVEL:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.DISTORTION_CORRECTION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_CAPTURE_INTENT:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.EFV_AUTO_ZOOM:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_CALIBRATION_TRANSFORM1:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_ABERRATION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_COLOR_TRANSFORM1:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.TONEMAP_GAMMA:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.NOISE_REDUCTION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.SCALER_CROP_REGION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.TONEMAP_PRESET_CURVE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_EXPOSURE_TIME_RANGE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_POST_RAW_SENSITIVITY_BOOST:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.STATISTICS_OIS_DATA_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_FRAME_DURATION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.HOT_PIXEL_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_EXTENDED_SCENE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.REQUEST_AVAILABLE_REQUEST_KEYS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_GAINS:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_COLOR_TRANSFORM2:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_CALIBRATION_TRANSFORM2:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_LOCK:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.JPEG_THUMBNAIL_QUALITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_PRECAPTURE_TRIGGER:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_SENSITIVITY:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_EFFECT_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+[Landroid/hardware/camera2/params/MeteringRectangle; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AE_ANTIBANDING_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_AUTOFRAMING:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.EXTENSION_STRENGTH:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_SCENE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_SETTINGS_OVERRIDE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.EFV_ROTATE_VIEWPORT:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.FLASH_STRENGTH_LEVEL:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_REFERENCE_ILLUMINANT2:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_PIXEL_ARRAY_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.CONTROL_VIDEO_STABILIZATION_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.LENS_FOCAL_LENGTH:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.JPEG_ORIENTATION:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.EFV_TRANSLATE_VIEWPORT:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.SENSOR_EXPOSURE_TIME:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.TONEMAP_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.COLOR_CORRECTION_TRANSFORM:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.SHADING_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CaptureRequest;.EDGE_MODE:Landroid/hardware/camera2/CaptureRequest$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 534
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_PHYSICAL_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 535
+Landroid/util/Log; 536
+Landroid/accounts/AccountManager$20; 537
+Landroid/accounts/OnAccountsUpdateListener; 538
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.7:Ljava/util/WeakHashMap$Entry; 541
+Landroid/os/FileObserver; 544
+Landroid/widget/Space; 546
+Landroid/content/pm/ApplicationInfo; 547
+Landroid/graphics/ColorMatrix;.dexCache:Ljava/lang/Object; 548
+Landroid/text/style/CharacterStyle; 549
+Landroid/text/style/AlignmentSpan; 550
+Landroid/text/TextWatcher; 551
+Landroid/graphics/Bitmap;.sAllBitmaps:Ljava/util/WeakHashMap;.queue:Ljava/lang/ref/ReferenceQueue; 553
+Landroid/view/ViewRootImpl$$ExternalSyntheticLambda11; 554
+Landroid/app/Fragment;.sClassMap:Landroid/util/ArrayMap; 555
+Landroid/os/Bundle; 556
+Landroid/app/ActivityTaskManager;.sInstance:Landroid/util/Singleton; 557
+Landroid/content/pm/ShortcutInfo; 564
+Landroid/graphics/drawable/Icon; 565
+Landroid/os/PersistableBundle; 566
+Landroid/content/LocusId; 576
+Landroid/view/contentcapture/ContentCaptureContext; 576
+Landroid/telephony/TelephonyCallback$DisplayInfoListener; 577
+Landroid/app/Notification$Builder; 583
+Landroid/hardware/usb/UsbManager;.FUNCTION_NAME_TO_CODE:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.13:Ljava/util/HashMap$Node;.next:Ljava/util/HashMap$Node;.next:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 583
+Landroid/telephony/ims/ImsService;.CAPABILITIES_LOG_MAP:Ljava/util/Map;.table:[Ljava/lang/Object;.8:Ljava/lang/Long; 583
+Landroid/app/Notification; 584
+Landroid/app/RemoteAction; 585
+Landroid/graphics/Insets; 590
+Landroid/graphics/Rect; 591
+Lcom/android/internal/os/BackgroundThread; 592
+Landroid/widget/ViewSwitcher; 602
+Landroid/graphics/Color;.sColorNameMap:Ljava/util/HashMap;.table:[Ljava/util/HashMap$Node;.3:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 603
+Lcom/android/ims/rcs/uce/presence/pidfparser/pidf/Basic;.OPEN:Ljava/lang/String; 603
+Lcom/android/internal/os/BinderCallsStats$SettingsObserver;.SETTINGS_ENABLED_KEY:Ljava/lang/String; 603
+Landroid/icu/text/DecimalFormatSymbols;.DEF_DIGIT_STRINGS_ARRAY:[Ljava/lang/String;.3:Ljava/lang/String; 603
+Landroid/os/BatteryConsumer;.sPowerComponentNames:[Ljava/lang/String;.13:Ljava/lang/String; 603
+Landroid/os/IncidentManager;.URI_SCHEME:Ljava/lang/String; 603
+Landroid/os/AsyncTask$4; 603
+Landroid/text/Html$HtmlParser;.schema:Lorg/ccil/cowan/tagsoup/HTMLSchema;.theEntities:Ljava/util/HashMap;.table:[Ljava/util/HashMap$Node;.3233:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 603
+Landroid/provider/DocumentsContract;.PATH_SEARCH:Ljava/lang/String; 603
+Landroid/icu/impl/LocaleIDs;._languages:[Ljava/lang/String;.437:Ljava/lang/String; 603
+Landroid/icu/impl/units/UnitsData$Constants;.DEFAULT_USAGE:Ljava/lang/String; 604
+Lcom/android/internal/telephony/IccProvider;.ADDRESS_BOOK_COLUMN_NAMES:[Ljava/lang/String;.0:Ljava/lang/String; 604
+Landroid/text/method/DialerKeyListener; 605
+Landroid/icu/text/DecimalFormatSymbols;.DEF_DIGIT_STRINGS_ARRAY:[Ljava/lang/String;.0:Ljava/lang/String; 605
+Lcom/android/ims/rcs/uce/presence/pidfparser/pidf/Timestamp;.ELEMENT_NAME:Ljava/lang/String; 605
+Lcom/android/ims/rcs/uce/presence/pidfparser/pidf/Status;.ELEMENT_NAME:Ljava/lang/String; 605
+Landroid/os/BatteryManager;.EXTRA_SEQUENCE:Ljava/lang/String; 605
+Landroid/icu/text/MessageFormat;.typeList:[Ljava/lang/String;.5:Ljava/lang/String; 605
+Landroid/provider/Telephony$ThreadsColumns;.ERROR:Ljava/lang/String; 605
+Lcom/android/internal/os/RailStats;.WIFI_SUBSYSTEM:Ljava/lang/String; 605
+Landroid/app/NotificationChannel;.TAG_CHANNEL:Ljava/lang/String; 605
+Landroid/app/NotificationChannel;.EDIT_LAUNCHER:Ljava/lang/String; 605
+Lcom/android/ims/ImsUt;.KEY_ACTION:Ljava/lang/String; 605
+Landroid/view/textclassifier/TextClassifier;.TYPE_URL:Ljava/lang/String; 605
+Landroid/provider/Telephony$BaseMmsColumns;.START:Ljava/lang/String; 605
+Landroid/icu/impl/ValidIdentifiers$Datatype;.region:Landroid/icu/impl/ValidIdentifiers$Datatype;.name:Ljava/lang/String; 605
+Landroid/icu/impl/ZoneMeta;.REGION_CACHE:Landroid/icu/impl/ICUCache; 608
+Landroid/widget/TextView;.TEMP_RECTF:Landroid/graphics/RectF; 609
+Landroid/app/Activity; 611
+Landroid/text/method/LinkMovementMethod; 614
+Landroid/net/Uri; 615
+Landroid/app/PendingIntent; 617
+Landroid/security/net/config/UserCertificateSource$NoPreloadHolder; 618
+Landroid/net/Uri$PathPart;.EMPTY:Landroid/net/Uri$PathPart; 619
+Landroid/content/Intent; 620
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.197:Landroid/os/PersistableBundle; 622
+Landroid/graphics/HardwareRenderer; 624
+Landroid/icu/util/TimeZone; 625
+Landroid/telephony/TelephonyRegistryManager; 627
+Landroid/telecom/TelecomManager; 628
+Landroid/telephony/TelephonyCallback$ServiceStateListener; 629
+Landroid/telephony/TelephonyCallback$RadioPowerStateListener; 630
+Landroid/widget/ActionMenuView; 631
+Landroid/widget/ActionMenuPresenter$OverflowMenuButton; 631
+Landroid/widget/Toolbar; 631
+Lcom/android/internal/widget/ActionBarContainer; 632
+Lcom/android/internal/widget/ActionBarContainer$ActionBarBackgroundDrawable; 632
+Lcom/android/internal/widget/ActionBarContextView; 632
+Lcom/android/internal/widget/ActionBarOverlayLayout; 632
+Landroid/graphics/drawable/AdaptiveIconDrawable; 633
+Landroid/widget/ImageButton; 634
+Landroid/widget/Button; 635
+Landroid/view/AbsSavedState$1; 636
+Landroid/app/FragmentManagerState; 637
+Landroid/view/View$BaseSavedState; 638
+Landroid/graphics/drawable/ShapeDrawable; 639
+Lcom/android/internal/telephony/WspTypeDecoder;.WELL_KNOWN_MIME_TYPES:Ljava/util/HashMap;.table:[Ljava/util/HashMap$Node;.54:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 640
+Lcom/android/internal/telephony/WspTypeDecoder;.WELL_KNOWN_MIME_TYPES:Ljava/util/HashMap;.table:[Ljava/util/HashMap$Node;.33:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 640
+Landroid/widget/MultiAutoCompleteTextView; 642
+Landroid/speech/RecognitionListener; 642
+Landroid/widget/ToggleButton; 643
+Landroid/widget/AutoCompleteTextView; 644
+Landroid/widget/RadioButton; 645
+Landroid/widget/CheckBox; 646
+Landroid/view/View$OnGenericMotionListener; 647
+Landroid/os/UserHandle; 648
+Landroid/app/servertransaction/ResumeActivityItem; 655
+Landroid/app/servertransaction/ActivityRelaunchItem; 655
+Landroid/app/servertransaction/ObjectPool;.sPoolMap:Ljava/util/Map; 655
+Landroid/text/style/URLSpan; 656
+Landroid/icu/util/ULocale$AvailableType;.DEFAULT:Landroid/icu/util/ULocale$AvailableType;.name:Ljava/lang/String; 656
+Landroid/icu/util/CodePointMap$RangeOption;.NORMAL:Landroid/icu/util/CodePointMap$RangeOption;.name:Ljava/lang/String; 658
+Landroid/security/keystore2/AndroidKeyStoreProvider; 676
+Landroid/security/keystore2/KeyStoreCryptoOperationUtils; 677
+Landroid/view/accessibility/AccessibilityManager$TouchExplorationStateChangeListener; 678
+Landroid/view/View;.sNextGeneratedId:Ljava/util/concurrent/atomic/AtomicInteger; 679
+Landroid/icu/impl/number/range/StandardPluralRanges; 680
+Landroid/icu/impl/PluralRulesLoader;.loader:Landroid/icu/impl/PluralRulesLoader; 680
+Landroid/icu/impl/PluralRulesLoader;.loader:Landroid/icu/impl/PluralRulesLoader;.pluralRulesCache:Ljava/util/Map; 680
+Landroid/icu/text/PluralRules$Operand; 680
+Landroid/icu/impl/StandardPlural; 681
+Landroid/webkit/JavascriptInterface; 682
+Landroid/content/res/AssetManager; 684
+Ljavax/sip/header/ContentEncodingHeader;.NAME:Ljava/lang/String; 685
+Landroid/view/View$OnClickListener; 685
+Landroid/hardware/usb/UsbManager;.FUNCTION_NAME_TO_CODE:Ljava/util/Map;.table:[Ljava/util/HashMap$Node;.13:Ljava/util/HashMap$Node;.value:Ljava/lang/Object; 685
+Landroid/widget/CompoundButton; 685
+Landroid/view/accessibility/AccessibilityManager;.sInstanceSync:Ljava/lang/Object; 686
+Landroid/webkit/CookieManager; 687
+Landroid/icu/text/NFRule;.ZERO:Ljava/lang/Long; 689
+Landroid/app/AppOpsManager$OnOpActiveChangedListener; 691
+Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mMap:Landroid/util/ArrayMap; 692
+Landroid/os/RemoteException; 693
+Landroid/content/pm/PackageManager$OnChecksumsReadyListener; 694
+Landroid/content/pm/Checksum$Type; 695
+Landroid/view/InputEvent;.mNextSeq:Ljava/util/concurrent/atomic/AtomicInteger; 696
+Landroid/view/MotionEvent; 697
+Landroid/widget/ScrollView; 698
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.10:Ljava/util/WeakHashMap$Entry;.referent:Ljava/lang/Object;.mSkips:[J 702
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.queue:Ljava/lang/ref/ReferenceQueue; 703
+Landroid/widget/ProgressBar; 704
+Landroid/animation/LayoutTransition; 706
+Landroid/animation/PropertyValuesHolder$IntPropertyValuesHolder;.sJNISetterPropertyMap:Ljava/util/HashMap; 707
+Lorg/apache/http/params/HttpParams; 711
+Landroid/app/NotificationChannelGroup; 712
+Landroid/content/pm/ParceledListSlice; 712
+Landroid/os/vibrator/StepSegment; 713
+Lcom/android/internal/util/LatencyTracker$SLatencyTrackerHolder; 714
+Lcom/android/internal/util/LatencyTracker; 714
+Landroid/app/Application$ActivityLifecycleCallbacks; 715
+Landroid/os/Messenger; 716
+Landroid/hardware/camera2/CameraCharacteristics;.CONTROL_AE_AVAILABLE_MODES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 720
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_INFO_ACTIVE_ARRAY_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 720
+Landroid/hardware/camera2/CameraCharacteristics;.REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 720
+Landroid/hardware/camera2/CameraCharacteristics;.INFO_SESSION_CONFIGURATION_QUERY_VERSION:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 720
+Landroid/hardware/camera2/CameraCharacteristics;.LENS_INFO_SHADING_MAP_SIZE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 720
+Landroid/hardware/camera2/CaptureResult;.SENSOR_TIMESTAMP:Landroid/hardware/camera2/CaptureResult$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 720
+Landroid/hardware/camera2/CameraCharacteristics;.CONTROL_AWB_AVAILABLE_MODES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 720
+Landroid/hardware/camera2/CameraDevice$StateCallback; 720
+Landroid/hardware/camera2/impl/CameraMetadataNative; 720
+Landroid/hardware/camera2/CameraCharacteristics;.SCALER_AVAILABLE_STREAM_USE_CASES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 720
+Landroid/hardware/camera2/CameraCharacteristics;.CONTROL_ZOOM_RATIO_RANGE:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 720
+Landroid/util/Size; 720
+Landroid/hardware/camera2/CameraCaptureSession$StateCallback; 720
+Landroid/hardware/camera2/CameraCharacteristics;.CONTROL_AF_AVAILABLE_MODES:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 720
+Landroid/hardware/camera2/CameraCharacteristics;.REQUEST_PARTIAL_RESULT_COUNT:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 720
+Landroid/hardware/camera2/CameraCaptureSession$CaptureCallback; 720
+Landroid/util/Range; 720
+Landroid/widget/ListView; 721
+Landroid/widget/AbsListView; 721
+Landroid/transition/Explode; 723
+Landroid/text/HtmlToSpannedConverter$Font; 724
+Landroid/text/Html$TagHandler; 725
+Lcom/android/internal/telephony/cdnr/CarrierDisplayNameResolver;.EF_SOURCE_PRIORITY:Ljava/util/List;.a:[Ljava/lang/Object;.2:Ljava/lang/Integer; 725
+Landroid/telephony/ims/feature/MmTelFeature$1; 726
+Landroid/telephony/ims/stub/ImsConfigImplBase$ImsConfigStub; 726
+Landroid/telephony/ims/ImsUtListener; 726
+Landroid/telephony/ims/stub/ImsRegistrationImplBase$1; 726
+Lcom/android/ims/ImsManager;.IMS_MANAGER_INSTANCES:Landroid/util/SparseArray;.mKeys:[I 727
+Lcom/android/ims/ImsManager;.IMS_MANAGER_INSTANCES:Landroid/util/SparseArray; 728
+Lcom/android/ims/ImsManager;.IMS_MANAGER_INSTANCES:Landroid/util/SparseArray;.mValues:[Ljava/lang/Object; 728
+Landroid/telephony/ims/aidl/IImsConfig$Stub$Proxy; 729
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SipMessageResponse; 730
+Landroid/timezone/TimeZoneFinder; 730
+Landroid/telephony/TelephonyRegistryManager$3; 730
+Lcom/android/internal/telephony/DeviceStateMonitor; 730
+Lcom/android/internal/telephony/imsphone/ImsPhone; 730
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker; 730
+Lcom/android/internal/telephony/cat/CatService; 730
+Landroid/net/NetworkPolicyManager$SubscriptionCallbackProxy; 730
+Landroid/telephony/ModemActivityInfo; 730
+Lcom/android/internal/telephony/InboundSmsHandler$NewMessageNotificationActionReceiver; 730
+Landroid/icu/impl/ZoneMeta;.SYSTEM_ZONE_CACHE:Landroid/icu/impl/ZoneMeta$SystemTimeZoneCache;.map:Ljava/util/concurrent/ConcurrentHashMap; 730
+Lcom/android/internal/telephony/TelephonyDevController; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$GbaEvent; 730
+Lcom/android/internal/telephony/RadioInterfaceCapabilityController; 730
+Lcom/android/internal/telephony/SmsBroadcastUndelivered; 730
+Landroid/telephony/data/ApnSetting;.APN_TYPE_INT_MAP:Ljava/util/Map; 730
+Lcom/android/internal/telephony/SmsStorageMonitor$1; 730
+Lcom/android/internal/telephony/CellBroadcastServiceManager; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$CellularDataServiceSwitch; 730
+Lcom/android/internal/telephony/StateMachine$SmHandler; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$CarrierRoamingSatelliteControllerStats; 730
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.673:[Ljava/lang/String; 730
+Lcom/android/internal/telephony/NetworkTypeController$1; 730
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mDisplayInfoRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 730
+Lcom/android/internal/telephony/CarrierActionAgent; 730
+Lcom/android/internal/telephony/uicc/UiccCarrierPrivilegeRules; 730
+Lcom/android/internal/telephony/MultiSimSettingController; 730
+Lcom/android/internal/telephony/GsmCdmaCallTracker; 730
+Lcom/android/internal/telephony/gsm/GsmInboundSmsHandler$GsmCbTestBroadcastReceiver; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteController; 730
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1289:[Ljava/lang/String; 730
+Lcom/android/internal/telephony/IntentBroadcaster$1; 730
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.483:[Ljava/lang/String; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$PresenceNotifyEvent; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteSosMessageRecommender; 730
+Landroid/telephony/CellSignalStrengthWcdma; 730
+Lcom/android/ims/rcs/uce/eab/EabProvider; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$CarrierRoamingSatelliteSession; 730
+Lcom/android/internal/telephony/TelephonyComponentFactory; 730
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mRingingCalls:Ljava/util/ArrayList; 730
+Lcom/android/internal/telephony/ims/ImsResolver$2; 730
+Lcom/android/internal/telephony/emergency/EmergencyNumberTracker; 730
+Landroid/timezone/TelephonyLookup; 730
+Lcom/android/internal/telephony/euicc/EuiccConnector$UnavailableState; 730
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.363:[Ljava/lang/String; 730
+Lcom/android/internal/telephony/ProxyController; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteOutgoingDatagram; 730
+Lcom/android/i18n/timezone/TimeZoneFinder; 730
+Lcom/android/internal/telephony/SimActivationTracker; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteProvision; 730
+Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler$CdmaScpTestBroadcastReceiver; 730
+Lcom/android/internal/telephony/ServiceStateTracker; 730
+Lcom/android/internal/telephony/euicc/EuiccConnector$AvailableState; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$RcsClientProvisioningStats; 730
+Lcom/android/internal/telephony/SmsApplication; 730
+Lcom/android/internal/telephony/TelephonyDevController;.mModems:Ljava/util/ArrayList; 730
+Lcom/android/internal/telephony/SimActivationTracker$1; 730
+Lcom/android/internal/telephony/emergency/EmergencyNumberTracker$1; 730
+Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$NetworkRequestsV2; 730
+Lcom/android/internal/telephony/AppSmsManager; 730
+Landroid/telephony/ims/ProvisioningManager$Callback$CallbackBinder; 730
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.789:[Ljava/lang/String; 730
+Lcom/android/i18n/timezone/TelephonyLookup; 730
+Lcom/android/internal/telephony/CarrierServiceBindHelper$CarrierServicePackageMonitor; 730
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.549:[Ljava/lang/String; 730
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mInCallVoicePrivacyOffRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 730
+Lcom/android/internal/telephony/cdma/CdmaInboundSmsHandler$CdmaCbTestBroadcastReceiver; 730
+Lcom/android/internal/telephony/IntentBroadcaster; 730
+Landroid/telephony/ims/RegistrationManager$RegistrationCallback$RegistrationBinder; 730
+Lcom/android/internal/telephony/GsmCdmaCallTracker$1; 730
+Lcom/android/internal/telephony/uicc/UiccProfile$2; 730
+Landroid/telephony/ims/ImsMmTelManager$CapabilityCallback$CapabilityBinder; 730
+Landroid/telephony/CellSignalStrengthGsm; 730
+Landroid/os/Handler$MessengerImpl; 730
+Lcom/android/internal/telephony/DisplayInfoController; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationStats; 730
+Lcom/android/internal/telephony/DeviceStateMonitor$3; 730
+Lcom/android/internal/telephony/RIL;.sRilTimeHistograms:Landroid/util/SparseArray; 730
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.469:[Ljava/lang/String; 730
+Lcom/android/internal/telephony/PhoneConfigurationManager; 730
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.349:[Ljava/lang/String; 730
+Lcom/android/internal/telephony/TelephonyDevController;.mSims:Ljava/util/ArrayList; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$IncomingSms; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$UnmeteredNetworks; 730
+Lcom/android/internal/telephony/euicc/EuiccCardController; 730
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mMmiCompleteRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$DataNetworkValidation; 730
+Lcom/android/internal/telephony/euicc/EuiccConnector$BindingState; 730
+Lcom/android/internal/telephony/uicc/UiccPkcs15$Pkcs15Selector; 730
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.23:[Ljava/lang/String; 730
+Lcom/android/internal/telephony/SomeArgs; 730
+Lcom/android/internal/telephony/SmsStorageMonitor; 730
+Lcom/android/internal/telephony/SmsApplication$SmsPackageMonitor; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$CarrierIdMismatch; 730
+Lcom/android/phone/ecc/nano/ProtobufEccData$EccInfo; 730
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mSuppServiceFailedRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 730
+Lcom/android/internal/telephony/nano/TelephonyProto$TelephonyCallSession$Event$RilCall; 730
+Lcom/android/internal/telephony/metrics/TelephonyMetrics; 730
+Lcom/android/internal/telephony/ims/ImsResolver$3; 730
+Lcom/android/internal/telephony/uicc/UiccProfile; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteAccessController; 730
+Lcom/android/internal/telephony/NitzStateMachine; 730
+Lcom/android/internal/telephony/euicc/EuiccConnector$DisconnectedState; 730
+Lcom/android/internal/telephony/uicc/UiccStateChangedLauncher; 730
+Lcom/android/ims/ImsManager;.IMS_STATS_CALLBACKS:Landroid/util/SparseArray; 730
+Lcom/android/internal/telephony/euicc/EuiccConnector$ConnectedState$15; 730
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.833:[Ljava/lang/String; 730
+Lcom/android/internal/telephony/SmsUsageMonitor; 730
+Lcom/android/internal/telephony/euicc/EuiccCardController$SimSlotStatusChangedBroadcastReceiver; 730
+Lcom/android/internal/telephony/ims/ImsServiceController$1; 730
+Lcom/android/internal/telephony/satellite/SatelliteModemInterface; 730
+Lcom/android/internal/telephony/CarrierResolver$2; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$NetworkRequests; 730
+Lcom/android/internal/telephony/MccTable; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SipDelegateStats; 730
+Lcom/android/ims/ImsManager;.IMS_STATS_CALLBACKS:Landroid/util/SparseArray;.mValues:[Ljava/lang/Object; 730
+Lcom/android/ims/FeatureConnector$1; 730
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1443:[Ljava/lang/String; 730
+Lcom/android/internal/telephony/ims/ImsResolver$1; 730
+Lcom/android/internal/telephony/euicc/EuiccConnector$ConnectedState; 730
+Lcom/android/internal/telephony/security/NullCipherNotifier; 730
+Lcom/android/internal/telephony/SMSDispatcher$1; 730
+Lcom/android/phone/ecc/nano/ProtobufEccData$CountryInfo; 730
+Lcom/android/internal/telephony/LocaleTracker$1; 730
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mTtyModeReceivedRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$VoiceCallRatUsage; 730
+Landroid/os/AsyncResult; 730
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mDisconnectRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteConfigUpdater; 730
+Lcom/android/internal/telephony/ims/ImsResolver; 730
+Lcom/android/internal/telephony/ServiceStateTracker$1; 730
+Lcom/android/internal/telephony/PhoneFactory; 730
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager; 730
+Landroid/telephony/CellSignalStrengthTdscdma; 730
+Landroid/telephony/emergency/EmergencyNumber; 730
+Lcom/android/internal/telephony/GsmCdmaPhone; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SipTransportSession; 730
+Landroid/app/timezonedetector/TimeZoneDetector; 730
+Landroid/telephony/ims/aidl/IImsServiceController$Stub$Proxy; 730
+Lcom/android/internal/telephony/TelephonyTester$1; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$EmergencyNumbersInfo; 730
+Lcom/android/internal/telephony/nano/TelephonyProto$TelephonyServiceState$NetworkRegistrationInfo; 730
+Lcom/android/internal/telephony/CarrierServiceBindHelper$1; 730
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mHandlerMap:Ljava/util/HashMap; 730
+Lcom/android/internal/telephony/IccPhoneBookInterfaceManager; 730
+Lcom/android/internal/telephony/CarrierPrivilegesTracker$1; 730
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1173:[Ljava/lang/String; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$DataCallSession; 730
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mForegroundCalls:Ljava/util/ArrayList; 730
+Landroid/telephony/TelephonyLocalConnection; 730
+Lcom/android/internal/telephony/euicc/EuiccConnector$1; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsDedicatedBearerListenerEvent; 730
+Landroid/telephony/ModemInfo; 730
+Lcom/android/internal/telephony/CommandException$Error;.INVALID_SIM_STATE:Lcom/android/internal/telephony/CommandException$Error; 730
+Lcom/android/internal/telephony/CommandException; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$VoiceCallSession; 730
+Lcom/android/internal/telephony/imsphone/ImsExternalCallTracker; 730
+Lcom/android/internal/telephony/euicc/EuiccController; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteSession; 730
+Landroid/telephony/CellSignalStrengthLte; 730
+Lcom/android/internal/telephony/CarrierActionAgent$1; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$OutgoingShortCodeSms; 730
+Lcom/android/internal/telephony/satellite/PointingAppController; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteIncomingDatagram; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationFeatureTagStats; 730
+Lcom/android/internal/telephony/imsphone/ImsPhoneCallTracker$2; 730
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.33:[Ljava/lang/String; 730
+Lcom/android/internal/telephony/nano/TelephonyProto$RilDataCall; 730
+Lcom/android/internal/telephony/RILRequest; 730
+Lcom/android/internal/telephony/euicc/EuiccConnector$ConnectedState$5; 730
+Landroid/telephony/BarringInfo$BarringServiceInfo; 730
+Lcom/android/internal/telephony/IWapPushManager; 730
+Lcom/android/internal/telephony/SmsDispatchersController; 730
+Lcom/android/internal/telephony/uicc/UiccController; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$CellularServiceState; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$OutgoingSms; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SatelliteEntitlement; 730
+Lcom/android/internal/telephony/util/NotificationChannelController$1; 730
+Lcom/android/ims/ImsManager;.IMS_STATS_CALLBACKS:Landroid/util/SparseArray;.mKeys:[I 730
+Lcom/android/internal/telephony/IccSmsInterfaceManager; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$SipTransportFeatureTagStats; 730
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mInCallVoicePrivacyOnRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 730
+Lcom/android/internal/telephony/uicc/UiccProfile$4; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$UceEventStats; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsDedicatedBearerEvent; 730
+Lcom/android/internal/telephony/RadioConfig; 730
+Lcom/android/internal/telephony/PackageChangeReceiver; 730
+Lcom/android/internal/telephony/PhoneSubInfoController; 730
+Lcom/android/internal/telephony/euicc/EuiccConnector$EuiccPackageMonitor; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationTermination; 730
+Lcom/android/internal/telephony/uicc/PinStorage$1; 730
+Lcom/android/internal/telephony/SmsBroadcastUndelivered$1; 730
+Lcom/android/internal/telephony/cdma/CdmaSubscriptionSourceManager; 730
+Lcom/android/internal/telephony/CarrierKeyDownloadManager$3; 730
+Lcom/android/internal/telephony/NetworkTypeController$DefaultState; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$RcsAcsProvisioningStats; 730
+Landroid/net/TelephonyNetworkSpecifier; 730
+Landroid/telephony/CarrierConfigManager;.sDefaults:Landroid/os/PersistableBundle;.mMap:Landroid/util/ArrayMap;.mArray:[Ljava/lang/Object;.1459:[Ljava/lang/String; 730
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mSignalInfoRegistrants:Lcom/android/internal/telephony/RegistrantList;.registrants:Ljava/util/ArrayList; 730
+Lcom/android/internal/telephony/nano/PersistAtomsProto$ImsRegistrationServiceDescStats; 730
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mBackgroundCalls:Ljava/util/ArrayList; 730
+Lcom/android/internal/telephony/CallManager;.INSTANCE:Lcom/android/internal/telephony/CallManager;.mPhones:Ljava/util/ArrayList; 730
+Lcom/android/internal/telephony/LocaleTracker; 730
+Lcom/android/internal/telephony/RilWakelockInfo; 730
+Landroid/telephony/CellSignalStrengthNr; 730
+Landroid/telephony/CellSignalStrengthCdma; 730
+Landroid/telephony/NetworkService; 731
+Landroid/util/Log$TerribleFailure; 732
+Lcom/android/internal/os/RuntimeInit$KillApplicationHandler; 733
+Landroid/content/res/ResourcesKey; 734
+Landroid/app/ResourcesManager; 734
+Landroid/widget/HorizontalScrollView$SavedState; 736
+Landroid/widget/AbsSpinner$SavedState; 736
+Landroid/widget/Spinner$SavedState; 736
+Lcom/android/internal/transition/EpicenterTranslateClipReveal; 737
+Landroid/transition/TransitionInflater;.sConstructors:Landroid/util/ArrayMap; 737
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.15:Ljava/lang/String; 738
+Landroid/view/ThreadedRenderer;.OVERDRAW_PROPERTY_SHOW:Ljava/lang/String; 738
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.141:Ljava/lang/String; 738
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.35:Ljava/lang/String; 738
+Landroid/text/Html$ImageGetter; 738
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.80:Ljava/lang/String; 738
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.224:Ljava/lang/String; 738
+Landroid/webkit/ConsoleMessage$MessageLevel;.WARNING:Landroid/webkit/ConsoleMessage$MessageLevel; 738
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.118:Ljava/lang/String; 738
+Landroid/webkit/ConsoleMessage$MessageLevel;.LOG:Landroid/webkit/ConsoleMessage$MessageLevel; 738
+Landroid/webkit/ConsoleMessage$MessageLevel;.DEBUG:Landroid/webkit/ConsoleMessage$MessageLevel; 738
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.221:Ljava/lang/String; 738
+Landroid/icu/impl/LocaleIDs;._replacementCountries:[Ljava/lang/String;.9:Ljava/lang/String; 738
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.127:Ljava/lang/String; 738
+Landroid/window/ImeOnBackInvokedDispatcher;.RESULT_KEY_PRIORITY:Ljava/lang/String; 738
+Landroid/util/AndroidRuntimeException; 738
+Lcom/android/internal/app/procstats/DumpUtils;.STATE_TAGS:[Ljava/lang/String;.14:Ljava/lang/String; 738
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.6:Ljava/lang/String; 738
+Landroid/webkit/ConsoleMessage$MessageLevel;.TIP:Landroid/webkit/ConsoleMessage$MessageLevel; 738
+Landroid/webkit/ConsoleMessage$MessageLevel;.ERROR:Landroid/webkit/ConsoleMessage$MessageLevel; 738
+Landroid/opengl/GLSurfaceView; 738
+Landroid/icu/impl/LocaleIDs;._countries:[Ljava/lang/String;.237:Ljava/lang/String; 738
+Landroid/app/servertransaction/LaunchActivityItem; 739
+Landroid/app/backup/BackupManager; 750
+Landroid/content/pm/PackageManager$NameNotFoundException; 751
+Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mClassLoader:Ljava/lang/ClassLoader;.packages:Ljava/util/Map;.m:Ljava/util/Map;.table:[Ljava/util/HashMap$Node; 752
+Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mClassLoader:Ljava/lang/ClassLoader;.packages:Ljava/util/Map;.m:Ljava/util/Map; 752
+Landroid/view/textclassifier/TextLanguage;.EMPTY:Landroid/view/textclassifier/TextLanguage;.mBundle:Landroid/os/Bundle;.mClassLoader:Ljava/lang/ClassLoader; 752
+Landroid/icu/util/ULocale$AliasReplacer; 753
+Landroid/widget/MediaController$MediaPlayerControl; 755
+Landroid/graphics/Point; 759
+Landroid/content/ContentValues; 759
+Landroid/opengl/GLSurfaceView$Renderer; 760
+Landroid/opengl/GLSurfaceView;.sGLThreadManager:Landroid/opengl/GLSurfaceView$GLThreadManager; 761
+Landroid/text/StaticLayout; 762
+Landroid/animation/AnimationHandler$AnimationFrameCallbackProvider; 762
+Landroid/text/method/DigitsKeyListener;.sLocaleInstanceCache:Ljava/util/HashMap; 764
+Landroid/graphics/Path$Op; 765
+Landroid/text/method/QwertyKeyListener; 765
+Landroid/app/StackTrace; 765
+Landroid/icu/text/BreakIterator;.iterCache:[Landroid/icu/impl/CacheValue; 766
+Landroid/view/View$OnHoverListener; 767
+Landroid/content/res/ColorStateList; 767
+Landroid/security/IKeyChainService; 768
+Landroid/app/Notification$MessagingStyle; 769
+Landroid/content/ContentProviderClient; 773
+Landroid/os/UserHandle;.sExtraUserHandleCache:Landroid/util/SparseArray; 773
+Landroid/content/ContentProvider$PipeDataWriter; 774
+Landroid/os/strictmode/UnsafeIntentLaunchViolation; 774
+Landroid/content/AsyncQueryHandler; 776
+Landroid/app/Activity$$ExternalSyntheticLambda0; 777
+Landroid/widget/CheckedTextView; 777
+Landroid/graphics/PorterDuff$Mode;.SRC_IN:Landroid/graphics/PorterDuff$Mode; 778
+Landroid/graphics/drawable/InsetDrawable; 779
+Landroid/view/OrientationEventListener; 781
+Landroid/hardware/camera2/CameraCharacteristics;.INFO_SUPPORTED_HARDWARE_LEVEL:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 782
+Landroid/hardware/camera2/CameraCharacteristics;.SENSOR_ORIENTATION:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 783
+Landroid/hardware/camera2/CameraCharacteristics;.INFO_DEVICE_STATE_ORIENTATIONS:Landroid/hardware/camera2/CameraCharacteristics$Key;.mKey:Landroid/hardware/camera2/impl/CameraMetadataNative$Key; 783
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.9:Ljava/util/WeakHashMap$Entry; 785
+Landroid/media/MediaRouter$VolumeChangeReceiver; 787
+Landroid/media/MediaRouter$WifiDisplayStatusChangedReceiver; 787
+Landroid/media/MediaRouter; 788
+Landroid/hardware/SensorPrivacyManager; 789
+Landroid/os/storage/StorageManager; 790
+Landroid/telephony/SubscriptionManager; 791
+Landroid/view/textservice/TextServicesManager; 791
+Landroid/os/SystemConfigManager; 791
+Landroid/view/LayoutInflater; 791
+Landroid/hardware/input/InputManager; 791
+Landroid/credentials/CredentialManager; 791
+Landroid/permission/PermissionControllerManager; 791
+Landroid/net/NetworkPolicyManager; 791
+Landroid/security/attestationverification/AttestationVerificationManager; 791
+Landroid/app/contextualsearch/ContextualSearchManager; 791
+Landroid/app/wearable/WearableSensingManager; 791
+Landroid/app/people/PeopleManager; 791
+Landroid/net/wifi/sharedconnectivity/app/SharedConnectivityManager; 791
+Landroid/media/session/MediaSessionManager; 791
+Landroid/provider/E2eeContactKeysManager; 791
+Landroid/view/contentcapture/ContentCaptureManager; 791
+Landroid/app/contentsuggestions/ContentSuggestionsManager; 791
+Landroid/os/HardwarePropertiesManager; 791
+Landroid/app/admin/DevicePolicyManager; 791
+Landroid/view/translation/TranslationManager; 791
+Landroid/view/autofill/AutofillManager; 791
+Landroid/net/vcn/VcnManager; 791
+Landroid/service/persistentdata/PersistentDataBlockManager; 791
+Landroid/view/textclassifier/TextClassificationManager; 791
+Landroid/media/tv/tunerresourcemanager/TunerResourceManager; 791
+Landroid/os/RecoverySystem; 791
+Landroid/os/strictmode/Violation; 793
+Lcom/android/internal/telephony/uicc/asn1/Asn1Node;.EMPTY_NODE_LIST:Ljava/util/List; 795
+Landroid/os/strictmode/CredentialProtectedWhileLockedViolation; 796
+Landroid/net/metrics/DhcpClientEvent; 797
+Landroid/icu/impl/CharacterPropertiesImpl;.inclusions:[Landroid/icu/text/UnicodeSet; 798
+Landroid/content/AttributionSource; 800
+Landroid/database/sqlite/SQLiteException; 801
+Lcom/android/ims/ImsManager;.TRUE:Ljava/lang/String; 802
+Landroid/graphics/Matrix; 803
+Landroid/graphics/RectF; 803
+Landroid/os/Parcel$LazyValue; 803
+Landroid/telephony/TelephonyCallback$DataEnabledListener; 804
+Landroid/app/PropertyInvalidatedCache;.sCaches:Ljava/util/WeakHashMap;.table:[Ljava/util/WeakHashMap$Entry;.6:Ljava/util/WeakHashMap$Entry; 805
+Landroid/service/media/MediaBrowserService$ServiceState; 806
+Landroid/graphics/drawable/PictureDrawable; 806
+Landroid/content/pm/PackageManager; 812
+Landroid/window/IWindowContainerToken$Stub$Proxy; 813
+Landroid/app/UriGrantsManager;.IUriGrantsManagerSingleton:Landroid/util/Singleton; 814
+Landroid/provider/FontsContract;.sTypefaceCache:Landroid/util/LruCache;.map:Ljava/util/LinkedHashMap; 816
+Landroid/provider/FontsContract;.sTypefaceCache:Landroid/util/LruCache; 816
+Lcom/android/internal/telephony/WspTypeDecoder;.WELL_KNOWN_MIME_TYPES:Ljava/util/HashMap;.table:[Ljava/util/HashMap$Node;.81:Ljava/util/HashMap$Node;.key:Ljava/lang/Object; 817
+Landroid/app/Service; 818
+Landroid/app/ReceiverRestrictedContext; 819
+Landroid/util/proto/ProtoStream;.FIELD_TYPE_NAMES:[Ljava/lang/String;.10:Ljava/lang/String; 820
+Lorg/apache/http/conn/ssl/SSLSocketFactory$NoPreloadHolder; 820
+Landroid/app/LoadedApk$WarningContextClassLoader; 820
+Ljavax/sip/header/PriorityHeader;.NORMAL:Ljava/lang/String; 820
+Lcom/android/internal/telephony/euicc/EuiccController;.EXTRA_OPERATION:Ljava/lang/String; 820
+Landroid/widget/ViewAnimator; 820
+Landroid/security/keystore/KeyGenParameterSpec; 821
+Landroid/text/style/StyleSpan; 821
+Landroid/util/SparseIntArray; 823
+Landroid/database/ContentObserver; 823
diff --git a/core/api/current.txt b/core/api/current.txt
index b95295cd4ad9..a8b9e331de2a 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -11240,6 +11240,7 @@ package android.content {
method public void removeCategory(String);
method public void removeExtra(String);
method public void removeFlags(int);
+ method @FlaggedApi("android.security.prevent_intent_redirect") public void removeLaunchSecurityProtection();
method @NonNull public android.content.Intent replaceExtras(@NonNull android.content.Intent);
method @NonNull public android.content.Intent replaceExtras(@Nullable android.os.Bundle);
method public android.content.ComponentName resolveActivity(@NonNull android.content.pm.PackageManager);
@@ -61760,6 +61761,7 @@ package android.window {
method public float getTouchX();
method public float getTouchY();
field public static final int EDGE_LEFT = 0; // 0x0
+ field @FlaggedApi("com.android.window.flags.predictive_back_swipe_edge_none_api") public static final int EDGE_NONE = 2; // 0x2
field public static final int EDGE_RIGHT = 1; // 0x1
}
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 1ff8c510b6bf..79bea0188308 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1892,8 +1892,7 @@ package android.hardware.soundtrigger {
}
@FlaggedApi("android.media.soundtrigger.manager_api") public static final class SoundTrigger.RecognitionConfig implements android.os.Parcelable {
- ctor @Deprecated public SoundTrigger.RecognitionConfig(boolean, boolean, @Nullable android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra[], @Nullable byte[], int);
- ctor public SoundTrigger.RecognitionConfig(boolean, boolean, @Nullable android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra[], @Nullable byte[]);
+ ctor @Deprecated public SoundTrigger.RecognitionConfig(boolean, boolean, @Nullable android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra[], @Nullable byte[]);
}
public static class SoundTrigger.RecognitionEvent {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e7f4dbc24022..b0a8b1b2dbf3 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -237,6 +237,7 @@ import com.android.internal.os.DebugStore;
import com.android.internal.os.RuntimeInit;
import com.android.internal.os.SafeZipPathValidatorCallback;
import com.android.internal.os.SomeArgs;
+import com.android.internal.os.logging.MetricsLoggerWrapper;
import com.android.internal.policy.DecorView;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastPrintWriter;
@@ -2680,7 +2681,10 @@ public final class ActivityThread extends ClientTransactionHandler
handleUnstableProviderDied((IBinder)msg.obj, false);
break;
case REQUEST_ASSIST_CONTEXT_EXTRAS:
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+ "handleRequestAssistContextExtras");
handleRequestAssistContextExtras((RequestAssistContextExtras)msg.obj);
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case TRANSLUCENT_CONVERSION_COMPLETE:
handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1);
@@ -7675,6 +7679,16 @@ public final class ActivityThread extends ClientTransactionHandler
}
}
});
+
+ // Register callback to report native memory metrics post GC cleanup
+ if (Flags.reportPostgcMemoryMetrics() &&
+ com.android.libcore.readonly.Flags.postCleanupApis()) {
+ VMRuntime.addPostCleanupCallback(new Runnable() {
+ @Override public void run() {
+ MetricsLoggerWrapper.logPostGcMemorySnapshot();
+ }
+ });
+ }
}
@UnsupportedAppUsage
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index ed6b85125e66..fb5a12b49921 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -132,6 +132,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.Immutable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
+import com.android.internal.pm.RoSystemFeatures;
import com.android.internal.util.UserIcons;
import dalvik.system.VMRuntime;
@@ -822,6 +823,16 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public Boolean recompute(HasSystemFeatureQuery query) {
try {
+ // As an optimization, check first to see if the feature was defined at
+ // compile-time as either available or unavailable.
+ // TODO(b/203143243): Consider hoisting this optimization out of the cache
+ // after the trunk stable (build) flag has soaked and more features are
+ // defined at compile-time.
+ Boolean maybeHasSystemFeature =
+ RoSystemFeatures.maybeHasFeature(query.name, query.version);
+ if (maybeHasSystemFeature != null) {
+ return maybeHasSystemFeature.booleanValue();
+ }
return ActivityThread.currentActivityThread().getPackageManager().
hasSystemFeature(query.name, query.version);
} catch (RemoteException e) {
diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java
index e4d3baa2f05a..acedef0c7788 100644
--- a/core/java/android/app/PropertyInvalidatedCache.java
+++ b/core/java/android/app/PropertyInvalidatedCache.java
@@ -21,11 +21,13 @@ import static android.text.TextUtils.formatSimple;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
+import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
+import android.os.Process;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.text.TextUtils;
@@ -78,10 +80,15 @@ public class PropertyInvalidatedCache<Query, Result> {
public abstract @Nullable R apply(@NonNull Q query);
/**
- * Return true if a query should not use the cache. The default implementation
- * always uses the cache.
+ * Return true if a query should not use the cache. The default implementation returns true
+ * if the process UID differs from the calling UID. This is to prevent a binder caller from
+ * reading a cached value created due to a different binder caller, when processes are
+ * caching on behalf of other processes.
*/
public boolean shouldBypassCache(@NonNull Q query) {
+ if(android.multiuser.Flags.propertyInvalidatedCacheBypassMismatchedUids()) {
+ return Binder.getCallingUid() != Process.myUid();
+ }
return false;
}
};
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index e882bb564db9..081ce31e0886 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -345,6 +345,15 @@ public class TaskInfo {
*/
public AppCompatTaskInfo appCompatTaskInfo = AppCompatTaskInfo.create();
+ /**
+ * The top activity's main window frame if it doesn't match the top activity bounds.
+ * {@code null}, otherwise.
+ *
+ * @hide
+ */
+ @Nullable
+ public Rect topActivityMainWindowFrame;
+
TaskInfo() {
// Do nothing
}
@@ -477,7 +486,8 @@ public class TaskInfo {
&& Objects.equals(capturedLink, that.capturedLink)
&& capturedLinkTimestamp == that.capturedLinkTimestamp
&& requestedVisibleTypes == that.requestedVisibleTypes
- && appCompatTaskInfo.equalsForTaskOrganizer(that.appCompatTaskInfo);
+ && appCompatTaskInfo.equalsForTaskOrganizer(that.appCompatTaskInfo)
+ && Objects.equals(topActivityMainWindowFrame, that.topActivityMainWindowFrame);
}
/**
@@ -553,6 +563,7 @@ public class TaskInfo {
capturedLinkTimestamp = source.readLong();
requestedVisibleTypes = source.readInt();
appCompatTaskInfo = source.readTypedObject(AppCompatTaskInfo.CREATOR);
+ topActivityMainWindowFrame = source.readTypedObject(Rect.CREATOR);
}
/**
@@ -606,6 +617,7 @@ public class TaskInfo {
dest.writeLong(capturedLinkTimestamp);
dest.writeInt(requestedVisibleTypes);
dest.writeTypedObject(appCompatTaskInfo, flags);
+ dest.writeTypedObject(topActivityMainWindowFrame, flags);
}
@Override
@@ -649,6 +661,7 @@ public class TaskInfo {
+ " capturedLinkTimestamp=" + capturedLinkTimestamp
+ " requestedVisibleTypes=" + requestedVisibleTypes
+ " appCompatTaskInfo=" + appCompatTaskInfo
+ + " topActivityMainWindowFrame=" + topActivityMainWindowFrame
+ "}";
}
}
diff --git a/core/java/android/app/metrics.aconfig b/core/java/android/app/metrics.aconfig
new file mode 100644
index 000000000000..488f1c71990b
--- /dev/null
+++ b/core/java/android/app/metrics.aconfig
@@ -0,0 +1,10 @@
+package: "android.app"
+container: "system"
+
+flag {
+ namespace: "system_performance"
+ name: "report_postgc_memory_metrics"
+ is_exported: false
+ description: "Controls whether to report memory metrics post GC cleanup"
+ bug: "331243037"
+}
diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig
index 37fa9a26b91c..1d4c18f6a62c 100644
--- a/core/java/android/app/notification.aconfig
+++ b/core/java/android/app/notification.aconfig
@@ -286,4 +286,11 @@ flag {
namespace: "systemui"
description: "Adds logging for notification/modes backup and restore events"
bug: "289524803"
-} \ No newline at end of file
+}
+
+flag {
+ name: "notification_classification_ui"
+ namespace: "systemui"
+ description: "Adds UI for NAS classification of notifications"
+ bug: "367996732"
+}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index f71952849872..e8cec70ef6a8 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -20,6 +20,7 @@ import static android.app.sdksandbox.SdkSandboxManager.ACTION_START_SANDBOXED_AC
import static android.content.ContentProvider.maybeAddUserId;
import static android.os.Flags.FLAG_ALLOW_PRIVATE_PROFILE;
import static android.security.Flags.FLAG_FRP_ENFORCEMENT;
+import static android.security.Flags.FLAG_PREVENT_INTENT_REDIRECT;
import static android.security.Flags.preventIntentRedirect;
import android.Manifest;
@@ -40,7 +41,10 @@ import android.app.Activity;
import android.app.ActivityThread;
import android.app.AppGlobals;
import android.app.StatusBarManager;
+import android.app.compat.CompatChanges;
import android.bluetooth.BluetoothDevice;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.Overridable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -670,6 +674,11 @@ import java.util.TimeZone;
public class Intent implements Parcelable, Cloneable {
private static final String TAG = "Intent";
+ /** @hide */
+ @ChangeId
+ @Overridable
+ public static final long ENABLE_PREVENT_INTENT_REDIRECT = 29076063L;
+
private static final String ATTR_ACTION = "action";
private static final String TAG_CATEGORIES = "categories";
private static final String ATTR_CATEGORY = "category";
@@ -12240,7 +12249,7 @@ public class Intent implements Parcelable, Cloneable {
* @hide
*/
public void collectExtraIntentKeys() {
- if (!preventIntentRedirect()) return;
+ if (!isPreventIntentRedirectEnabled()) return;
if (mExtras != null && !mExtras.isParcelled() && !mExtras.isEmpty()) {
for (String key : mExtras.keySet()) {
@@ -12257,6 +12266,14 @@ public class Intent implements Parcelable, Cloneable {
}
}
+ /**
+ * @hide
+ */
+ public static boolean isPreventIntentRedirectEnabled() {
+ return preventIntentRedirect() && CompatChanges.isChangeEnabled(
+ ENABLE_PREVENT_INTENT_REDIRECT);
+ }
+
/** @hide */
public void checkCreatorToken() {
if (mExtras == null) return;
@@ -12281,6 +12298,20 @@ public class Intent implements Parcelable, Cloneable {
mExtras.setIsIntentExtra();
}
+ /**
+ * When an intent comes from another app or component as an embedded extra intent, the system
+ * creates a token to identify the creator of this foreign intent. If this token is missing or
+ * invalid, the system will block the launch of this intent. If it contains a valid token, the
+ * system will perform verification against the creator to block launching target it has no
+ * permission to launch or block it from granting URI access to the tagert it cannot access.
+ * This method provides a way to opt out this feature.
+ */
+ @FlaggedApi(FLAG_PREVENT_INTENT_REDIRECT)
+ public void removeLaunchSecurityProtection() {
+ mExtendedFlags &= ~EXTENDED_FLAG_MISSING_CREATOR_OR_INVALID_TOKEN;
+ removeCreatorTokenInfo();
+ }
+
public void writeToParcel(Parcel out, int flags) {
out.writeString8(mAction);
Uri.writeToParcel(out, mData);
@@ -12331,7 +12362,7 @@ public class Intent implements Parcelable, Cloneable {
out.writeInt(0);
}
- if (preventIntentRedirect()) {
+ if (isPreventIntentRedirectEnabled()) {
if (mCreatorTokenInfo == null) {
out.writeInt(0);
} else {
@@ -12398,7 +12429,7 @@ public class Intent implements Parcelable, Cloneable {
mOriginalIntent = new Intent(in);
}
- if (preventIntentRedirect()) {
+ if (isPreventIntentRedirectEnabled()) {
if (in.readInt() != 0) {
mCreatorTokenInfo = new CreatorTokenInfo();
mCreatorTokenInfo.mCreatorToken = in.readStrongBinder();
diff --git a/core/java/android/content/pm/flags.aconfig b/core/java/android/content/pm/flags.aconfig
index 5b38942d468d..5f439b1dcab9 100644
--- a/core/java/android/content/pm/flags.aconfig
+++ b/core/java/android/content/pm/flags.aconfig
@@ -342,3 +342,11 @@ flag {
bug: "292261144"
is_fixed_read_only: true
}
+
+flag {
+ name: "change_launcher_badging"
+ namespace: "package_manager_service"
+ description: "Feature flag to introduce a new way to change the launcher badging."
+ bug: "364760703"
+ is_fixed_read_only: true
+}
diff --git a/core/java/android/database/DatabaseUtils.java b/core/java/android/database/DatabaseUtils.java
index 3c4307c63cf7..0d583dedeb74 100644
--- a/core/java/android/database/DatabaseUtils.java
+++ b/core/java/android/database/DatabaseUtils.java
@@ -48,8 +48,6 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
/**
* Static utility methods for dealing with databases and {@link Cursor}s.
@@ -1577,49 +1575,6 @@ public class DatabaseUtils {
}
/**
- * The legacy prefix matcher.
- */
- private static String getSqlStatementPrefixSimple(@NonNull String sql) {
- sql = sql.trim();
- if (sql.length() < 3) {
- return null;
- }
- return sql.substring(0, 3).toUpperCase(Locale.ROOT);
- }
-
- /**
- * A regular expression that matches the first three characters in a SQL statement, after
- * skipping past comments and whitespace. PREFIX_GROUP_NUM is the regex group that contains
- * the matching prefix string. If PREFIX_REGEX is changed, PREFIX_GROUP_NUM may require an
- * update too.
- */
- private static final String PREFIX_REGEX =
- "(" // Zero-or more...
- + "\\s+" // Leading space
- + "|"
- + "--.*?\n" // Line comment
- + "|"
- + "/\\*[\\w\\W]*?\\*/" // Block comment
- + ")*"
- + "(\\w\\w\\w)"; // Three word-characters
- private static final int PREFIX_GROUP_NUM = 2;
- private static final Pattern sPrefixPattern = Pattern.compile(PREFIX_REGEX);
-
- /**
- * Return the three-letter prefix of a SQL statement, skipping past whitespace and comments.
- * Comments either start with "--" and run to the end of the line or are C-style block
- * comments. The function returns null if a prefix could not be found.
- */
- private static String getSqlStatementPrefixExtendedRegex(String sql) {
- Matcher m = sPrefixPattern.matcher(sql);
- if (m.lookingAt()) {
- return m.group(PREFIX_GROUP_NUM).toUpperCase(Locale.ROOT);
- } else {
- return null;
- }
- }
-
- /**
* Return the index of the first character past comments and whitespace. -1 is returned if
* a comment is malformed.
*/
@@ -1719,15 +1674,7 @@ public class DatabaseUtils {
* @hide
*/
public static int getSqlStatementTypeExtended(@NonNull String sql) {
- if (Flags.simpleSqlCommentScanner()) {
- return categorizeStatement(getSqlStatementPrefixExtendedNoRegex(sql), sql);
- } else {
- int type = categorizeStatement(getSqlStatementPrefixSimple(sql), sql);
- if (type == STATEMENT_COMMENT) {
- type = categorizeStatement(getSqlStatementPrefixExtendedRegex(sql), sql);
- }
- return type;
- }
+ return categorizeStatement(getSqlStatementPrefixExtendedNoRegex(sql), sql);
}
/**
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 914aa51e5314..d77e6280d19c 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -129,9 +129,6 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
// Restrict this connection to read-only operations.
private boolean mOnlyAllowReadOnlyOperations;
- // Allow this connection to treat updates to temporary tables as read-only operations.
- private boolean mAllowTempTableRetry = Flags.sqliteAllowTempTables();
-
// The number of times attachCancellationSignal has been called.
// Because SQLite statement execution can be reentrant, we keep track of how many
// times we have attempted to attach a cancellation signal to the connection so that
@@ -1281,19 +1278,17 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
/**
* Verify that the statement is read-only, if the connection only allows read-only
- * operations. If the connection allows updates to temporary tables, then the statement is
- * read-only if the only updates are to temporary tables.
+ * operations. If the statement is not read-only, then check if the statement only modifies
+ * temp tables, in which case it is treated the same as a read-only statement and is allowed.
* @param statement The statement to check.
* @throws SQLiteException if the statement could update the database inside a read-only
* transaction.
*/
void throwIfStatementForbidden(PreparedStatement statement) {
if (mOnlyAllowReadOnlyOperations && !statement.mReadOnly) {
- if (mAllowTempTableRetry) {
- statement.mReadOnly =
- nativeUpdatesTempOnly(mConnectionPtr, statement.mStatementPtr);
- if (statement.mReadOnly) return;
- }
+ statement.mReadOnly =
+ nativeUpdatesTempOnly(mConnectionPtr, statement.mStatementPtr);
+ if (statement.mReadOnly) return;
throw new SQLiteException("Cannot execute this statement because it "
+ "might modify the database but the connection is read-only.");
diff --git a/core/java/android/database/sqlite/flags.aconfig b/core/java/android/database/sqlite/flags.aconfig
index 285f984faab7..d5a7db82d456 100644
--- a/core/java/android/database/sqlite/flags.aconfig
+++ b/core/java/android/database/sqlite/flags.aconfig
@@ -9,19 +9,3 @@ flag {
description: "SQLite APIs held back for Android 15"
bug: "279043253"
}
-
-flag {
- name: "sqlite_allow_temp_tables"
- namespace: "system_performance"
- is_fixed_read_only: true
- description: "Permit updates to TEMP tables in read-only transactions"
- bug: "317993835"
-}
-
-flag {
- name: "simple_sql_comment_scanner"
- namespace: "system_performance"
- is_fixed_read_only: true
- description: "Scan SQL comments by hand instead of with a regex"
- bug: "329118560"
-}
diff --git a/core/java/android/hardware/biometrics/flags.aconfig b/core/java/android/hardware/biometrics/flags.aconfig
index 047d1fa4f49a..26ffa11823d8 100644
--- a/core/java/android/hardware/biometrics/flags.aconfig
+++ b/core/java/android/hardware/biometrics/flags.aconfig
@@ -39,3 +39,11 @@ flag {
description: "This flag controls whether LSKF fallback is removed from biometric prompt when the phone is outside trusted locations"
bug: "322081563"
}
+
+flag {
+ name: "screen_off_unlock_udfps"
+ is_exported: true
+ namespace: "biometrics_integration"
+ description: "This flag controls Whether to enable fp unlock when screen turns off on udfps devices"
+ bug: "373792870"
+}
diff --git a/core/java/android/hardware/display/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
index 47541ca16cda..59a602ca092d 100644
--- a/core/java/android/hardware/display/AmbientDisplayConfiguration.java
+++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
@@ -18,6 +18,7 @@ package android.hardware.display;
import android.annotation.TestApi;
import android.content.Context;
+import android.hardware.biometrics.Flags;
import android.os.Build;
import android.os.SystemProperties;
import android.provider.Settings;
@@ -41,6 +42,7 @@ public class AmbientDisplayConfiguration {
private final Context mContext;
private final boolean mAlwaysOnByDefault;
private final boolean mPickupGestureEnabledByDefault;
+ private final boolean mScreenOffUdfpsEnabledByDefault;
/** Copied from android.provider.Settings.Secure since these keys are hidden. */
private static final String[] DOZE_SETTINGS = {
@@ -68,6 +70,8 @@ public class AmbientDisplayConfiguration {
mAlwaysOnByDefault = mContext.getResources().getBoolean(R.bool.config_dozeAlwaysOnEnabled);
mPickupGestureEnabledByDefault =
mContext.getResources().getBoolean(R.bool.config_dozePickupGestureEnabled);
+ mScreenOffUdfpsEnabledByDefault =
+ mContext.getResources().getBoolean(R.bool.config_screen_off_udfps_enabled);
}
/** @hide */
@@ -146,7 +150,9 @@ public class AmbientDisplayConfiguration {
/** @hide */
public boolean screenOffUdfpsEnabled(int user) {
return !TextUtils.isEmpty(udfpsLongPressSensorType())
- && boolSettingDefaultOff("screen_off_udfps_enabled", user);
+ && ((mScreenOffUdfpsEnabledByDefault && Flags.screenOffUnlockUdfps())
+ ? boolSettingDefaultOn("screen_off_udfps_enabled", user)
+ : boolSettingDefaultOff("screen_off_udfps_enabled", user));
}
/** @hide */
diff --git a/core/java/android/hardware/input/KeyGestureEvent.java b/core/java/android/hardware/input/KeyGestureEvent.java
index 5ee61bcd436a..2df541818e3d 100644
--- a/core/java/android/hardware/input/KeyGestureEvent.java
+++ b/core/java/android/hardware/input/KeyGestureEvent.java
@@ -99,6 +99,7 @@ public final class KeyGestureEvent {
public static final int KEY_GESTURE_TYPE_TV_TRIGGER_BUG_REPORT = 59;
public static final int KEY_GESTURE_TYPE_ACCESSIBILITY_SHORTCUT = 60;
public static final int KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS = 61;
+ public static final int KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY = 62;
public static final int FLAG_CANCELLED = 1;
@@ -175,7 +176,7 @@ public final class KeyGestureEvent {
KEY_GESTURE_TYPE_TV_TRIGGER_BUG_REPORT,
KEY_GESTURE_TYPE_ACCESSIBILITY_SHORTCUT,
KEY_GESTURE_TYPE_CLOSE_ALL_DIALOGS,
-
+ KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY,
})
@Retention(RetentionPolicy.SOURCE)
public @interface KeyGestureType {
@@ -415,6 +416,8 @@ public final class KeyGestureEvent {
case KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_LEFT:
case KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_RIGHT:
return FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__CHANGE_SPLITSCREEN_FOCUS;
+ case KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY:
+ return FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__MOVE_TO_NEXT_DISPLAY;
case KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT:
return FrameworkStatsLog.KEYBOARD_SYSTEMS_EVENT_REPORTED__KEYBOARD_SYSTEM_EVENT__TRIGGER_BUG_REPORT;
case KEY_GESTURE_TYPE_LOCK_SCREEN:
@@ -530,6 +533,8 @@ public final class KeyGestureEvent {
return "KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_LEFT";
case KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_RIGHT:
return "KEY_GESTURE_TYPE_CHANGE_SPLITSCREEN_FOCUS_RIGHT";
+ case KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY:
+ return "KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY";
case KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT:
return "KEY_GESTURE_TYPE_TRIGGER_BUG_REPORT";
case KEY_GESTURE_TYPE_LOCK_SCREEN:
diff --git a/core/java/android/hardware/soundtrigger/ConversionUtil.java b/core/java/android/hardware/soundtrigger/ConversionUtil.java
index 22ae67672950..2ba107805569 100644
--- a/core/java/android/hardware/soundtrigger/ConversionUtil.java
+++ b/core/java/android/hardware/soundtrigger/ConversionUtil.java
@@ -40,6 +40,7 @@ import android.os.SharedMemory;
import android.system.ErrnoException;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Locale;
import java.util.UUID;
@@ -170,17 +171,18 @@ public class ConversionUtil {
public static SoundTrigger.RecognitionConfig aidl2apiRecognitionConfig(
RecognitionConfig aidlConfig) {
- var keyphrases =
- new SoundTrigger.KeyphraseRecognitionExtra[aidlConfig.phraseRecognitionExtras.length];
- int i = 0;
+ var keyphrases = new ArrayList<SoundTrigger.KeyphraseRecognitionExtra>(
+ aidlConfig.phraseRecognitionExtras.length);
for (var extras : aidlConfig.phraseRecognitionExtras) {
- keyphrases[i++] = aidl2apiPhraseRecognitionExtra(extras);
+ keyphrases.add(aidl2apiPhraseRecognitionExtra(extras));
}
- return new SoundTrigger.RecognitionConfig(aidlConfig.captureRequested,
- false /** allowMultipleTriggers **/,
- keyphrases,
- Arrays.copyOf(aidlConfig.data, aidlConfig.data.length),
- aidl2apiAudioCapabilities(aidlConfig.audioCapabilities));
+ return new SoundTrigger.RecognitionConfig.Builder()
+ .setCaptureRequested(aidlConfig.captureRequested)
+ .setAllowMultipleTriggers(false)
+ .setKeyphrases(keyphrases)
+ .setData(Arrays.copyOf(aidlConfig.data, aidlConfig.data.length))
+ .setAudioCapabilities(aidl2apiAudioCapabilities(aidlConfig.audioCapabilities))
+ .build();
}
public static PhraseRecognitionExtra api2aidlPhraseRecognitionExtra(
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index 05e91e447a43..a1e7567faead 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -1529,8 +1529,6 @@ public class SoundTrigger {
* config that can be used by
* {@link SoundTriggerModule#startRecognition(int, RecognitionConfig)}
*
- * @deprecated should use builder-based constructor instead.
- * TODO(b/368042125): remove this method.
* @param captureRequested Whether the DSP should capture the trigger sound.
* @param allowMultipleTriggers Whether the service should restart listening after the DSP
* triggers.
@@ -1538,15 +1536,10 @@ public class SoundTrigger {
* @param data Opaque data for use by system applications who know about voice engine
* internals, typically during enrollment.
* @param audioCapabilities Bit field encoding of the AudioCapabilities.
- *
- * @hide
*/
- @Deprecated
- @SuppressWarnings("Todo")
- @TestApi
- public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
- @SuppressLint("ArrayReturn") @Nullable KeyphraseRecognitionExtra[] keyphrases,
- @Nullable byte[] data, int audioCapabilities) {
+ private RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
+ @Nullable KeyphraseRecognitionExtra[] keyphrases, @Nullable byte[] data,
+ int audioCapabilities) {
this.mCaptureRequested = captureRequested;
this.mAllowMultipleTriggers = allowMultipleTriggers;
this.mKeyphrases = keyphrases != null ? keyphrases : new KeyphraseRecognitionExtra[0];
@@ -1558,6 +1551,7 @@ public class SoundTrigger {
* Constructor for {@link RecognitionConfig} without audioCapabilities. The
* audioCapabilities is set to 0.
*
+ * @deprecated Use {@link Builder} instead.
* @param captureRequested Whether the DSP should capture the trigger sound.
* @param allowMultipleTriggers Whether the service should restart listening after the DSP
* triggers.
@@ -1567,10 +1561,10 @@ public class SoundTrigger {
* @hide
*/
@UnsupportedAppUsage
+ @Deprecated
@TestApi
public RecognitionConfig(boolean captureRequested, boolean allowMultipleTriggers,
- @SuppressLint("ArrayReturn") @Nullable KeyphraseRecognitionExtra[] keyphrases,
- @Nullable byte[] data) {
+ @Nullable KeyphraseRecognitionExtra[] keyphrases, @Nullable byte[] data) {
this(captureRequested, allowMultipleTriggers, keyphrases, data, 0);
}
@@ -1718,7 +1712,7 @@ public class SoundTrigger {
/**
* Sets capture requested state.
- * @param captureRequested The new requested state.
+ * @param captureRequested Whether the DSP should capture the trigger sound.
* @return the same Builder instance.
*/
public @NonNull Builder setCaptureRequested(boolean captureRequested) {
@@ -1728,7 +1722,8 @@ public class SoundTrigger {
/**
* Sets allow multiple triggers state.
- * @param allowMultipleTriggers The new allow multiple triggers state.
+ * @param allowMultipleTriggers Whether the service should restart listening after the
+ * DSP triggers.
* @return the same Builder instance.
*/
public @NonNull Builder setAllowMultipleTriggers(boolean allowMultipleTriggers) {
@@ -1738,7 +1733,8 @@ public class SoundTrigger {
/**
* Sets the keyphrases field.
- * @param keyphrases The new keyphrases.
+ * @param keyphrases The list of keyphrase specific data associated with this
+ * recognition session.
* @return the same Builder instance.
*/
public @NonNull Builder setKeyphrases(
@@ -1749,7 +1745,9 @@ public class SoundTrigger {
/**
* Sets the data field.
- * @param data The new data.
+ * @param data Opaque data provided to the DSP associated with this recognition session,
+ * which is used by system applications who know about voice engine
+ * internals, typically during enrollment.
* @return the same Builder instance.
*/
public @NonNull Builder setData(@Nullable byte[] data) {
@@ -1759,7 +1757,8 @@ public class SoundTrigger {
/**
* Sets the audio capabilities field.
- * @param audioCapabilities The new audio capabilities.
+ * @param audioCapabilities The bit field encoding of the audio capabilities associated
+ * with this recognition session.
* @return the same Builder instance.
*/
public @NonNull Builder setAudioCapabilities(int audioCapabilities) {
diff --git a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java
index 46cf0163c0e5..c0398ce1fcf1 100644
--- a/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java
+++ b/core/java/android/net/vcn/VcnCellUnderlyingNetworkTemplate.java
@@ -40,9 +40,9 @@ import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.server.vcn.util.PersistableBundleUtils;
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index 1c9be6fb4b82..f275714e2cf5 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -28,13 +28,13 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.net.LinkProperties;
import android.net.NetworkCapabilities;
-import android.os.Binder;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.net.module.util.BinderUtils;
import java.io.IOException;
import java.lang.annotation.Retention;
@@ -711,7 +711,7 @@ public class VcnManager {
@Override
public void onPolicyChanged() {
- Binder.withCleanCallingIdentity(
+ BinderUtils.withCleanCallingIdentity(
() -> mExecutor.execute(() -> mListener.onPolicyChanged()));
}
}
@@ -734,7 +734,7 @@ public class VcnManager {
@Override
public void onVcnStatusChanged(@VcnStatusCode int statusCode) {
- Binder.withCleanCallingIdentity(
+ BinderUtils.withCleanCallingIdentity(
() -> mExecutor.execute(() -> mCallback.onStatusChanged(statusCode)));
}
@@ -747,7 +747,7 @@ public class VcnManager {
@Nullable String exceptionMessage) {
final Throwable cause = createThrowableByClassName(exceptionClass, exceptionMessage);
- Binder.withCleanCallingIdentity(
+ BinderUtils.withCleanCallingIdentity(
() ->
mExecutor.execute(
() ->
diff --git a/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java
index edf2c093bc8b..16114dd135af 100644
--- a/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java
+++ b/core/java/android/net/vcn/VcnUnderlyingNetworkTemplate.java
@@ -21,10 +21,10 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.PersistableBundle;
+import android.util.IndentingPrintWriter;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
diff --git a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java
index 2e6b09f032fb..c7b2f188ba96 100644
--- a/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java
+++ b/core/java/android/net/vcn/VcnWifiUnderlyingNetworkTemplate.java
@@ -29,9 +29,9 @@ import android.net.NetworkCapabilities;
import android.net.vcn.VcnUnderlyingNetworkTemplate.MatchCriteria;
import android.os.PersistableBundle;
import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.IndentingPrintWriter;
import com.android.server.vcn.util.PersistableBundleUtils;
import java.util.ArrayList;
diff --git a/core/java/android/os/BatteryUsageStats.java b/core/java/android/os/BatteryUsageStats.java
index ddcb5c60ab80..6c3c2852c7e7 100644
--- a/core/java/android/os/BatteryUsageStats.java
+++ b/core/java/android/os/BatteryUsageStats.java
@@ -24,6 +24,8 @@ import android.util.Range;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BatteryStatsHistory;
import com.android.internal.os.BatteryStatsHistoryIterator;
import com.android.internal.os.MonotonicClock;
@@ -43,7 +45,9 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
/**
* Contains a snapshot of battery attribution data, on a per-subsystem and per-UID basis.
@@ -126,6 +130,12 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
// Max window size. CursorWindow uses only as much memory as needed.
private static final long BATTERY_CONSUMER_CURSOR_WINDOW_SIZE = 20_000_000; // bytes
+ /**
+ * Used by tests to ensure all BatteryUsageStats instances are closed.
+ */
+ @VisibleForTesting
+ public static boolean DEBUG_INSTANCE_COUNT;
+
private static final int STATSD_PULL_ATOM_MAX_BYTES = 45000;
private static final int[] UID_USAGE_TIME_PROCESS_STATES = {
@@ -153,7 +163,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
private final List<UserBatteryConsumer> mUserBatteryConsumers;
private final AggregateBatteryConsumer[] mAggregateBatteryConsumers;
private final BatteryStatsHistory mBatteryStatsHistory;
- private BatteryConsumer.BatteryConsumerDataLayout mBatteryConsumerDataLayout;
+ private final BatteryConsumer.BatteryConsumerDataLayout mBatteryConsumerDataLayout;
private CursorWindow mBatteryConsumersCursorWindow;
private BatteryUsageStats(@NonNull Builder builder) {
@@ -873,6 +883,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
@Override
public void close() throws IOException {
+ onCursorWindowReleased(mBatteryConsumersCursorWindow);
mBatteryConsumersCursorWindow.close();
mBatteryConsumersCursorWindow = null;
}
@@ -880,6 +891,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
@Override
protected void finalize() throws Throwable {
if (mBatteryConsumersCursorWindow != null) {
+ // Do not decrement sOpenCusorWindowCount. All instances should be closed explicitly
mBatteryConsumersCursorWindow.close();
}
super.finalize();
@@ -934,6 +946,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
boolean includesPowerStateData, double minConsumedPowerThreshold) {
mBatteryConsumersCursorWindow =
new CursorWindow(null, BATTERY_CONSUMER_CURSOR_WINDOW_SIZE);
+ onCursorWindowAllocated(mBatteryConsumersCursorWindow);
mBatteryConsumerDataLayout = BatteryConsumer.createBatteryConsumerDataLayout(
customPowerComponentNames, includePowerModels, includeProcessStateData,
includeScreenStateData, includesPowerStateData);
@@ -996,6 +1009,7 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
*/
public void discard() {
mBatteryConsumersCursorWindow.close();
+ onCursorWindowReleased(mBatteryConsumersCursorWindow);
}
/**
@@ -1264,4 +1278,50 @@ public final class BatteryUsageStats implements Parcelable, Closeable {
}
}
}
+
+ @GuardedBy("BatteryUsageStats.class")
+ private static Map<CursorWindow, Exception> sInstances;
+
+ private static void onCursorWindowAllocated(CursorWindow window) {
+ if (!DEBUG_INSTANCE_COUNT) {
+ return;
+ }
+
+ synchronized (BatteryUsageStats.class) {
+ if (sInstances == null) {
+ sInstances = new HashMap<>();
+ }
+ sInstances.put(window, new Exception());
+ }
+ }
+
+ private static void onCursorWindowReleased(CursorWindow window) {
+ if (!DEBUG_INSTANCE_COUNT) {
+ return;
+ }
+
+ synchronized (BatteryUsageStats.class) {
+ sInstances.remove(window);
+ }
+ }
+
+ /**
+ * Used by tests to ensure all BatteryUsageStats instances are closed.
+ */
+ @VisibleForTesting
+ public static void assertAllInstancesClosed() {
+ if (!DEBUG_INSTANCE_COUNT) {
+ throw new IllegalStateException("DEBUG_INSTANCE_COUNT is false");
+ }
+
+ synchronized (BatteryUsageStats.class) {
+ if (!sInstances.isEmpty()) {
+ Exception callSite = sInstances.entrySet().iterator().next().getValue();
+ int count = sInstances.size();
+ sInstances.clear();
+ throw new IllegalStateException(
+ "Instances of BatteryUsageStats not closed: " + count, callSite);
+ }
+ }
+ }
}
diff --git a/core/java/android/os/VibratorInfo.java b/core/java/android/os/VibratorInfo.java
index 9419032c46f8..9dec8673f019 100644
--- a/core/java/android/os/VibratorInfo.java
+++ b/core/java/android/os/VibratorInfo.java
@@ -316,9 +316,7 @@ public class VibratorInfo implements Parcelable {
* @return True if the hardware can control the frequency of the vibrations, otherwise false.
*/
public boolean hasFrequencyControl() {
- // We currently can only control frequency of the vibration using the compose PWLE method.
- return hasCapability(
- IVibrator.CAP_FREQUENCY_CONTROL | IVibrator.CAP_COMPOSE_PWLE_EFFECTS);
+ return hasCapability(IVibrator.CAP_FREQUENCY_CONTROL);
}
/**
@@ -481,7 +479,8 @@ public class VibratorInfo implements Parcelable {
* @return True if the hardware supports creating envelope effects, false otherwise.
*/
public boolean areEnvelopeEffectsSupported() {
- return hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2);
+ return hasCapability(
+ IVibrator.CAP_FREQUENCY_CONTROL | IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2);
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0be55844b829..764570ead4e1 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -19305,14 +19305,14 @@ public final class Settings {
* If hotword detection should be enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String HOTWORD_DETECTION_ENABLED = "hotword_detection_enabled";
/**
* Whether Smart Replies are enabled within Wear.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String SMART_REPLIES_ENABLED = "smart_replies_enabled";
/**
@@ -19326,7 +19326,7 @@ public final class Settings {
* If FLP should obtain location data from the paired device.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String OBTAIN_PAIRED_DEVICE_LOCATION =
"obtain_paired_device_location";
@@ -19334,7 +19334,7 @@ public final class Settings {
* The play store availability on companion phone.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String PHONE_PLAY_STORE_AVAILABILITY =
"phone_play_store_availability";
@@ -19350,7 +19350,7 @@ public final class Settings {
* Whether the bug report is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String BUG_REPORT = "bug_report";
// Possible bug report states
@@ -19363,14 +19363,14 @@ public final class Settings {
* The enabled/disabled state of the SmartIlluminate.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String SMART_ILLUMINATE_ENABLED = "smart_illuminate_enabled";
/**
* Whether automatic time is enabled on the watch.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String CLOCKWORK_AUTO_TIME = "clockwork_auto_time";
// Possible clockwork auto time states
@@ -19388,7 +19388,7 @@ public final class Settings {
* Whether automatic time zone is enabled on the watch.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String CLOCKWORK_AUTO_TIME_ZONE = "clockwork_auto_time_zone";
// Possible clockwork auto time zone states
@@ -19405,14 +19405,14 @@ public final class Settings {
* Whether 24 hour time format is enabled on the watch.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String CLOCKWORK_24HR_TIME = "clockwork_24hr_time";
/**
* Whether the auto wifi toggle setting is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AUTO_WIFI = "auto_wifi";
// Possible force wifi on states
@@ -19432,7 +19432,7 @@ public final class Settings {
* wifi requirement until this time). The time is in millis since epoch.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String ALT_BYPASS_WIFI_REQUIREMENT_TIME_MILLIS =
"alt_bypass_wifi_requirement_time_millis";
@@ -19440,7 +19440,7 @@ public final class Settings {
* Whether the setup was skipped.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String SETUP_SKIPPED = "setup_skipped";
// Possible setup_skipped states
@@ -19455,7 +19455,7 @@ public final class Settings {
* The last requested call forwarding action.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String LAST_CALL_FORWARD_ACTION = "last_call_forward_action";
// Possible call forwarding actions
@@ -19468,31 +19468,31 @@ public final class Settings {
// Stem button settings.
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_1_TYPE = "STEM_1_TYPE";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_1_DATA = "STEM_1_DATA";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_1_DEFAULT_DATA = "STEM_1_DEFAULT_DATA";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_2_TYPE = "STEM_2_TYPE";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_2_DATA = "STEM_2_DATA";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_2_DEFAULT_DATA = "STEM_2_DEFAULT_DATA";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_3_TYPE = "STEM_3_TYPE";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_3_DATA = "STEM_3_DATA";
/** @hide */
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String STEM_3_DEFAULT_DATA = "STEM_3_DEFAULT_DATA";
// Stem types
@@ -19507,14 +19507,14 @@ public final class Settings {
* If the device should be muted when off body.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String MUTE_WHEN_OFF_BODY_ENABLED = "obtain_mute_when_off_body";
/**
* Wear OS version string.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String WEAR_OS_VERSION_STRING = "wear_os_version_string";
/**
@@ -19527,28 +19527,28 @@ public final class Settings {
* The android wear system version.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String ANDROID_WEAR_VERSION = "android_wear_version";
/**
* The wear system capabiltiies.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String SYSTEM_CAPABILITIES = "system_capabilities";
/**
* The android wear system edition.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String SYSTEM_EDITION = "android_wear_system_edition";
/**
* The Wear platform MR number.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String WEAR_PLATFORM_MR_NUMBER = "wear_platform_mr_number";
/**
@@ -19562,42 +19562,42 @@ public final class Settings {
* Whether ambient is currently enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_ENABLED = "ambient_enabled";
/**
* Whether ambient tilt to wake is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_TILT_TO_WAKE = "ambient_tilt_to_wake";
/**
* Whether ambient low bit mode is enabled by developer options.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_LOW_BIT_ENABLED_DEV = "ambient_low_bit_enabled_dev";
/**
* Whether ambient touch to wake is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_TOUCH_TO_WAKE = "ambient_touch_to_wake";
/**
* Whether ambient tilt to bright is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_TILT_TO_BRIGHT = "ambient_tilt_to_bright";
/**
* Whether touch and hold to edit WF is enabled
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String GESTURE_TOUCH_AND_HOLD_WATCH_FACE_ENABLED =
"gesture_touch_and_hold_watchface_enabled";
@@ -19611,7 +19611,7 @@ public final class Settings {
* Whether bedtime mode is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String BEDTIME_MODE = "bedtime_mode";
/**
@@ -19623,35 +19623,35 @@ public final class Settings {
* Whether the current watchface is decomposable.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String DECOMPOSABLE_WATCHFACE = "current_watchface_decomposable";
/**
* Whether to force ambient when docked.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_FORCE_WHEN_DOCKED = "ambient_force_when_docked";
/**
* Whether the ambient low bit mode is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_LOW_BIT_ENABLED = "ambient_low_bit_enabled";
/**
* The timeout duration in minutes of ambient mode when plugged in.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String AMBIENT_PLUGGED_TIMEOUT_MIN = "ambient_plugged_timeout_min";
/**
* What OS does paired device has.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String PAIRED_DEVICE_OS_TYPE = "paired_device_os_type";
// Possible values of PAIRED_DEVICE_OS_TYPE
@@ -19686,7 +19686,7 @@ public final class Settings {
* The user's last setting for hfp client.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String USER_HFP_CLIENT_SETTING = "user_hfp_client_setting";
// Possible hfp client user setting values
@@ -19711,7 +19711,7 @@ public final class Settings {
* The companion App name.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String COMPANION_APP_NAME = "wear_companion_app_name";
/**
@@ -19719,21 +19719,21 @@ public final class Settings {
* wear. 1 for supporting, 0 for not supporting.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String ENABLE_ALL_LANGUAGES = "enable_all_languages";
/**
* The Locale (as language tag) the user chose at startup.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String SETUP_LOCALE = "setup_locale";
/**
* The version of oem setup present.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String OEM_SETUP_VERSION = "oem_setup_version";
/**
@@ -19779,7 +19779,7 @@ public final class Settings {
* -{@link BATTERY_SAVER_MODE_CUSTOM}
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String BATTERY_SAVER_MODE = "battery_saver_mode";
/**
@@ -19836,7 +19836,7 @@ public final class Settings {
* If burn in protection is enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String BURN_IN_PROTECTION_ENABLED = "burn_in_protection";
/**
@@ -19855,7 +19855,7 @@ public final class Settings {
* RIGHT_WRIST_ROTATION_0 = "2", RIGHT_WRIST_ROTATION_180 = "3"
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String WRIST_ORIENTATION_MODE = "wear_wrist_orientation_mode";
/**
@@ -19894,7 +19894,7 @@ public final class Settings {
*
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String CLOCKWORK_SYSUI_PACKAGE = "clockwork_sysui_package";
/**
@@ -19924,7 +19924,7 @@ public final class Settings {
* Whether the device has Wet Mode/ Touch Lock Mode enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String WET_MODE_ON = "wet_mode_on";
/**
@@ -19943,7 +19943,7 @@ public final class Settings {
* Whether charging sounds are enabled.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String CHARGING_SOUNDS_ENABLED = "wear_charging_sounds_enabled";
/**
@@ -19952,7 +19952,7 @@ public final class Settings {
*
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String DYNAMIC_COLOR_THEME_ENABLED = "dynamic_color_theme_enabled";
/**
@@ -20044,7 +20044,7 @@ public final class Settings {
* The key to indicate the data migration status on device upgrade in Wear Services.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String UPGRADE_DATA_MIGRATION_STATUS =
"upgrade_data_migration_status";
@@ -20101,20 +20101,20 @@ public final class Settings {
* The custom foreground color.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String CUSTOM_COLOR_FOREGROUND = "custom_foreground_color";
/**
* The custom background color.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String CUSTOM_COLOR_BACKGROUND = "custom_background_color";
/** The status of the phone switching process.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String PHONE_SWITCHING_STATUS = "phone_switching_status";
/**
@@ -20291,7 +20291,7 @@ public final class Settings {
* Controls the launcher ui mode on wearable devices.
* @hide
*/
- @Readable(maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ @Readable
public static final String WEAR_LAUNCHER_UI_MODE = "wear_launcher_ui_mode";
/** Whether Wear Power Anomaly Service is enabled.
diff --git a/core/java/android/security/forensic/ForensicEvent.aidl b/core/java/android/security/forensic/ForensicEvent.aidl
new file mode 100644
index 000000000000..a321fb0cb939
--- /dev/null
+++ b/core/java/android/security/forensic/ForensicEvent.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.forensic;
+
+/** {@hide} */
+parcelable ForensicEvent;
diff --git a/core/java/android/security/forensic/ForensicEvent.java b/core/java/android/security/forensic/ForensicEvent.java
new file mode 100644
index 000000000000..9cbc5ecea962
--- /dev/null
+++ b/core/java/android/security/forensic/ForensicEvent.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.forensic;
+
+import android.annotation.FlaggedApi;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.security.Flags;
+import android.util.ArrayMap;
+
+import java.util.Map;
+
+/**
+ * A class that represents a forensic event.
+ * @hide
+ */
+@FlaggedApi(Flags.FLAG_AFL_API)
+public final class ForensicEvent implements Parcelable {
+ private static final String TAG = "ForensicEvent";
+
+ @NonNull
+ private final String mType;
+
+ @NonNull
+ private final Map<String, String> mKeyValuePairs;
+
+ public static final @NonNull Parcelable.Creator<ForensicEvent> CREATOR =
+ new Parcelable.Creator<>() {
+ public ForensicEvent createFromParcel(Parcel in) {
+ return new ForensicEvent(in);
+ }
+
+ public ForensicEvent[] newArray(int size) {
+ return new ForensicEvent[size];
+ }
+ };
+
+ public ForensicEvent(@NonNull String type, @NonNull Map<String, String> keyValuePairs) {
+ mType = type;
+ mKeyValuePairs = keyValuePairs;
+ }
+
+ private ForensicEvent(@NonNull Parcel in) {
+ mType = in.readString();
+ mKeyValuePairs = new ArrayMap<>(in.readInt());
+ in.readMap(mKeyValuePairs, getClass().getClassLoader(), String.class, String.class);
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel out, int flags) {
+ out.writeString(mType);
+ out.writeInt(mKeyValuePairs.size());
+ out.writeMap(mKeyValuePairs);
+ }
+
+ @FlaggedApi(Flags.FLAG_AFL_API)
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return "ForensicEvent{"
+ + "mType=" + mType
+ + ", mKeyValuePairs=" + mKeyValuePairs
+ + '}';
+ }
+}
diff --git a/core/java/android/security/forensic/IBackupTransport.aidl b/core/java/android/security/forensic/IBackupTransport.aidl
new file mode 100644
index 000000000000..c2cbc83ba1b3
--- /dev/null
+++ b/core/java/android/security/forensic/IBackupTransport.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.forensic;
+import android.security.forensic.ForensicEvent;
+
+import com.android.internal.infra.AndroidFuture;
+
+/** {@hide} */
+oneway interface IBackupTransport {
+ /**
+ * Initialize the server side.
+ */
+ void initialize(in AndroidFuture<int> resultFuture);
+
+ /**
+ * Send forensic logging data to the backup destination.
+ * The data is a list of ForensicEvent.
+ * The ForensicEvent is an abstract class that represents
+ * different type of events.
+ */
+ void addData(in List<ForensicEvent> events, in AndroidFuture<int> resultFuture);
+
+ /**
+ * Release the binder to the server.
+ */
+ void release(in AndroidFuture<int> resultFuture);
+}
diff --git a/core/java/android/security/responsible_apis_flags.aconfig b/core/java/android/security/responsible_apis_flags.aconfig
index b593902a95d4..9bb1039849e5 100644
--- a/core/java/android/security/responsible_apis_flags.aconfig
+++ b/core/java/android/security/responsible_apis_flags.aconfig
@@ -77,4 +77,11 @@ flag {
description: "Prevent intent redirect attacks"
bug: "361143368"
is_fixed_read_only: true
+}
+
+flag {
+ name: "prevent_intent_redirect_abort_or_throw_exception"
+ namespace: "responsible_apis"
+ description: "Prevent intent redirect attacks by aborting or throwing security exception"
+ bug: "361143368"
} \ No newline at end of file
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index ccc17ecccbf9..2e660fc1f157 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -73,6 +73,7 @@ import com.android.internal.infra.AndroidFuture;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
@@ -1513,10 +1514,11 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
"Recognition for the given keyphrase is not supported");
}
- KeyphraseRecognitionExtra[] recognitionExtra = new KeyphraseRecognitionExtra[1];
+ List<KeyphraseRecognitionExtra> recognitionExtra =
+ new ArrayList<KeyphraseRecognitionExtra>(1);
// TODO: Do we need to do something about the confidence level here?
- recognitionExtra[0] = new KeyphraseRecognitionExtra(mKeyphraseMetadata.getId(),
- mKeyphraseMetadata.getRecognitionModeFlags(), 0, new ConfidenceLevel[0]);
+ recognitionExtra.add(new KeyphraseRecognitionExtra(mKeyphraseMetadata.getId(),
+ mKeyphraseMetadata.getRecognitionModeFlags(), 0, new ConfidenceLevel[0]));
boolean captureTriggerAudio =
(recognitionFlags&RECOGNITION_FLAG_CAPTURE_TRIGGER_AUDIO) != 0;
boolean allowMultipleTriggers =
@@ -1534,10 +1536,17 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
int code;
try {
code = mSoundTriggerSession.startRecognition(
- mKeyphraseMetadata.getId(), mLocale.toLanguageTag(), mInternalCallback,
- new RecognitionConfig(captureTriggerAudio, allowMultipleTriggers,
- recognitionExtra, data, audioCapabilities),
- runInBatterySaver);
+ mKeyphraseMetadata.getId(),
+ mLocale.toLanguageTag(),
+ mInternalCallback,
+ new RecognitionConfig.Builder()
+ .setCaptureRequested(captureTriggerAudio)
+ .setAllowMultipleTriggers(allowMultipleTriggers)
+ .setKeyphrases(recognitionExtra)
+ .setData(data)
+ .setAudioCapabilities(audioCapabilities)
+ .build(),
+ runInBatterySaver);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index e8ef9d65a2b4..bce51f297aff 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -1701,6 +1701,11 @@ public class PhoneStateListener {
public final void onCarrierRoamingNtnEligibleStateChanged(boolean eligible) {
// not supported on the deprecated interface - Use TelephonyCallback instead
}
+
+ public final void onCarrierRoamingNtnAvailableServicesChanged(
+ @NetworkRegistrationInfo.ServiceType int[] availableServices) {
+ // not supported on the deprecated interface - Use TelephonyCallback instead
+ }
}
private void log(String s) {
diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java
index 5295b606dd19..46e27dc60adc 100644
--- a/core/java/android/telephony/TelephonyCallback.java
+++ b/core/java/android/telephony/TelephonyCallback.java
@@ -681,6 +681,20 @@ public class TelephonyCallback {
public static final int EVENT_CARRIER_ROAMING_NTN_ELIGIBLE_STATE_CHANGED = 43;
/**
+ * Event for listening to changes in carrier roaming non-terrestrial network available services
+ * via callback onCarrierRoamingNtnAvailableServicesChanged().
+ * This callback is triggered when the available services provided by the carrier roaming
+ * satellite changes. The carrier roaming satellite is defined by the following conditions.
+ * <ul>
+ * <li>Subscription supports attaching to satellite which is defined by
+ * {@link CarrierConfigManager#KEY_SATELLITE_ATTACH_SUPPORTED_BOOL} </li>
+ * </ul>
+ *
+ * @hide
+ */
+ public static final int EVENT_CARRIER_ROAMING_NTN_AVAILABLE_SERVICES_CHANGED = 44;
+
+ /**
* @hide
*/
@IntDef(prefix = {"EVENT_"}, value = {
@@ -726,7 +740,8 @@ public class TelephonyCallback {
EVENT_EMERGENCY_CALLBACK_MODE_CHANGED,
EVENT_SIMULTANEOUS_CELLULAR_CALLING_SUBSCRIPTIONS_CHANGED,
EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED,
- EVENT_CARRIER_ROAMING_NTN_ELIGIBLE_STATE_CHANGED
+ EVENT_CARRIER_ROAMING_NTN_ELIGIBLE_STATE_CHANGED,
+ EVENT_CARRIER_ROAMING_NTN_AVAILABLE_SERVICES_CHANGED
})
@Retention(RetentionPolicy.SOURCE)
public @interface TelephonyEvent {
@@ -1784,6 +1799,15 @@ public class TelephonyCallback {
* </ul>
*/
default void onCarrierRoamingNtnEligibleStateChanged(boolean eligible) {}
+
+ /**
+ * Callback invoked when carrier roaming non-terrestrial network available
+ * service changes.
+ *
+ * @param availableServices The list of the supported services.
+ */
+ default void onCarrierRoamingNtnAvailableServicesChanged(
+ @NetworkRegistrationInfo.ServiceType List<Integer> availableServices) {}
}
/**
@@ -2235,5 +2259,19 @@ public class TelephonyCallback {
Binder.withCleanCallingIdentity(() -> mExecutor.execute(
() -> listener.onCarrierRoamingNtnEligibleStateChanged(eligible)));
}
+
+ public void onCarrierRoamingNtnAvailableServicesChanged(
+ @NetworkRegistrationInfo.ServiceType int[] availableServices) {
+ if (!Flags.carrierRoamingNbIotNtn()) return;
+
+ CarrierRoamingNtnModeListener listener =
+ (CarrierRoamingNtnModeListener) mTelephonyCallbackWeakRef.get();
+ if (listener == null) return;
+
+ List<Integer> ServiceList = Arrays.stream(availableServices).boxed()
+ .collect(Collectors.toList());
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(
+ () -> listener.onCarrierRoamingNtnAvailableServicesChanged(ServiceList)));
+ }
}
}
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 3c7e924f07df..4d50a450490e 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -1118,6 +1118,21 @@ public class TelephonyRegistryManager {
}
/**
+ * Notify external listeners that carrier roaming non-terrestrial available services changed.
+ * @param availableServices The list of the supported services.
+ * @hide
+ */
+ public void notifyCarrierRoamingNtnAvailableServicesChanged(
+ int subId, @NetworkRegistrationInfo.ServiceType int[] availableServices) {
+ try {
+ sRegistry.notifyCarrierRoamingNtnAvailableServicesChanged(subId, availableServices);
+ } catch (RemoteException ex) {
+ // system server crash
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Processes potential event changes from the provided {@link TelephonyCallback}.
*
* @param telephonyCallback callback for monitoring callback changes to the telephony state.
@@ -1272,12 +1287,9 @@ public class TelephonyRegistryManager {
if (telephonyCallback instanceof TelephonyCallback.CarrierRoamingNtnModeListener) {
eventList.add(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED);
- }
-
- if (telephonyCallback instanceof TelephonyCallback.CarrierRoamingNtnModeListener) {
eventList.add(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_ELIGIBLE_STATE_CHANGED);
+ eventList.add(TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_AVAILABLE_SERVICES_CHANGED);
}
-
return eventList;
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 0efded2d0eb9..d57a88075f8a 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -131,6 +131,7 @@ import static android.window.DesktopModeFlags.ENABLE_CAPTION_COMPAT_INSET_FORCE_
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
import static com.android.text.flags.Flags.disableHandwritingInitiatorForIme;
import static com.android.window.flags.Flags.enableBufferTransformHintFromDisplay;
+import static com.android.window.flags.Flags.predictiveBackSwipeEdgeNoneApi;
import static com.android.window.flags.Flags.setScPropertiesInClient;
import static com.android.window.flags.Flags.systemUiImmersiveConfirmationDialog;
@@ -7559,8 +7560,13 @@ public final class ViewRootImpl implements ViewParent,
// - 0 means the button was pressed.
// - 1 means the button continues to be pressed (long press).
if (keyEvent.getRepeatCount() == 0) {
- animationCallback.onBackStarted(
- new BackEvent(0, 0, 0f, BackEvent.EDGE_LEFT));
+ BackEvent backEvent;
+ if (predictiveBackSwipeEdgeNoneApi()) {
+ backEvent = new BackEvent(0, 0, 0f, BackEvent.EDGE_NONE);
+ } else {
+ backEvent = new BackEvent(0, 0, 0f, BackEvent.EDGE_LEFT);
+ }
+ animationCallback.onBackStarted(backEvent);
}
break;
case KeyEvent.ACTION_UP:
diff --git a/core/java/android/window/BackEvent.java b/core/java/android/window/BackEvent.java
index 23e572fcd577..90fac361c966 100644
--- a/core/java/android/window/BackEvent.java
+++ b/core/java/android/window/BackEvent.java
@@ -16,6 +16,7 @@
package android.window;
+import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_SWIPE_EDGE_NONE_API;
import static com.android.window.flags.Flags.FLAG_PREDICTIVE_BACK_TIMESTAMP_API;
import static com.android.window.flags.Flags.predictiveBackTimestampApi;
@@ -37,11 +38,19 @@ public final class BackEvent {
public static final int EDGE_LEFT = 0;
/** Indicates that the edge swipe starts from the right edge of the screen */
public static final int EDGE_RIGHT = 1;
+ /**
+ * Indicates that the back event was not triggered by an edge swipe back gesture. This applies
+ * to cases like using the back button in 3-button navigation or pressing a hardware back
+ * button.
+ */
+ @FlaggedApi(FLAG_PREDICTIVE_BACK_SWIPE_EDGE_NONE_API)
+ public static final int EDGE_NONE = 2;
/** @hide */
@IntDef({
EDGE_LEFT,
EDGE_RIGHT,
+ EDGE_NONE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SwipeEdge{}
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index 0bcc9c1f58c5..a0d58d5a0c76 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -348,3 +348,10 @@ flag {
description: "Enables a switch to change the concequence of dragging a window to the top edge."
bug: "372614715"
}
+
+flag {
+ name: "enable_task_resizing_keyboard_shortcuts"
+ namespace: "lse_desktop_experience"
+ description: "Enables keyboard shortcuts for resizing tasks in desktop mode."
+ bug: "335819608"
+}
diff --git a/core/java/android/window/flags/windowing_frontend.aconfig b/core/java/android/window/flags/windowing_frontend.aconfig
index d15f52c39efa..966e835018f3 100644
--- a/core/java/android/window/flags/windowing_frontend.aconfig
+++ b/core/java/android/window/flags/windowing_frontend.aconfig
@@ -332,3 +332,11 @@ flag {
is_fixed_read_only: true
bug: "362938401"
}
+
+flag {
+ name: "predictive_back_swipe_edge_none_api"
+ namespace: "systemui"
+ description: "EDGE_NONE swipeEdge option in BackEvent"
+ is_fixed_read_only: true
+ bug: "362938401"
+}
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index 6448f10f01b9..003393c337e7 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -230,7 +230,7 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
mRendererWrapper = mSurfaceOnly ? null : renderer;
mMetricsWrapper = mSurfaceOnly ? null : metrics;
mViewRoot = mSurfaceOnly ? null : viewRootWrapper;
- mObserver = mSurfaceOnly
+ mObserver = mSurfaceOnly || (Flags.useSfFrameDuration() && Flags.ignoreHwuiIsFirstFrame())
? null
: new HardwareRendererObserver(this, mMetricsWrapper.getTiming(),
mHandler, /* waitForPresentTime= */ false);
@@ -253,6 +253,7 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
mSurfaceChangedCallback = new ViewRootImpl.SurfaceChangedCallback() {
@Override
public void surfaceCreated(SurfaceControl.Transaction t) {
+ Trace.beginSection("FrameTracker#surfaceCreated");
mHandler.runWithScissors(() -> {
if (mSurfaceControl == null) {
mSurfaceControl = mViewRoot.getSurfaceControl();
@@ -262,6 +263,7 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
}
}
}, EXECUTOR_TASK_TIMEOUT);
+ Trace.endSection();
}
@Override
@@ -464,23 +466,28 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
@Override
public void onJankDataAvailable(SurfaceControl.JankData[] jankData) {
postCallback(() -> {
- if (mCancelled || mMetricsFinalized) {
- return;
- }
-
- for (SurfaceControl.JankData jankStat : jankData) {
- if (!isInRange(jankStat.frameVsyncId)) {
- continue;
+ try {
+ Trace.beginSection("FrameTracker#onJankDataAvailable");
+ if (mCancelled || mMetricsFinalized) {
+ return;
}
- JankInfo info = findJankInfo(jankStat.frameVsyncId);
- if (info != null) {
- info.update(jankStat);
- } else {
- mJankInfos.put((int) jankStat.frameVsyncId,
- JankInfo.createFromSurfaceControlCallback(jankStat));
+
+ for (SurfaceControl.JankData jankStat : jankData) {
+ if (!isInRange(jankStat.frameVsyncId)) {
+ continue;
+ }
+ JankInfo info = findJankInfo(jankStat.frameVsyncId);
+ if (info != null) {
+ info.update(jankStat);
+ } else {
+ mJankInfos.put((int) jankStat.frameVsyncId,
+ JankInfo.createFromSurfaceControlCallback(jankStat));
+ }
}
+ processJankInfos();
+ } finally {
+ Trace.endSection();
}
- processJankInfos();
});
}
@@ -507,29 +514,35 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
@Override
public void onFrameMetricsAvailable(int dropCountSinceLastInvocation) {
postCallback(() -> {
- if (mCancelled || mMetricsFinalized) {
- return;
- }
-
- // Since this callback might come a little bit late after the end() call.
- // We should keep tracking the begin / end timestamp that we can compare with
- // vsync timestamp to check if the frame is in the duration of the CUJ.
- long totalDurationNanos = mMetricsWrapper.getMetric(FrameMetrics.TOTAL_DURATION);
- boolean isFirstFrame = mMetricsWrapper.getMetric(FrameMetrics.FIRST_DRAW_FRAME) == 1;
- long frameVsyncId =
- mMetricsWrapper.getTiming()[FrameMetrics.Index.FRAME_TIMELINE_VSYNC_ID];
+ try {
+ Trace.beginSection("FrameTracker#onFrameMetricsAvailable");
+ if (mCancelled || mMetricsFinalized) {
+ return;
+ }
- if (!isInRange(frameVsyncId)) {
- return;
- }
- JankInfo info = findJankInfo(frameVsyncId);
- if (info != null) {
- info.update(totalDurationNanos, isFirstFrame);
- } else {
- mJankInfos.put((int) frameVsyncId, JankInfo.createFromHwuiCallback(
- frameVsyncId, totalDurationNanos, isFirstFrame));
+ // Since this callback might come a little bit late after the end() call.
+ // We should keep tracking the begin / end timestamp that we can compare with
+ // vsync timestamp to check if the frame is in the duration of the CUJ.
+ long totalDurationNanos = mMetricsWrapper.getMetric(FrameMetrics.TOTAL_DURATION);
+ boolean isFirstFrame =
+ mMetricsWrapper.getMetric(FrameMetrics.FIRST_DRAW_FRAME) == 1;
+ long frameVsyncId =
+ mMetricsWrapper.getTiming()[FrameMetrics.Index.FRAME_TIMELINE_VSYNC_ID];
+
+ if (!isInRange(frameVsyncId)) {
+ return;
+ }
+ JankInfo info = findJankInfo(frameVsyncId);
+ if (info != null) {
+ info.update(totalDurationNanos, isFirstFrame);
+ } else {
+ mJankInfos.put((int) frameVsyncId, JankInfo.createFromHwuiCallback(
+ frameVsyncId, totalDurationNanos, isFirstFrame));
+ }
+ processJankInfos();
+ } finally {
+ Trace.endSection();
}
- processJankInfos();
});
}
@@ -568,13 +581,20 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
}
private boolean callbacksReceived(JankInfo info) {
- return mSurfaceOnly
+ return mObserver == null
? info.surfaceControlCallbackFired
: info.hwuiCallbackFired && info.surfaceControlCallbackFired;
}
@UiThread
private void finish() {
+ Trace.beginSection("FrameTracker#finish");
+ finishTraced();
+ Trace.endSection();
+ }
+
+ @UiThread
+ private void finishTraced() {
if (mMetricsFinalized || mCancelled) return;
mMetricsFinalized = true;
@@ -599,7 +619,7 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
for (int i = 0; i < mJankInfos.size(); i++) {
JankInfo info = mJankInfos.valueAt(i);
final boolean isFirstDrawn = !mSurfaceOnly && info.isFirstFrame;
- if (isFirstDrawn) {
+ if (isFirstDrawn && !Flags.ignoreHwuiIsFirstFrame()) {
continue;
}
if (info.frameVsyncId > mEndVsyncId) {
@@ -636,7 +656,7 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
}
// TODO (b/174755489): Early latch currently gets fired way too often, so we have
// to ignore it for now.
- if (!mSurfaceOnly && !info.hwuiCallbackFired) {
+ if (mObserver != null && !info.hwuiCallbackFired) {
markEvent("FT#MissedHWUICallback", info.frameVsyncId);
Log.w(TAG, "Missing HWUI jank callback for vsyncId: " + info.frameVsyncId
+ ", CUJ=" + name);
@@ -762,7 +782,9 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
* @param observer observer
*/
public void addObserver(HardwareRendererObserver observer) {
- mRenderer.addObserver(observer);
+ if (observer != null) {
+ mRenderer.addObserver(observer);
+ }
}
/**
@@ -770,7 +792,9 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
* @param observer observer
*/
public void removeObserver(HardwareRendererObserver observer) {
- mRenderer.removeObserver(observer);
+ if (observer != null) {
+ mRenderer.removeObserver(observer);
+ }
}
}
diff --git a/core/java/com/android/internal/jank/flags.aconfig b/core/java/com/android/internal/jank/flags.aconfig
index 82f50ae848b3..287ad1856258 100644
--- a/core/java/com/android/internal/jank/flags.aconfig
+++ b/core/java/com/android/internal/jank/flags.aconfig
@@ -8,3 +8,10 @@ flag {
bug: "354763298"
is_fixed_read_only: true
}
+flag {
+ name: "ignore_hwui_is_first_frame"
+ namespace: "window_surfaces"
+ description: "Whether to remove the usage of the HWUI 'is first frame' flag to ignore jank"
+ bug: "354763298"
+ is_fixed_read_only: true
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsHistory.java b/core/java/com/android/internal/os/BatteryStatsHistory.java
index 07aa7206c0e7..b56aadd366d5 100644
--- a/core/java/com/android/internal/os/BatteryStatsHistory.java
+++ b/core/java/com/android/internal/os/BatteryStatsHistory.java
@@ -1770,6 +1770,10 @@ public class BatteryStatsHistory {
@GuardedBy("this")
private void writeHistoryItem(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
+ if (cur.eventCode != HistoryItem.EVENT_NONE && cur.eventTag.string == null) {
+ Slog.wtfStack(TAG, "Event " + Integer.toHexString(cur.eventCode) + " without a name");
+ }
+
if (mTracer != null && mTracer.tracingEnabled()) {
recordTraceEvents(cur.eventCode, cur.eventTag);
recordTraceCounters(mTraceLastState, cur.states, STATE1_TRACE_MASK,
@@ -2266,6 +2270,7 @@ public class BatteryStatsHistory {
private int writeHistoryTag(HistoryTag tag) {
if (tag.string == null) {
Slog.wtfStack(TAG, "writeHistoryTag called with null name");
+ tag.string = "";
}
final int stringLength = tag.string.length();
diff --git a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
index dfb2884044f5..489721fbc10e 100644
--- a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
+++ b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
@@ -105,7 +105,7 @@ public final class LongArrayMultiStateCounter implements Parcelable {
public void setValues(long[] array) {
if (array.length != mLength) {
throw new IllegalArgumentException(
- "Invalid array length: " + mLength + ", expected: " + mLength);
+ "Invalid array length: " + array.length + ", expected: " + mLength);
}
native_setValues(mNativeObject, array);
}
@@ -116,7 +116,7 @@ public final class LongArrayMultiStateCounter implements Parcelable {
public void getValues(long[] array) {
if (array.length != mLength) {
throw new IllegalArgumentException(
- "Invalid array length: " + mLength + ", expected: " + mLength);
+ "Invalid array length: " + array.length + ", expected: " + mLength);
}
native_getValues(mNativeObject, array);
}
@@ -347,6 +347,11 @@ public final class LongArrayMultiStateCounter implements Parcelable {
throw new IllegalArgumentException(
"State: " + state + ", outside the range: [0-" + mStateCount + "]");
}
+ if (longArrayContainer.mLength != mLength) {
+ throw new IllegalArgumentException(
+ "Invalid array length: " + longArrayContainer.mLength
+ + ", expected: " + mLength);
+ }
native_getCounts(mNativeObject, longArrayContainer.mNativeObject, state);
}
diff --git a/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java b/core/java/com/android/internal/os/ProcfsMemoryUtil.java
index 6cb6dc07f8b8..382f6c4a8a16 100644
--- a/services/core/java/com/android/server/stats/pull/ProcfsMemoryUtil.java
+++ b/core/java/com/android/internal/os/ProcfsMemoryUtil.java
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.android.server.stats.pull;
+package com.android.internal.os;
-import static android.os.Process.PROC_OUT_STRING;
+import static android.os.Process.*;
import android.annotation.Nullable;
import android.os.Process;
@@ -23,6 +23,7 @@ import android.util.SparseArray;
public final class ProcfsMemoryUtil {
private static final int[] CMDLINE_OUT = new int[] { PROC_OUT_STRING };
+ private static final int[] OOM_SCORE_ADJ_OUT = new int[] { PROC_NEWLINE_TERM | PROC_OUT_LONG };
private static final String[] STATUS_KEYS = new String[] {
"Uid:",
"VmHWM:",
@@ -38,17 +39,34 @@ public final class ProcfsMemoryUtil {
private ProcfsMemoryUtil() {}
/**
- * Reads memory stats of a process from procfs. Returns values of the VmHWM, VmRss, AnonRSS,
- * VmSwap, RssShmem fields in /proc/pid/status in kilobytes or null if not available.
+ * Reads memory stats of a process from procfs.
+ *
+ * Returns values of the VmHWM, VmRss, AnonRSS, VmSwap, RssShmem fields in
+ * /proc/pid/status in kilobytes or null if not available.
*/
@Nullable
public static MemorySnapshot readMemorySnapshotFromProcfs(int pid) {
+ return readMemorySnapshotFromProcfs("/proc/" + pid + "/status");
+ }
+
+ /**
+ * Reads memory stats of the current process from procfs.
+ *
+ * Returns values of the VmHWM, VmRss, AnonRSS, VmSwap, RssShmem fields in
+ * /proc/self/status in kilobytes or null if not available.
+ */
+ @Nullable
+ public static MemorySnapshot readMemorySnapshotFromProcfs() {
+ return readMemorySnapshotFromProcfs("/proc/self/status");
+ }
+
+ private static MemorySnapshot readMemorySnapshotFromProcfs(String path) {
long[] output = new long[STATUS_KEYS.length];
output[0] = -1;
output[3] = -1;
output[4] = -1;
output[5] = -1;
- Process.readProcLines("/proc/" + pid + "/status", STATUS_KEYS, output);
+ Process.readProcLines(path, STATUS_KEYS, output);
if (output[0] == -1 || output[3] == -1 || output[4] == -1 || output[5] == -1) {
// Could not open or parse file.
return null;
@@ -70,14 +88,54 @@ public final class ProcfsMemoryUtil {
* if the file is not available.
*/
public static String readCmdlineFromProcfs(int pid) {
+ return readCmdlineFromProcfs("/proc/" + pid + "/cmdline");
+ }
+
+ /**
+ * Reads cmdline of the current process from procfs.
+ *
+ * Returns content of /proc/pid/cmdline (e.g. /system/bin/statsd) or an empty string
+ * if the file is not available.
+ */
+ public static String readCmdlineFromProcfs() {
+ return readCmdlineFromProcfs("/proc/self/cmdline");
+ }
+
+ private static String readCmdlineFromProcfs(String path) {
String[] cmdline = new String[1];
- if (!Process.readProcFile("/proc/" + pid + "/cmdline", CMDLINE_OUT, cmdline, null, null)) {
+ if (!Process.readProcFile(path, CMDLINE_OUT, cmdline, null, null)) {
return "";
}
return cmdline[0];
}
/**
+ * Reads oom_score_adj of a process from procfs
+ *
+ * Returns content of /proc/pid/oom_score_adj. Defaults to 0 if reading fails.
+ */
+ public static int readOomScoreAdjFromProcfs(int pid) {
+ return readOomScoreAdjFromProcfs("/proc/" + pid + "/oom_score_adj");
+ }
+
+ /**
+ * Reads oom_score_adj of the current process from procfs
+ *
+ * Returns content of /proc/pid/oom_score_adj. Defaults to 0 if reading fails.
+ */
+ public static int readOomScoreAdjFromProcfs() {
+ return readOomScoreAdjFromProcfs("/proc/self/oom_score_adj");
+ }
+
+ private static int readOomScoreAdjFromProcfs(String path) {
+ long[] oom_score_adj = new long[1];
+ if (Process.readProcFile(path, OOM_SCORE_ADJ_OUT, null, oom_score_adj, null)) {
+ return (int)oom_score_adj[0];
+ }
+ return 0;
+ }
+
+ /**
* Scans all /proc/pid/cmdline entries and returns a mapping between pid and cmdline.
*/
public static SparseArray<String> getProcessCmdlines() {
@@ -109,7 +167,7 @@ public final class ProcfsMemoryUtil {
/** Reads and parses selected entries of /proc/vmstat. */
@Nullable
- static VmStat readVmStat() {
+ public static VmStat readVmStat() {
long[] vmstat = new long[VMSTAT_KEYS.length];
vmstat[0] = -1;
Process.readProcLines("/proc/vmstat", VMSTAT_KEYS, vmstat);
@@ -121,7 +179,7 @@ public final class ProcfsMemoryUtil {
return result;
}
- static final class VmStat {
+ public static final class VmStat {
public int oomKillCount;
}
}
diff --git a/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java b/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java
index b42ea7d0b769..e2237f61dfbb 100644
--- a/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java
+++ b/core/java/com/android/internal/os/logging/MetricsLoggerWrapper.java
@@ -16,9 +16,15 @@
package com.android.internal.os.logging;
+import android.app.Application;
+import android.os.Process;
+import android.util.Log;
import android.view.WindowManager.LayoutParams;
+import com.android.internal.os.ProcfsMemoryUtil;
import com.android.internal.util.FrameworkStatsLog;
+import java.util.Collection;
+import libcore.util.NativeAllocationRegistry;
/**
* Used to wrap different logging calls in one, so that client side code base is clean and more
@@ -49,4 +55,46 @@ public class MetricsLoggerWrapper {
}
}
}
+
+ public static void logPostGcMemorySnapshot() {
+ if (!com.android.libcore.Flags.nativeMetrics()) {
+ return;
+ }
+ int pid = Process.myPid();
+ String processName = Application.getProcessName();
+ Collection<NativeAllocationRegistry.Metrics> metrics =
+ NativeAllocationRegistry.getMetrics();
+ int nMetrics = metrics.size();
+
+ String[] classNames = new String[nMetrics];
+ long[] mallocedCount = new long[nMetrics];
+ long[] mallocedBytes = new long[nMetrics];
+ long[] nonmallocedCount = new long[nMetrics];
+ long[] nonmallocedBytes = new long[nMetrics];
+
+ int i = 0;
+ for (NativeAllocationRegistry.Metrics m : metrics) {
+ classNames[i] = m.getClassName();
+ mallocedCount[i] = m.getMallocedCount();
+ mallocedBytes[i] = m.getMallocedBytes();
+ nonmallocedCount[i] = m.getNonmallocedCount();
+ nonmallocedBytes[i] = m.getNonmallocedBytes();
+ i++;
+ }
+
+ ProcfsMemoryUtil.MemorySnapshot m = ProcfsMemoryUtil.readMemorySnapshotFromProcfs();
+ int oom_score_adj = ProcfsMemoryUtil.readOomScoreAdjFromProcfs();
+ FrameworkStatsLog.write(FrameworkStatsLog.POSTGC_MEMORY_SNAPSHOT,
+ m.uid, processName, pid,
+ oom_score_adj,
+ m.rssInKilobytes,
+ m.anonRssInKilobytes,
+ m.swapInKilobytes,
+ m.anonRssInKilobytes + m.swapInKilobytes,
+ classNames,
+ mallocedCount,
+ mallocedBytes,
+ nonmallocedCount,
+ nonmallocedBytes);
+ }
}
diff --git a/core/java/com/android/internal/protolog/AutoClosableProtoInputStream.java b/core/java/com/android/internal/protolog/AutoClosableProtoInputStream.java
new file mode 100644
index 000000000000..1acb34f73002
--- /dev/null
+++ b/core/java/com/android/internal/protolog/AutoClosableProtoInputStream.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.protolog;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.proto.ProtoInputStream;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+
+public final class AutoClosableProtoInputStream implements AutoCloseable {
+ @NonNull
+ private final ProtoInputStream mProtoInputStream;
+ @Nullable
+ private final FileInputStream mFileInputStream;
+
+ public AutoClosableProtoInputStream(@NonNull FileInputStream fileInputStream) {
+ mProtoInputStream = new ProtoInputStream(fileInputStream);
+ mFileInputStream = fileInputStream;
+ }
+
+ public AutoClosableProtoInputStream(@NonNull byte[] input) {
+ mProtoInputStream = new ProtoInputStream(input);
+ mFileInputStream = null;
+ }
+
+ /**
+ * @return the ProtoInputStream this class is wrapping
+ */
+ @NonNull
+ public ProtoInputStream get() {
+ return mProtoInputStream;
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (mFileInputStream != null) {
+ mFileInputStream.close();
+ }
+ }
+}
diff --git a/core/java/com/android/internal/protolog/NoViewerConfigProtoLogImpl.java b/core/java/com/android/internal/protolog/NoViewerConfigProtoLogImpl.java
new file mode 100644
index 000000000000..1598766412dd
--- /dev/null
+++ b/core/java/com/android/internal/protolog/NoViewerConfigProtoLogImpl.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.protolog;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.protolog.common.ILogger;
+import com.android.internal.protolog.common.IProtoLog;
+import com.android.internal.protolog.common.IProtoLogGroup;
+import com.android.internal.protolog.common.LogLevel;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Class should only be used as a temporary solution to missing viewer config file on device.
+ * In particular this class should only be initialized in Robolectric tests, if it's being used
+ * otherwise please report it.
+ *
+ * @deprecated
+ */
+@Deprecated
+public class NoViewerConfigProtoLogImpl implements IProtoLog {
+ private static final String LOG_TAG = "ProtoLog";
+
+ @Override
+ public void log(LogLevel logLevel, IProtoLogGroup group, long messageHash, int paramsMask,
+ Object[] args) {
+ Log.w(LOG_TAG, "ProtoLogging is not available due to missing viewer config file...");
+ logMessage(logLevel, group.getTag(), "PROTOLOG#" + messageHash + "("
+ + Arrays.stream(args).map(Object::toString).collect(Collectors.joining()) + ")");
+ }
+
+ @Override
+ public void log(LogLevel logLevel, IProtoLogGroup group, String messageString, Object... args) {
+ logMessage(logLevel, group.getTag(), TextUtils.formatSimple(messageString, args));
+ }
+
+ @Override
+ public boolean isProtoEnabled() {
+ return false;
+ }
+
+ @Override
+ public int startLoggingToLogcat(String[] groups, ILogger logger) {
+ return 0;
+ }
+
+ @Override
+ public int stopLoggingToLogcat(String[] groups, ILogger logger) {
+ return 0;
+ }
+
+ @Override
+ public boolean isEnabled(IProtoLogGroup group, LogLevel level) {
+ return false;
+ }
+
+ @Override
+ public List<IProtoLogGroup> getRegisteredGroups() {
+ return List.of();
+ }
+
+ private void logMessage(LogLevel logLevel, String tag, String message) {
+ switch (logLevel) {
+ case VERBOSE -> Log.v(tag, message);
+ case INFO -> Log.i(tag, message);
+ case DEBUG -> Log.d(tag, message);
+ case WARN -> Log.w(tag, message);
+ case ERROR -> Log.e(tag, message);
+ case WTF -> Log.wtf(tag, message);
+ }
+ }
+}
diff --git a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
index a037cb421b0c..a1c987f79304 100644
--- a/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/PerfettoProtoLogImpl.java
@@ -60,18 +60,16 @@ import android.util.ArraySet;
import android.util.Log;
import android.util.LongArray;
import android.util.Slog;
-import android.util.proto.ProtoInputStream;
import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.ProtoLogConfigurationServiceImpl.RegisterClientArgs;
import com.android.internal.protolog.common.ILogger;
import com.android.internal.protolog.common.IProtoLog;
import com.android.internal.protolog.common.IProtoLogGroup;
import com.android.internal.protolog.common.LogDataType;
import com.android.internal.protolog.common.LogLevel;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
@@ -93,26 +91,18 @@ import java.util.stream.Stream;
/**
* A service for the ProtoLog logging system.
*/
-public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProtoLog {
+public abstract class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProtoLog {
private static final String LOG_TAG = "ProtoLog";
public static final String NULL_STRING = "null";
private final AtomicInteger mTracingInstances = new AtomicInteger();
@NonNull
- private final ProtoLogDataSource mDataSource;
- @Nullable
- private final ProtoLogViewerConfigReader mViewerConfigReader;
- @Deprecated
- @Nullable
- private final ViewerConfigInputStreamProvider mViewerConfigInputStreamProvider;
+ protected final ProtoLogDataSource mDataSource;
@NonNull
- private final TreeMap<String, IProtoLogGroup> mLogGroups = new TreeMap<>();
+ protected final TreeMap<String, IProtoLogGroup> mLogGroups = new TreeMap<>();
@NonNull
private final Runnable mCacheUpdater;
- @Nullable // null when the flag android.tracing.client_side_proto_logging is not flipped
- private final IProtoLogConfigurationService mProtoLogConfigurationService;
-
@NonNull
private final int[] mDefaultLogLevelCounts = new int[LogLevel.values().length];
@NonNull
@@ -121,68 +111,15 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto
private final Map<String, Integer> mCollectStackTraceGroupCounts = new ArrayMap<>();
private final Lock mBackgroundServiceLock = new ReentrantLock();
- private ExecutorService mBackgroundLoggingService = Executors.newSingleThreadExecutor();
-
- public PerfettoProtoLogImpl(@NonNull IProtoLogGroup[] groups)
- throws ServiceManager.ServiceNotFoundException {
- this(null, null, null, () -> {}, groups);
- }
-
- public PerfettoProtoLogImpl(@NonNull Runnable cacheUpdater, @NonNull IProtoLogGroup[] groups)
- throws ServiceManager.ServiceNotFoundException {
- this(null, null, null, cacheUpdater, groups);
- }
-
- public PerfettoProtoLogImpl(
- @NonNull String viewerConfigFilePath,
- @NonNull Runnable cacheUpdater,
- @NonNull IProtoLogGroup[] groups) throws ServiceManager.ServiceNotFoundException {
- this(viewerConfigFilePath,
- null,
- new ProtoLogViewerConfigReader(() -> {
- try {
- return new ProtoInputStream(new FileInputStream(viewerConfigFilePath));
- } catch (FileNotFoundException e) {
- throw new RuntimeException(
- "Failed to load viewer config file " + viewerConfigFilePath, e);
- }
- }),
- cacheUpdater, groups);
- }
-
- @Deprecated
- @VisibleForTesting
- public PerfettoProtoLogImpl(
- @Nullable ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
- @Nullable ProtoLogViewerConfigReader viewerConfigReader,
- @NonNull Runnable cacheUpdater,
- @NonNull IProtoLogGroup[] groups,
- @NonNull ProtoLogDataSourceBuilder dataSourceBuilder,
- @NonNull ProtoLogConfigurationService configurationService) {
- this(null, viewerConfigInputStreamProvider, viewerConfigReader, cacheUpdater,
- groups, dataSourceBuilder, configurationService);
- }
+ protected ExecutorService mBackgroundLoggingService = Executors.newSingleThreadExecutor();
- @VisibleForTesting
- public PerfettoProtoLogImpl(
- @Nullable String viewerConfigFilePath,
- @Nullable ProtoLogViewerConfigReader viewerConfigReader,
- @NonNull Runnable cacheUpdater,
- @NonNull IProtoLogGroup[] groups,
- @NonNull ProtoLogDataSourceBuilder dataSourceBuilder,
- @NonNull ProtoLogConfigurationService configurationService) {
- this(viewerConfigFilePath, null, viewerConfigReader, cacheUpdater,
- groups, dataSourceBuilder, configurationService);
- }
+ // Set to true once this is ready to accept protolog to logcat requests.
+ private boolean mLogcatReady = false;
- private PerfettoProtoLogImpl(
- @Nullable String viewerConfigFilePath,
- @Nullable ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
- @Nullable ProtoLogViewerConfigReader viewerConfigReader,
+ protected PerfettoProtoLogImpl(
@NonNull Runnable cacheUpdater,
@NonNull IProtoLogGroup[] groups) throws ServiceManager.ServiceNotFoundException {
- this(viewerConfigFilePath, viewerConfigInputStreamProvider, viewerConfigReader,
- cacheUpdater, groups,
+ this(cacheUpdater, groups,
ProtoLogDataSource::new,
android.tracing.Flags.clientSideProtoLogging() ?
IProtoLogConfigurationService.Stub.asInterface(
@@ -191,19 +128,11 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto
);
}
- private PerfettoProtoLogImpl(
- @Nullable String viewerConfigFilePath,
- @Nullable ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
- @Nullable ProtoLogViewerConfigReader viewerConfigReader,
+ protected PerfettoProtoLogImpl(
@NonNull Runnable cacheUpdater,
@NonNull IProtoLogGroup[] groups,
@NonNull ProtoLogDataSourceBuilder dataSourceBuilder,
@Nullable IProtoLogConfigurationService configurationService) {
- if (viewerConfigFilePath != null && viewerConfigInputStreamProvider != null) {
- throw new RuntimeException("Only one of viewerConfigFilePath and "
- + "viewerConfigInputStreamProvider can be set");
- }
-
mDataSource = dataSourceBuilder.build(
this::onTracingInstanceStart,
this::onTracingFlush,
@@ -219,55 +148,33 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto
// for some messages logged right after the construction of this class.
mDataSource.register(params);
- if (viewerConfigInputStreamProvider == null && viewerConfigFilePath != null) {
- viewerConfigInputStreamProvider = new ViewerConfigInputStreamProvider() {
- @NonNull
- @Override
- public ProtoInputStream getInputStream() {
- try {
- return new ProtoInputStream(new FileInputStream(viewerConfigFilePath));
- } catch (FileNotFoundException e) {
- throw new RuntimeException(
- "Failed to load viewer config file " + viewerConfigFilePath, e);
- }
- }
- };
- }
-
- this.mViewerConfigInputStreamProvider = viewerConfigInputStreamProvider;
- this.mViewerConfigReader = viewerConfigReader;
this.mCacheUpdater = cacheUpdater;
registerGroupsLocally(groups);
if (android.tracing.Flags.clientSideProtoLogging()) {
- mProtoLogConfigurationService = configurationService;
- Objects.requireNonNull(mProtoLogConfigurationService,
+ Objects.requireNonNull(configurationService,
"A null ProtoLog Configuration Service was provided!");
try {
- var args = new ProtoLogConfigurationServiceImpl.RegisterClientArgs();
-
- if (viewerConfigFilePath != null) {
- args.setViewerConfigFile(viewerConfigFilePath);
- }
+ var args = createConfigurationServiceRegisterClientArgs();
final var groupArgs = Stream.of(groups)
- .map(group -> new ProtoLogConfigurationServiceImpl.RegisterClientArgs
+ .map(group -> new RegisterClientArgs
.GroupConfig(group.name(), group.isLogToLogcat()))
- .toArray(ProtoLogConfigurationServiceImpl
- .RegisterClientArgs.GroupConfig[]::new);
+ .toArray(RegisterClientArgs.GroupConfig[]::new);
args.setGroups(groupArgs);
- mProtoLogConfigurationService.registerClient(this, args);
+ configurationService.registerClient(this, args);
} catch (RemoteException e) {
throw new RuntimeException("Failed to register ProtoLog client");
}
- } else {
- mProtoLogConfigurationService = null;
}
}
+ @NonNull
+ protected abstract RegisterClientArgs createConfigurationServiceRegisterClientArgs();
+
/**
* Main log method, do not call directly.
*/
@@ -334,9 +241,6 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto
* @return status code
*/
public int startLoggingToLogcat(String[] groups, @NonNull ILogger logger) {
- if (mViewerConfigReader != null) {
- mViewerConfigReader.loadViewerConfig(groups, logger);
- }
return setTextLogging(true, logger, groups);
}
@@ -347,9 +251,6 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto
* @return status code
*/
public int stopLoggingToLogcat(String[] groups, @NonNull ILogger logger) {
- if (mViewerConfigReader != null) {
- mViewerConfigReader.unloadViewerConfig(groups, logger);
- }
return setTextLogging(false, logger, groups);
}
@@ -372,21 +273,8 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto
// we might want to manually specify an id for the group with a collision
verifyNoCollisionsOrDuplicates(protoLogGroups);
- final var groupsLoggingToLogcat = new ArrayList<String>();
for (IProtoLogGroup protoLogGroup : protoLogGroups) {
mLogGroups.put(protoLogGroup.name(), protoLogGroup);
-
- if (protoLogGroup.isLogToLogcat()) {
- groupsLoggingToLogcat.add(protoLogGroup.name());
- }
- }
-
- if (mViewerConfigReader != null) {
- // Load in background to avoid delay in boot process.
- // The caveat is that any log message that is also logged to logcat will not be
- // successfully decoded until this completes.
- mBackgroundLoggingService.execute(() -> mViewerConfigReader
- .loadViewerConfig(groupsLoggingToLogcat.toArray(new String[0])));
}
}
@@ -403,6 +291,10 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto
}
}
+ protected void readyToLogToLogcat() {
+ mLogcatReady = true;
+ }
+
/**
* Responds to a shell command.
*/
@@ -499,57 +391,21 @@ public class PerfettoProtoLogImpl extends IProtoLogClient.Stub implements IProto
}
@Deprecated
- private void dumpViewerConfig() {
- if (mViewerConfigInputStreamProvider == null) {
- // No viewer config available
- return;
- }
-
- Log.d(LOG_TAG, "Dumping viewer config to trace");
+ abstract void dumpViewerConfig();
- Utils.dumpViewerConfig(mDataSource, mViewerConfigInputStreamProvider);
-
- Log.d(LOG_TAG, "Dumped viewer config to trace");
- }
+ @NonNull
+ abstract String getLogcatMessageString(@NonNull Message message);
- private void logToLogcat(String tag, LogLevel level, Message message,
+ private void logToLogcat(@NonNull String tag, @NonNull LogLevel level, @NonNull Message message,
@Nullable Object[] args) {
- String messageString;
- if (mViewerConfigReader == null) {
- messageString = message.getMessage();
-
- if (messageString == null) {
- Log.e(LOG_TAG, "Failed to decode message for logcat. "
- + "Message not available without ViewerConfig to decode the hash.");
- }
- } else {
- messageString = message.getMessage(mViewerConfigReader);
-
- if (messageString == null) {
- Log.e(LOG_TAG, "Failed to decode message for logcat. "
- + "Message hash either not available in viewerConfig file or "
- + "not loaded into memory from file before decoding.");
- }
- }
-
- if (messageString == null) {
- StringBuilder builder = new StringBuilder("UNKNOWN MESSAGE");
- if (args != null) {
- builder.append(" args = (");
- builder.append(String.join(", ", Arrays.stream(args)
- .map(it -> {
- if (it == null) {
- return "null";
- } else {
- return it.toString();
- }
- }).toList()));
- builder.append(")");
- }
- messageString = builder.toString();
- args = new Object[0];
+ if (!mLogcatReady) {
+ Log.w(LOG_TAG, "Trying to log a protolog message with hash "
+ + message.getMessageHash() + " to logcat before the service is ready to accept "
+ + "such requests.");
+ return;
}
+ String messageString = getLogcatMessageString(message);
logToLogcat(tag, level, messageString, args);
}
diff --git a/core/java/com/android/internal/protolog/ProcessedPerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/ProcessedPerfettoProtoLogImpl.java
new file mode 100644
index 000000000000..febe1f3a72ac
--- /dev/null
+++ b/core/java/com/android/internal/protolog/ProcessedPerfettoProtoLogImpl.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.protolog;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.ProtoLogConfigurationServiceImpl.RegisterClientArgs;
+import com.android.internal.protolog.common.ILogger;
+import com.android.internal.protolog.common.IProtoLogGroup;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+
+public class ProcessedPerfettoProtoLogImpl extends PerfettoProtoLogImpl {
+ private static final String LOG_TAG = "PerfettoProtoLogImpl";
+
+ @NonNull
+ private final ProtoLogViewerConfigReader mViewerConfigReader;
+ @Deprecated
+ @NonNull
+ private final ViewerConfigInputStreamProvider mViewerConfigInputStreamProvider;
+ @NonNull
+ private final String mViewerConfigFilePath;
+
+ public ProcessedPerfettoProtoLogImpl(
+ @NonNull String viewerConfigFilePath,
+ @NonNull Runnable cacheUpdater,
+ @NonNull IProtoLogGroup[] groups) throws ServiceManager.ServiceNotFoundException {
+ this(viewerConfigFilePath, new ViewerConfigInputStreamProvider() {
+ @NonNull
+ @Override
+ public AutoClosableProtoInputStream getInputStream() {
+ try {
+ final var protoFileInputStream =
+ new FileInputStream(viewerConfigFilePath);
+ return new AutoClosableProtoInputStream(protoFileInputStream);
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(
+ "Failed to load viewer config file " + viewerConfigFilePath, e);
+ }
+ }
+ },
+ cacheUpdater, groups);
+ }
+
+ @VisibleForTesting
+ public ProcessedPerfettoProtoLogImpl(
+ @NonNull String viewerConfigFilePath,
+ @NonNull ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
+ @NonNull Runnable cacheUpdater,
+ @NonNull IProtoLogGroup[] groups) throws ServiceManager.ServiceNotFoundException {
+ super(cacheUpdater, groups);
+
+ this.mViewerConfigFilePath = viewerConfigFilePath;
+
+ this.mViewerConfigInputStreamProvider = viewerConfigInputStreamProvider;
+ this.mViewerConfigReader = new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider);
+
+ loadLogcatGroupsViewerConfig(groups);
+ }
+
+ @VisibleForTesting
+ public ProcessedPerfettoProtoLogImpl(
+ @NonNull String viewerConfigFilePath,
+ @NonNull ViewerConfigInputStreamProvider viewerConfigInputStreamProvider,
+ @NonNull ProtoLogViewerConfigReader viewerConfigReader,
+ @NonNull Runnable cacheUpdater,
+ @NonNull IProtoLogGroup[] groups,
+ @NonNull ProtoLogDataSourceBuilder dataSourceBuilder,
+ @Nullable IProtoLogConfigurationService configurationService)
+ throws ServiceManager.ServiceNotFoundException {
+ super(cacheUpdater, groups, dataSourceBuilder, configurationService);
+
+ this.mViewerConfigFilePath = viewerConfigFilePath;
+
+ this.mViewerConfigInputStreamProvider = viewerConfigInputStreamProvider;
+ this.mViewerConfigReader = viewerConfigReader;
+
+ loadLogcatGroupsViewerConfig(groups);
+ }
+
+ @NonNull
+ @Override
+ protected RegisterClientArgs createConfigurationServiceRegisterClientArgs() {
+ return new RegisterClientArgs()
+ .setViewerConfigFile(mViewerConfigFilePath);
+ }
+
+ /**
+ * Start text logging
+ * @param groups Groups to start text logging for
+ * @param logger A logger to write status updates to
+ * @return status code
+ */
+ @Override
+ public int startLoggingToLogcat(String[] groups, @NonNull ILogger logger) {
+ mViewerConfigReader.loadViewerConfig(groups, logger);
+ return super.startLoggingToLogcat(groups, logger);
+ }
+
+ /**
+ * Stop text logging
+ * @param groups Groups to start text logging for
+ * @param logger A logger to write status updates to
+ * @return status code
+ */
+ @Override
+ public int stopLoggingToLogcat(String[] groups, @NonNull ILogger logger) {
+ mViewerConfigReader.unloadViewerConfig(groups, logger);
+ return super.stopLoggingToLogcat(groups, logger);
+ }
+
+ @Deprecated
+ @Override
+ void dumpViewerConfig() {
+ Log.d(LOG_TAG, "Dumping viewer config to trace");
+ Utils.dumpViewerConfig(mDataSource, mViewerConfigInputStreamProvider);
+ Log.d(LOG_TAG, "Dumped viewer config to trace");
+ }
+
+ @NonNull
+ @Override
+ String getLogcatMessageString(@NonNull Message message) {
+ String messageString;
+ messageString = message.getMessage(mViewerConfigReader);
+
+ if (messageString == null) {
+ throw new RuntimeException("Failed to decode message for logcat. "
+ + "Message hash (" + message.getMessageHash() + ") either not available in "
+ + "viewerConfig file (" + mViewerConfigFilePath + ") or "
+ + "not loaded into memory from file before decoding.");
+ }
+
+ return messageString;
+ }
+
+ private void loadLogcatGroupsViewerConfig(@NonNull IProtoLogGroup[] protoLogGroups) {
+ final var groupsLoggingToLogcat = new ArrayList<String>();
+ for (IProtoLogGroup protoLogGroup : protoLogGroups) {
+ if (protoLogGroup.isLogToLogcat()) {
+ groupsLoggingToLogcat.add(protoLogGroup.name());
+ }
+ }
+
+ // Load in background to avoid delay in boot process.
+ // The caveat is that any log message that is also logged to logcat will not be
+ // successfully decoded until this completes.
+ mBackgroundLoggingService.execute(() -> {
+ mViewerConfigReader.loadViewerConfig(groupsLoggingToLogcat.toArray(new String[0]));
+ readyToLogToLogcat();
+ });
+ }
+}
diff --git a/core/java/com/android/internal/protolog/ProtoLog.java b/core/java/com/android/internal/protolog/ProtoLog.java
index 60213b1830c6..d117e93d7de7 100644
--- a/core/java/com/android/internal/protolog/ProtoLog.java
+++ b/core/java/com/android/internal/protolog/ProtoLog.java
@@ -70,16 +70,16 @@ public class ProtoLog {
// directly to the generated tracing implementations.
if (android.tracing.Flags.perfettoProtologTracing()) {
synchronized (sInitLock) {
+ final var allGroups = new HashSet<>(Arrays.stream(groups).toList());
if (sProtoLogInstance != null) {
// The ProtoLog instance has already been initialized in this process
final var alreadyRegisteredGroups = sProtoLogInstance.getRegisteredGroups();
- final var allGroups = new HashSet<>(alreadyRegisteredGroups);
- allGroups.addAll(Arrays.stream(groups).toList());
- groups = allGroups.toArray(new IProtoLogGroup[0]);
+ allGroups.addAll(alreadyRegisteredGroups);
}
try {
- sProtoLogInstance = new PerfettoProtoLogImpl(groups);
+ sProtoLogInstance = new UnprocessedPerfettoProtoLogImpl(
+ allGroups.toArray(new IProtoLogGroup[0]));
} catch (ServiceManager.ServiceNotFoundException e) {
throw new RuntimeException(e);
}
diff --git a/core/java/com/android/internal/protolog/ProtoLogConfigurationServiceImpl.java b/core/java/com/android/internal/protolog/ProtoLogConfigurationServiceImpl.java
index 8d37899f8602..e9a8770deb73 100644
--- a/core/java/com/android/internal/protolog/ProtoLogConfigurationServiceImpl.java
+++ b/core/java/com/android/internal/protolog/ProtoLogConfigurationServiceImpl.java
@@ -379,7 +379,7 @@ public class ProtoLogConfigurationServiceImpl extends IProtoLogConfigurationServ
@NonNull String viewerConfigFilePath) {
Utils.dumpViewerConfig(dataSource, () -> {
try {
- return new ProtoInputStream(new FileInputStream(viewerConfigFilePath));
+ return new AutoClosableProtoInputStream(new FileInputStream(viewerConfigFilePath));
} catch (FileNotFoundException e) {
throw new RuntimeException(
"Failed to load viewer config file " + viewerConfigFilePath, e);
diff --git a/core/java/com/android/internal/protolog/ProtoLogImpl.java b/core/java/com/android/internal/protolog/ProtoLogImpl.java
index 5d67534b1b44..3378d08e7761 100644
--- a/core/java/com/android/internal/protolog/ProtoLogImpl.java
+++ b/core/java/com/android/internal/protolog/ProtoLogImpl.java
@@ -105,31 +105,10 @@ public class ProtoLogImpl {
+ "viewerConfigPath = " + sViewerConfigPath);
final var groups = sLogGroups.values().toArray(new IProtoLogGroup[0]);
-
if (android.tracing.Flags.perfettoProtologTracing()) {
- try {
- File f = new File(sViewerConfigPath);
- if (!ProtoLog.REQUIRE_PROTOLOGTOOL && !f.exists()) {
- // TODO(b/353530422): Remove - temporary fix to unblock b/352290057
- // In some tests the viewer config file might not exist in which we don't
- // want to provide config path to the user
- Log.w(LOG_TAG, "Failed to find viewerConfigFile when setting up "
- + ProtoLogImpl.class.getSimpleName() + ". "
- + "Setting up without a viewer config instead...");
-
- sServiceInstance = new PerfettoProtoLogImpl(sCacheUpdater, groups);
- } else {
- sServiceInstance =
- new PerfettoProtoLogImpl(sViewerConfigPath, sCacheUpdater, groups);
- }
- } catch (ServiceManager.ServiceNotFoundException e) {
- throw new RuntimeException(e);
- }
+ sServiceInstance = createProtoLogImpl(groups);
} else {
- var protologImpl = new LegacyProtoLogImpl(
- sLegacyOutputFilePath, sLegacyViewerConfigPath, sCacheUpdater);
- protologImpl.registerGroups(groups);
- sServiceInstance = protologImpl;
+ sServiceInstance = createLegacyProtoLogImpl(groups);
}
sCacheUpdater.run();
@@ -137,6 +116,34 @@ public class ProtoLogImpl {
return sServiceInstance;
}
+ private static IProtoLog createProtoLogImpl(IProtoLogGroup[] groups) {
+ try {
+ File f = new File(sViewerConfigPath);
+ if (!f.exists()) {
+ // TODO(b/353530422): Remove - temporary fix to unblock b/352290057
+ // In robolectric tests the viewer config file isn't current available, so we cannot
+ // use the ProcessedPerfettoProtoLogImpl.
+ Log.e(LOG_TAG, "Failed to find viewer config file " + sViewerConfigPath
+ + " when setting up " + ProtoLogImpl.class.getSimpleName() + ". "
+ + "ProtoLog will not work here!");
+
+ return new NoViewerConfigProtoLogImpl();
+ } else {
+ return new ProcessedPerfettoProtoLogImpl(sViewerConfigPath, sCacheUpdater, groups);
+ }
+ } catch (ServiceManager.ServiceNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static LegacyProtoLogImpl createLegacyProtoLogImpl(IProtoLogGroup[] groups) {
+ var protologImpl = new LegacyProtoLogImpl(
+ sLegacyOutputFilePath, sLegacyViewerConfigPath, sCacheUpdater);
+ protologImpl.registerGroups(groups);
+
+ return protologImpl;
+ }
+
@VisibleForTesting
public static synchronized void setSingleInstance(@Nullable IProtoLog instance) {
sServiceInstance = instance;
diff --git a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
index 571fe0ba37b2..524f64225084 100644
--- a/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
+++ b/core/java/com/android/internal/protolog/ProtoLogViewerConfigReader.java
@@ -106,46 +106,47 @@ public class ProtoLogViewerConfigReader {
long targetGroupId = loadGroupId(group);
final Map<Long, String> hashesForGroup = new TreeMap<>();
- final ProtoInputStream pis = mViewerConfigInputStreamProvider.getInputStream();
-
- while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
- if (pis.getFieldNumber() == (int) MESSAGES) {
- final long inMessageToken = pis.start(MESSAGES);
-
- long messageId = 0;
- String message = null;
- int groupId = 0;
- while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
- switch (pis.getFieldNumber()) {
- case (int) MESSAGE_ID:
- messageId = pis.readLong(MESSAGE_ID);
- break;
- case (int) MESSAGE:
- message = pis.readString(MESSAGE);
- break;
- case (int) GROUP_ID:
- groupId = pis.readInt(GROUP_ID);
- break;
+ try (var pisWrapper = mViewerConfigInputStreamProvider.getInputStream()) {
+ final var pis = pisWrapper.get();
+ while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+ if (pis.getFieldNumber() == (int) MESSAGES) {
+ final long inMessageToken = pis.start(MESSAGES);
+
+ long messageId = 0;
+ String message = null;
+ int groupId = 0;
+ while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+ switch (pis.getFieldNumber()) {
+ case (int) MESSAGE_ID:
+ messageId = pis.readLong(MESSAGE_ID);
+ break;
+ case (int) MESSAGE:
+ message = pis.readString(MESSAGE);
+ break;
+ case (int) GROUP_ID:
+ groupId = pis.readInt(GROUP_ID);
+ break;
+ }
}
- }
- if (groupId == 0) {
- throw new IOException("Failed to get group id");
- }
+ if (groupId == 0) {
+ throw new IOException("Failed to get group id");
+ }
- if (messageId == 0) {
- throw new IOException("Failed to get message id");
- }
+ if (messageId == 0) {
+ throw new IOException("Failed to get message id");
+ }
- if (message == null) {
- throw new IOException("Failed to get message string");
- }
+ if (message == null) {
+ throw new IOException("Failed to get message string");
+ }
- if (groupId == targetGroupId) {
- hashesForGroup.put(messageId, message);
- }
+ if (groupId == targetGroupId) {
+ hashesForGroup.put(messageId, message);
+ }
- pis.end(inMessageToken);
+ pis.end(inMessageToken);
+ }
}
}
@@ -153,30 +154,32 @@ public class ProtoLogViewerConfigReader {
}
private long loadGroupId(@NonNull String group) throws IOException {
- final ProtoInputStream pis = mViewerConfigInputStreamProvider.getInputStream();
-
- while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
- if (pis.getFieldNumber() == (int) GROUPS) {
- final long inMessageToken = pis.start(GROUPS);
-
- long groupId = 0;
- String groupName = null;
- while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
- switch (pis.getFieldNumber()) {
- case (int) ID:
- groupId = pis.readInt(ID);
- break;
- case (int) NAME:
- groupName = pis.readString(NAME);
- break;
+ try (var pisWrapper = mViewerConfigInputStreamProvider.getInputStream()) {
+ final var pis = pisWrapper.get();
+
+ while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+ if (pis.getFieldNumber() == (int) GROUPS) {
+ final long inMessageToken = pis.start(GROUPS);
+
+ long groupId = 0;
+ String groupName = null;
+ while (pis.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+ switch (pis.getFieldNumber()) {
+ case (int) ID:
+ groupId = pis.readInt(ID);
+ break;
+ case (int) NAME:
+ groupName = pis.readString(NAME);
+ break;
+ }
}
- }
- if (Objects.equals(groupName, group)) {
- return groupId;
- }
+ if (Objects.equals(groupName, group)) {
+ return groupId;
+ }
- pis.end(inMessageToken);
+ pis.end(inMessageToken);
+ }
}
}
diff --git a/core/java/com/android/internal/protolog/UnprocessedPerfettoProtoLogImpl.java b/core/java/com/android/internal/protolog/UnprocessedPerfettoProtoLogImpl.java
new file mode 100644
index 000000000000..f3fe58070fa9
--- /dev/null
+++ b/core/java/com/android/internal/protolog/UnprocessedPerfettoProtoLogImpl.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.protolog;
+
+import android.annotation.NonNull;
+import android.os.ServiceManager;
+
+import com.android.internal.protolog.ProtoLogConfigurationServiceImpl.RegisterClientArgs;
+import com.android.internal.protolog.common.IProtoLogGroup;
+
+public class UnprocessedPerfettoProtoLogImpl extends PerfettoProtoLogImpl {
+ public UnprocessedPerfettoProtoLogImpl(@NonNull IProtoLogGroup[] groups)
+ throws ServiceManager.ServiceNotFoundException {
+ this(() -> {}, groups);
+ }
+
+ public UnprocessedPerfettoProtoLogImpl(@NonNull Runnable cacheUpdater,
+ @NonNull IProtoLogGroup[] groups) throws ServiceManager.ServiceNotFoundException {
+ super(cacheUpdater, groups);
+ readyToLogToLogcat();
+ }
+
+ @NonNull
+ @Override
+ protected RegisterClientArgs createConfigurationServiceRegisterClientArgs() {
+ return new RegisterClientArgs();
+ }
+
+ @Override
+ void dumpViewerConfig() {
+ // No-op
+ }
+
+ @NonNull
+ @Override
+ String getLogcatMessageString(@NonNull Message message) {
+ String messageString;
+ messageString = message.getMessage();
+
+ if (messageString == null) {
+ throw new RuntimeException("Failed to decode message for logcat. "
+ + "Message not available without ViewerConfig to decode the hash.");
+ }
+
+ return messageString;
+ }
+}
diff --git a/core/java/com/android/internal/protolog/Utils.java b/core/java/com/android/internal/protolog/Utils.java
index 00ef80ab2bdd..629682ca2e71 100644
--- a/core/java/com/android/internal/protolog/Utils.java
+++ b/core/java/com/android/internal/protolog/Utils.java
@@ -48,8 +48,8 @@ public class Utils {
public static void dumpViewerConfig(@NonNull ProtoLogDataSource dataSource,
@NonNull ViewerConfigInputStreamProvider viewerConfigInputStreamProvider) {
dataSource.trace(ctx -> {
- try {
- ProtoInputStream pis = viewerConfigInputStreamProvider.getInputStream();
+ try (var pisWrapper = viewerConfigInputStreamProvider.getInputStream()) {
+ final var pis = pisWrapper.get();
final ProtoOutputStream os = ctx.newTracePacket();
diff --git a/core/java/com/android/internal/protolog/ViewerConfigInputStreamProvider.java b/core/java/com/android/internal/protolog/ViewerConfigInputStreamProvider.java
index 14bc8e4782f2..60c98923eb23 100644
--- a/core/java/com/android/internal/protolog/ViewerConfigInputStreamProvider.java
+++ b/core/java/com/android/internal/protolog/ViewerConfigInputStreamProvider.java
@@ -17,12 +17,12 @@
package com.android.internal.protolog;
import android.annotation.NonNull;
-import android.util.proto.ProtoInputStream;
public interface ViewerConfigInputStreamProvider {
/**
* @return a ProtoInputStream.
*/
@NonNull
- ProtoInputStream getInputStream();
+ AutoClosableProtoInputStream getInputStream();
}
+
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 81b885aa626b..b5c87868af12 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -84,4 +84,5 @@ oneway interface IPhoneStateListener {
void onSimultaneousCallingStateChanged(in int[] subIds);
void onCarrierRoamingNtnModeChanged(in boolean active);
void onCarrierRoamingNtnEligibleStateChanged(in boolean eligible);
+ void onCarrierRoamingNtnAvailableServicesChanged(in int[] availableServices);
}
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index f836cf2b9d87..ca75abdedfcc 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -123,4 +123,5 @@ interface ITelephonyRegistry {
void notifyCallbackModeStopped(int phoneId, int subId, int type, int reason);
void notifyCarrierRoamingNtnModeChanged(int subId, in boolean active);
void notifyCarrierRoamingNtnEligibleStateChanged(int subId, in boolean eligible);
+ void notifyCarrierRoamingNtnAvailableServicesChanged(int subId, in int[] availableServices);
}
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 70a80b2bd4f1..76f66cd4ebc9 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -1024,10 +1024,18 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool p
parseCompilerOption("dalvik.vm.image-dex2oat-filter", dex2oatImageCompilerFilterBuf,
"--compiler-filter=", "-Ximage-compiler-option");
- // If there is a dirty-image-objects file, push it.
- if (hasFile("/system/etc/dirty-image-objects")) {
- addOption("-Ximage-compiler-option");
- addOption("--dirty-image-objects=/system/etc/dirty-image-objects");
+ // If there are dirty-image-objects files, push them.
+ const char* dirty_image_objects_options[] = {
+ "--dirty-image-objects=/apex/com.android.art/etc/dirty-image-objects",
+ "--dirty-image-objects=/system/etc/dirty-image-objects",
+ };
+ for (const char* option : dirty_image_objects_options) {
+ // Get the file path by finding the first '/' and check if
+ // this file exists.
+ if (hasFile(strchr(option, '/'))) {
+ addOption("-Ximage-compiler-option");
+ addOption(option);
+ }
}
parseCompilerOption("dalvik.vm.image-dex2oat-threads", dex2oatThreadsImageBuf, "-j",
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 41981715a855..9c92e5ca589b 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -7175,4 +7175,10 @@
<string name="identity_check_settings_action"></string>
<!-- Package for opening identity check settings page [CHAR LIMIT=NONE] [DO NOT TRANSLATE] -->
<string name="identity_check_settings_package_name">com\u002eandroid\u002esettings</string>
+
+ <!-- The name of the service for forensic backup transport. -->
+ <string name="config_forensicBackupTransport" translatable="false"></string>
+
+ <!-- Whether to enable fp unlock when screen turns off on udfps devices -->
+ <bool name="config_screen_off_udfps_enabled">false</bool>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 0b2b3453f20a..712b99439496 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -5636,4 +5636,10 @@
<!-- Identity check strings -->
<java-symbol type="string" name="identity_check_settings_action" />
<java-symbol type="string" name="identity_check_settings_package_name" />
+
+ <!-- Forensic backup transport -->
+ <java-symbol type="string" name="config_forensicBackupTransport" />
+
+ <!-- Fingerprint screen off unlock config -->
+ <java-symbol type="bool" name="config_screen_off_udfps_enabled" />
</resources>
diff --git a/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java b/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java
index 9d477094692a..d5479ea3310d 100644
--- a/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java
+++ b/core/tests/coretests/src/android/database/sqlite/SQLiteDatabaseTest.java
@@ -358,7 +358,6 @@ public class SQLiteDatabaseTest {
assertTrue("ReadThread failed with errors: " + errors, errors.isEmpty());
}
- @RequiresFlagsEnabled(Flags.FLAG_SQLITE_ALLOW_TEMP_TABLES)
@Test
public void testTempTable() {
boolean allowed;
diff --git a/core/tests/vibrator/src/android/os/VibratorInfoTest.java b/core/tests/vibrator/src/android/os/VibratorInfoTest.java
index 04945f38e319..9099918edb02 100644
--- a/core/tests/vibrator/src/android/os/VibratorInfoTest.java
+++ b/core/tests/vibrator/src/android/os/VibratorInfoTest.java
@@ -71,8 +71,7 @@ public class VibratorInfoTest {
VibratorInfo noCapabilities = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build();
assertFalse(noCapabilities.hasFrequencyControl());
VibratorInfo composeAndFrequencyControl = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
- .setCapabilities(
- IVibrator.CAP_FREQUENCY_CONTROL | IVibrator.CAP_COMPOSE_PWLE_EFFECTS)
+ .setCapabilities(IVibrator.CAP_FREQUENCY_CONTROL)
.build();
assertTrue(composeAndFrequencyControl.hasFrequencyControl());
}
@@ -153,7 +152,8 @@ public class VibratorInfoTest {
VibratorInfo noCapabilities = new VibratorInfo.Builder(TEST_VIBRATOR_ID).build();
assertFalse(noCapabilities.areEnvelopeEffectsSupported());
VibratorInfo envelopeEffectCapability = new VibratorInfo.Builder(TEST_VIBRATOR_ID)
- .setCapabilities(IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2)
+ .setCapabilities(
+ IVibrator.CAP_FREQUENCY_CONTROL | IVibrator.CAP_COMPOSE_PWLE_EFFECTS_V2)
.build();
assertTrue(envelopeEffectCapability.areEnvelopeEffectsSupported());
}
diff --git a/data/fonts/Android.bp b/data/fonts/Android.bp
index 4edf52bae161..0964aab43380 100644
--- a/data/fonts/Android.bp
+++ b/data/fonts/Android.bp
@@ -53,22 +53,9 @@ soong_config_bool_variable {
name: "use_var_font",
}
-soong_config_module_type {
- name: "prebuilt_fonts_xml",
- module_type: "prebuilt_etc",
- config_namespace: "noto_sans_cjk_config",
- bool_variables: ["use_var_font"],
- properties: ["src"],
-}
-
-prebuilt_fonts_xml {
+prebuilt_etc {
name: "fonts.xml",
src: "fonts.xml",
- soong_config_variables: {
- use_var_font: {
- src: "fonts_cjkvf.xml",
- },
- },
}
prebuilt_etc {
diff --git a/data/fonts/font_fallback.xml b/data/fonts/font_fallback.xml
deleted file mode 100644
index ae50da18119f..000000000000
--- a/data/fonts/font_fallback.xml
+++ /dev/null
@@ -1,950 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- In this file, all fonts without names are added to the default list.
- Fonts are chosen based on a match: full BCP-47 language tag including
- script, then just language, and finally order (the first font containing
- the glyph).
-
- Order of appearance is also the tiebreaker for weight matching. This is
- the reason why the 900 weights of Roboto precede the 700 weights - we
- prefer the former when an 800 weight is requested. Since bold spans
- effectively add 300 to the weight, this ensures that 900 is the bold
- paired with the 500 weight, ensuring adequate contrast.
-
-
- The font_fallback.xml defines the list of font used by the system.
-
- `familyset` node:
- A `familyset` element must be a root node of the font_fallback.xml. No attributes are allowed
- to `familyset` node.
- The `familyset` node can contains `family` and `alias` nodes. Any other nodes will be ignored.
-
- `family` node:
- A `family` node defines a single font family definition.
- A font family is a set of fonts for drawing text in various styles such as weight, slant.
- There are three types of families, default family, named family and locale fallback family.
-
- The default family is a special family node appeared the first node of the `familyset` node.
- The default family is used as first priority fallback.
- Only `name` attribute can be used for default family node. If the `name` attribute is
- specified, This family will also works as named family.
-
- The named family is a family that has name attribute. The named family defines a new fallback.
- For example, if the name attribute is "serif", it creates serif fallback. Developers can
- access the fallback by using Typeface#create API.
- The named family can not have attribute other than `name` attribute. The `name` attribute
- cannot be empty.
-
- The locale fallback family is a font family that is used for fallback. The fallback family is
- used when the named family or default family cannot be used. The locale fallback family can
- have `lang` attribute and `variant` attribute. The `lang` attribute is an optional comma
- separated BCP-47i language tag. The `variant` is an optional attribute that can be one one
- `element`, `compact`. If a `variant` attribute is not specified, it is treated as default.
-
- `alias` node:
- An `alias` node defines a alias of named family with changing weight offset. An `alias` node
- can have mandatory `name` and `to` attribute and optional `weight` attribute. This `alias`
- defines new fallback that has the name of specified `name` attribute. The fallback list is
- the same to the fallback that of the name specified with `to` attribute. If `weight` attribute
- is specified, the base weight offset is shifted to the specified value. For example, if the
- `weight` is 500, the output text is drawn with 500 of weight.
-
- `font` node:
- A `font` node defines a single font definition. There are two types of fonts, static font and
- variable font.
-
- A static font can have `weight`, `style`, `index` and `postScriptName` attributes. A `weight`
- is a mandatory attribute that defines the weight of the font. Any number between 0 to 1000 is
- valid. A `style` is a mandatory attribute that defines the style of the font. A 'style'
- attribute can be `normal` or `italic`. An `index` is an optional attribute that defines the
- index of the font collection. If this is not specified, it is treated as 0. If the font file
- is not a font collection, this attribute is ignored. A `postScriptName` attribute is an
- optional attribute. A PostScript name is used for identifying target of system font update.
- If this is not specified, the system assumes the filename is same to PostScript name of the
- font file. For example, if the font file is "Roboto-Regular.ttf", the system assume the
- PostScript name of this font is "Roboto-Regular".
-
- A variable font can be only defined for the variable font file. A variable font can have
- `axis` child nodes for specifying axis values. A variable font can have all attribute of
- static font and can have additional `supportedAxes` attribute. A `supportedAxes` attribute
- is a comma separated supported axis tags. As of Android V, only `wght` and `ital` axes can
- be specified.
-
- If `supportedAxes` attribute is not specified, this `font` node works as static font of the
- single instance of variable font specified with `axis` children.
-
- If `supportedAxes` attribute is specified, the system dynamically create font instance for the
- given weight and style value. If `wght` is specified in `supportedAxes` attribute the `weight`
- attribute and `axis` child that has `wght` tag become optional and ignored because it is
- determined by system at runtime. Similarly, if `ital` is specified in `supportedAxes`
- attribute, the `style` attribute and `axis` child that has `ital` tag become optional and
- ignored.
-
- `axis` node:
- An `axis` node defines a font variation value for a tag. An `axis` node can have two mandatory
- attributes, `tag` and `value`. If the font is variable font and the same tag `axis` node is
- specified in `supportedAxes` attribute, the style value works like a default instance.
--->
-<familyset>
- <!-- first font is default -->
- <family name="sans-serif">
- <font supportedAxes="wght,ital">Roboto-Regular.ttf
- <axis tag="wdth" stylevalue="100" />
- </font>
- </family>
-
-
- <!-- Note that aliases must come after the fonts they reference. -->
- <alias name="sans-serif-thin" to="sans-serif" weight="100" />
- <alias name="sans-serif-light" to="sans-serif" weight="300" />
- <alias name="sans-serif-medium" to="sans-serif" weight="500" />
- <alias name="sans-serif-black" to="sans-serif" weight="900" />
- <alias name="arial" to="sans-serif" />
- <alias name="helvetica" to="sans-serif" />
- <alias name="tahoma" to="sans-serif" />
- <alias name="verdana" to="sans-serif" />
-
- <family name="sans-serif-condensed">
- <font supportedAxes="wght,ital">Roboto-Regular.ttf
- <axis tag="wdth" stylevalue="75" />
- </font>
- </family>
- <alias name="sans-serif-condensed-light" to="sans-serif-condensed" weight="300" />
- <alias name="sans-serif-condensed-medium" to="sans-serif-condensed" weight="500" />
-
- <family name="serif">
- <font weight="400" style="normal" postScriptName="NotoSerif">NotoSerif-Regular.ttf</font>
- <font weight="700" style="normal">NotoSerif-Bold.ttf</font>
- <font weight="400" style="italic">NotoSerif-Italic.ttf</font>
- <font weight="700" style="italic">NotoSerif-BoldItalic.ttf</font>
- </family>
- <alias name="serif-bold" to="serif" weight="700" />
- <alias name="times" to="serif" />
- <alias name="times new roman" to="serif" />
- <alias name="palatino" to="serif" />
- <alias name="georgia" to="serif" />
- <alias name="baskerville" to="serif" />
- <alias name="goudy" to="serif" />
- <alias name="fantasy" to="serif" />
- <alias name="ITC Stone Serif" to="serif" />
-
- <family name="monospace">
- <font weight="400" style="normal">DroidSansMono.ttf</font>
- </family>
- <alias name="sans-serif-monospace" to="monospace" />
- <alias name="monaco" to="monospace" />
-
- <family name="serif-monospace">
- <font weight="400" style="normal" postScriptName="CutiveMono-Regular">CutiveMono.ttf</font>
- </family>
- <alias name="courier" to="serif-monospace" />
- <alias name="courier new" to="serif-monospace" />
-
- <family name="casual">
- <font weight="400" style="normal" postScriptName="ComingSoon-Regular">ComingSoon.ttf</font>
- </family>
-
- <family name="cursive">
- <font supportedAxes="wght">DancingScript-Regular.ttf</font>
- </family>
-
- <family name="sans-serif-smallcaps">
- <font weight="400" style="normal">CarroisGothicSC-Regular.ttf</font>
- </family>
-
- <family name="source-sans-pro">
- <font weight="400" style="normal">SourceSansPro-Regular.ttf</font>
- <font weight="400" style="italic">SourceSansPro-Italic.ttf</font>
- <font weight="600" style="normal">SourceSansPro-SemiBold.ttf</font>
- <font weight="600" style="italic">SourceSansPro-SemiBoldItalic.ttf</font>
- <font weight="700" style="normal">SourceSansPro-Bold.ttf</font>
- <font weight="700" style="italic">SourceSansPro-BoldItalic.ttf</font>
- </family>
- <alias name="source-sans-pro-semi-bold" to="source-sans-pro" weight="600"/>
-
- <family name="roboto-flex">
- <font supportedAxes="wght">RobotoFlex-Regular.ttf
- <axis tag="wdth" stylevalue="100" />
- </font>
- </family>
-
- <!-- fallback fonts -->
- <family lang="und-Arab" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoNaskhArabic">
- NotoNaskhArabic-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoNaskhArabic-Bold.ttf</font>
- </family>
- <family lang="und-Arab" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoNaskhArabicUI">
- NotoNaskhArabicUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoNaskhArabicUI-Bold.ttf</font>
- </family>
- <family lang="und-Ethi">
- <font postScriptName="NotoSansEthiopic-Regular" supportedAxes="wght">
- NotoSansEthiopic-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifEthiopic-Regular" supportedAxes="wght">
- NotoSerifEthiopic-VF.ttf
- </font>
- </family>
- <family lang="und-Hebr">
- <font weight="400" style="normal" postScriptName="NotoSansHebrew">
- NotoSansHebrew-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansHebrew-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifHebrew-Regular.ttf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifHebrew-Bold.ttf</font>
- </family>
- <family lang="und-Thai" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansThai">NotoSansThai-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThai-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">
- NotoSerifThai-Regular.ttf
- </font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifThai-Bold.ttf</font>
- </family>
- <family lang="und-Thai" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansThaiUI">
- NotoSansThaiUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThaiUI-Bold.ttf</font>
- </family>
- <family lang="und-Armn">
- <font postScriptName="NotoSansArmenian-Regular" supportedAxes="wght">
- NotoSansArmenian-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifArmenian-Regular" supportedAxes="wght">
- NotoSerifArmenian-VF.ttf
- </font>
- </family>
- <family lang="und-Geor,und-Geok">
- <font postScriptName="NotoSansGeorgian-Regular" supportedAxes="wght">
- NotoSansGeorgian-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifGeorgian-Regular" supportedAxes="wght">
- NotoSerifGeorgian-VF.ttf
- </font>
- </family>
- <family lang="und-Deva" variant="elegant">
- <font postScriptName="NotoSansDevanagari-Regular" supportedAxes="wght">
- NotoSansDevanagari-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifDevanagari-Regular" supportedAxes="wght">
- NotoSerifDevanagari-VF.ttf
- </font>
- </family>
- <family lang="und-Deva" variant="compact">
- <font postScriptName="NotoSansDevanagariUI-Regular" supportedAxes="wght">
- NotoSansDevanagariUI-VF.ttf
- </font>
- </family>
-
- <!-- All scripts of India should come after Devanagari, due to shared
- danda characters.
- -->
- <family lang="und-Gujr" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansGujarati">
- NotoSansGujarati-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansGujarati-Bold.ttf</font>
- <font style="normal" fallbackFor="serif" postScriptName="NotoSerifGujarati-Regular"
- supportedAxes="wght">
- NotoSerifGujarati-VF.ttf
- </font>
- </family>
- <family lang="und-Gujr" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansGujaratiUI">
- NotoSansGujaratiUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansGujaratiUI-Bold.ttf</font>
- </family>
- <family lang="und-Guru" variant="elegant">
- <font postScriptName="NotoSansGurmukhi-Regular" supportedAxes="wght">
- NotoSansGurmukhi-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifGurmukhi-Regular" supportedAxes="wght">
- NotoSerifGurmukhi-VF.ttf
- </font>
- </family>
- <family lang="und-Guru" variant="compact">
- <font postScriptName="NotoSansGurmukhiUI-Regular" supportedAxes="wght">
- NotoSansGurmukhiUI-VF.ttf
- </font>
- </family>
- <family lang="und-Taml" variant="elegant">
- <font postScriptName="NotoSansTamil-Regular" supportedAxes="wght">
- NotoSansTamil-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifTamil-Regular" supportedAxes="wght">
- NotoSerifTamil-VF.ttf
- </font>
- </family>
- <family lang="und-Taml" variant="compact">
- <font postScriptName="NotoSansTamilUI-Regular" supportedAxes="wght">
- NotoSansTamilUI-VF.ttf
- </font>
- </family>
- <family lang="und-Mlym" variant="elegant">
- <font postScriptName="NotoSansMalayalam-Regular" supportedAxes="wght">
- NotoSansMalayalam-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifMalayalam-Regular" supportedAxes="wght">
- NotoSerifMalayalam-VF.ttf
- </font>
- </family>
- <family lang="und-Mlym" variant="compact">
- <font postScriptName="NotoSansMalayalamUI-Regular" supportedAxes="wght">
- NotoSansMalayalamUI-VF.ttf
- </font>
- </family>
- <family lang="und-Beng" variant="elegant">
- <font postScriptName="NotoSansBengali-Regular" supportedAxes="wght">
- NotoSansBengali-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifBengali-Regular" supportedAxes="wght">
- NotoSerifBengali-VF.ttf
- </font>
- </family>
- <family lang="und-Beng" variant="compact">
- <font postScriptName="NotoSansBengaliUI-Regular" supportedAxes="wght">
- NotoSansBengaliUI-VF.ttf
- </font>
- </family>
- <family lang="und-Telu" variant="elegant">
- <font postScriptName="NotoSansTelugu-Regular" supportedAxes="wght">
- NotoSansTelugu-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifTelugu-Regular" supportedAxes="wght">
- NotoSerifTelugu-VF.ttf
- </font>
- </family>
- <family lang="und-Telu" variant="compact">
- <font postScriptName="NotoSansTeluguUI-Regular" supportedAxes="wght">
- NotoSansTeluguUI-VF.ttf
- </font>
- </family>
- <family lang="und-Knda" variant="elegant">
- <font postScriptName="NotoSansKannada-Regular" supportedAxes="wght">
- NotoSansKannada-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifKannada-Regular" supportedAxes="wght">
- NotoSerifKannada-VF.ttf
- </font>
- </family>
- <family lang="und-Knda" variant="compact">
- <font postScriptName="NotoSansKannadaUI-Regular" supportedAxes="wght">
- NotoSansKannadaUI-VF.ttf
- </font>
- </family>
- <family lang="und-Orya" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansOriya">NotoSansOriya-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansOriya-Bold.ttf</font>
- </family>
- <family lang="und-Orya" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansOriyaUI">
- NotoSansOriyaUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansOriyaUI-Bold.ttf</font>
- </family>
- <family lang="und-Sinh" variant="elegant">
- <font postScriptName="NotoSansSinhala-Regular" supportedAxes="wght">
- NotoSansSinhala-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifSinhala-Regular" supportedAxes="wght">
- NotoSerifSinhala-VF.ttf
- </font>
- </family>
- <family lang="und-Sinh" variant="compact">
- <font postScriptName="NotoSansSinhalaUI-Regular" supportedAxes="wght">
- NotoSansSinhalaUI-VF.ttf
- </font>
- </family>
- <!-- TODO: NotoSansKhmer uses non-standard wght value, so cannot use auto-adjustment. -->
- <family lang="und-Khmr" variant="elegant">
- <font weight="100" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="26.0"/>
- </font>
- <font weight="200" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="39.0"/>
- </font>
- <font weight="300" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="58.0"/>
- </font>
- <font weight="400" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="90.0"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="108.0"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="128.0"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="151.0"/>
- </font>
- <font weight="800" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="169.0"/>
- </font>
- <font weight="900" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="190.0"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifKhmer-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifKhmer-Bold.otf</font>
- </family>
- <family lang="und-Khmr" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansKhmerUI">
- NotoSansKhmerUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansKhmerUI-Bold.ttf</font>
- </family>
- <family lang="und-Laoo" variant="elegant">
- <font weight="400" style="normal">NotoSansLao-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansLao-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">
- NotoSerifLao-Regular.ttf
- </font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifLao-Bold.ttf</font>
- </family>
- <family lang="und-Laoo" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansLaoUI">NotoSansLaoUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansLaoUI-Bold.ttf</font>
- </family>
- <family lang="und-Mymr" variant="elegant">
- <font weight="400" style="normal">NotoSansMyanmar-Regular.otf</font>
- <font weight="500" style="normal">NotoSansMyanmar-Medium.otf</font>
- <font weight="700" style="normal">NotoSansMyanmar-Bold.otf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifMyanmar-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifMyanmar-Bold.otf</font>
- </family>
- <family lang="und-Mymr" variant="compact">
- <font weight="400" style="normal">NotoSansMyanmarUI-Regular.otf</font>
- <font weight="500" style="normal">NotoSansMyanmarUI-Medium.otf</font>
- <font weight="700" style="normal">NotoSansMyanmarUI-Bold.otf</font>
- </family>
- <family lang="und-Thaa">
- <font weight="400" style="normal" postScriptName="NotoSansThaana">
- NotoSansThaana-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThaana-Bold.ttf</font>
- </family>
- <family lang="und-Cham">
- <font weight="400" style="normal" postScriptName="NotoSansCham">NotoSansCham-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
- </family>
- <family lang="und-Ahom">
- <font weight="400" style="normal">NotoSansAhom-Regular.otf</font>
- </family>
- <family lang="und-Adlm">
- <font postScriptName="NotoSansAdlam-Regular" supportedAxes="wght">
- NotoSansAdlam-VF.ttf
- </font>
- </family>
- <family lang="und-Avst">
- <font weight="400" style="normal" postScriptName="NotoSansAvestan">
- NotoSansAvestan-Regular.ttf
- </font>
- </family>
- <family lang="und-Bali">
- <font weight="400" style="normal" postScriptName="NotoSansBalinese">
- NotoSansBalinese-Regular.ttf
- </font>
- </family>
- <family lang="und-Bamu">
- <font weight="400" style="normal" postScriptName="NotoSansBamum">NotoSansBamum-Regular.ttf
- </font>
- </family>
- <family lang="und-Batk">
- <font weight="400" style="normal" postScriptName="NotoSansBatak">NotoSansBatak-Regular.ttf
- </font>
- </family>
- <family lang="und-Brah">
- <font weight="400" style="normal" postScriptName="NotoSansBrahmi">
- NotoSansBrahmi-Regular.ttf
- </font>
- </family>
- <family lang="und-Bugi">
- <font weight="400" style="normal" postScriptName="NotoSansBuginese">
- NotoSansBuginese-Regular.ttf
- </font>
- </family>
- <family lang="und-Buhd">
- <font weight="400" style="normal" postScriptName="NotoSansBuhid">NotoSansBuhid-Regular.ttf
- </font>
- </family>
- <family lang="und-Cans">
- <font weight="400" style="normal">
- NotoSansCanadianAboriginal-Regular.ttf
- </font>
- </family>
- <family lang="und-Cari">
- <font weight="400" style="normal" postScriptName="NotoSansCarian">
- NotoSansCarian-Regular.ttf
- </font>
- </family>
- <family lang="und-Cakm">
- <font weight="400" style="normal">NotoSansChakma-Regular.otf</font>
- </family>
- <family lang="und-Cher">
- <font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
- </family>
- <family lang="und-Copt">
- <font weight="400" style="normal" postScriptName="NotoSansCoptic">
- NotoSansCoptic-Regular.ttf
- </font>
- </family>
- <family lang="und-Xsux">
- <font weight="400" style="normal" postScriptName="NotoSansCuneiform">
- NotoSansCuneiform-Regular.ttf
- </font>
- </family>
- <family lang="und-Cprt">
- <font weight="400" style="normal" postScriptName="NotoSansCypriot">
- NotoSansCypriot-Regular.ttf
- </font>
- </family>
- <family lang="und-Dsrt">
- <font weight="400" style="normal" postScriptName="NotoSansDeseret">
- NotoSansDeseret-Regular.ttf
- </font>
- </family>
- <family lang="und-Egyp">
- <font weight="400" style="normal" postScriptName="NotoSansEgyptianHieroglyphs">
- NotoSansEgyptianHieroglyphs-Regular.ttf
- </font>
- </family>
- <family lang="und-Elba">
- <font weight="400" style="normal">NotoSansElbasan-Regular.otf</font>
- </family>
- <family lang="und-Glag">
- <font weight="400" style="normal" postScriptName="NotoSansGlagolitic">
- NotoSansGlagolitic-Regular.ttf
- </font>
- </family>
- <family lang="und-Goth">
- <font weight="400" style="normal" postScriptName="NotoSansGothic">
- NotoSansGothic-Regular.ttf
- </font>
- </family>
- <family lang="und-Hano">
- <font weight="400" style="normal" postScriptName="NotoSansHanunoo">
- NotoSansHanunoo-Regular.ttf
- </font>
- </family>
- <family lang="und-Armi">
- <font weight="400" style="normal" postScriptName="NotoSansImperialAramaic">
- NotoSansImperialAramaic-Regular.ttf
- </font>
- </family>
- <family lang="und-Phli">
- <font weight="400" style="normal" postScriptName="NotoSansInscriptionalPahlavi">
- NotoSansInscriptionalPahlavi-Regular.ttf
- </font>
- </family>
- <family lang="und-Prti">
- <font weight="400" style="normal" postScriptName="NotoSansInscriptionalParthian">
- NotoSansInscriptionalParthian-Regular.ttf
- </font>
- </family>
- <family lang="und-Java">
- <font weight="400" style="normal">NotoSansJavanese-Regular.otf</font>
- </family>
- <family lang="und-Kthi">
- <font weight="400" style="normal" postScriptName="NotoSansKaithi">
- NotoSansKaithi-Regular.ttf
- </font>
- </family>
- <family lang="und-Kali">
- <font weight="400" style="normal" postScriptName="NotoSansKayahLi">
- NotoSansKayahLi-Regular.ttf
- </font>
- </family>
- <family lang="und-Khar">
- <font weight="400" style="normal" postScriptName="NotoSansKharoshthi">
- NotoSansKharoshthi-Regular.ttf
- </font>
- </family>
- <family lang="und-Lepc">
- <font weight="400" style="normal" postScriptName="NotoSansLepcha">
- NotoSansLepcha-Regular.ttf
- </font>
- </family>
- <family lang="und-Limb">
- <font weight="400" style="normal" postScriptName="NotoSansLimbu">NotoSansLimbu-Regular.ttf
- </font>
- </family>
- <family lang="und-Linb">
- <font weight="400" style="normal" postScriptName="NotoSansLinearB">
- NotoSansLinearB-Regular.ttf
- </font>
- </family>
- <family lang="und-Lisu">
- <font weight="400" style="normal" postScriptName="NotoSansLisu">NotoSansLisu-Regular.ttf
- </font>
- </family>
- <family lang="und-Lyci">
- <font weight="400" style="normal" postScriptName="NotoSansLycian">
- NotoSansLycian-Regular.ttf
- </font>
- </family>
- <family lang="und-Lydi">
- <font weight="400" style="normal" postScriptName="NotoSansLydian">
- NotoSansLydian-Regular.ttf
- </font>
- </family>
- <family lang="und-Mand">
- <font weight="400" style="normal" postScriptName="NotoSansMandaic">
- NotoSansMandaic-Regular.ttf
- </font>
- </family>
- <family lang="und-Mtei">
- <font weight="400" style="normal" postScriptName="NotoSansMeeteiMayek">
- NotoSansMeeteiMayek-Regular.ttf
- </font>
- </family>
- <family lang="und-Talu">
- <font weight="400" style="normal" postScriptName="NotoSansNewTaiLue">
- NotoSansNewTaiLue-Regular.ttf
- </font>
- </family>
- <family lang="und-Nkoo">
- <font weight="400" style="normal" postScriptName="NotoSansNKo">NotoSansNKo-Regular.ttf
- </font>
- </family>
- <family lang="und-Ogam">
- <font weight="400" style="normal" postScriptName="NotoSansOgham">NotoSansOgham-Regular.ttf
- </font>
- </family>
- <family lang="und-Olck">
- <font weight="400" style="normal" postScriptName="NotoSansOlChiki">
- NotoSansOlChiki-Regular.ttf
- </font>
- </family>
- <family lang="und-Ital">
- <font weight="400" style="normal" postScriptName="NotoSansOldItalic">
- NotoSansOldItalic-Regular.ttf
- </font>
- </family>
- <family lang="und-Xpeo">
- <font weight="400" style="normal" postScriptName="NotoSansOldPersian">
- NotoSansOldPersian-Regular.ttf
- </font>
- </family>
- <family lang="und-Sarb">
- <font weight="400" style="normal" postScriptName="NotoSansOldSouthArabian">
- NotoSansOldSouthArabian-Regular.ttf
- </font>
- </family>
- <family lang="und-Orkh">
- <font weight="400" style="normal" postScriptName="NotoSansOldTurkic">
- NotoSansOldTurkic-Regular.ttf
- </font>
- </family>
- <family lang="und-Osge">
- <font weight="400" style="normal">NotoSansOsage-Regular.ttf</font>
- </family>
- <family lang="und-Osma">
- <font weight="400" style="normal" postScriptName="NotoSansOsmanya">
- NotoSansOsmanya-Regular.ttf
- </font>
- </family>
- <family lang="und-Phnx">
- <font weight="400" style="normal" postScriptName="NotoSansPhoenician">
- NotoSansPhoenician-Regular.ttf
- </font>
- </family>
- <family lang="und-Rjng">
- <font weight="400" style="normal" postScriptName="NotoSansRejang">
- NotoSansRejang-Regular.ttf
- </font>
- </family>
- <family lang="und-Runr">
- <font weight="400" style="normal" postScriptName="NotoSansRunic">NotoSansRunic-Regular.ttf
- </font>
- </family>
- <family lang="und-Samr">
- <font weight="400" style="normal" postScriptName="NotoSansSamaritan">
- NotoSansSamaritan-Regular.ttf
- </font>
- </family>
- <family lang="und-Saur">
- <font weight="400" style="normal" postScriptName="NotoSansSaurashtra">
- NotoSansSaurashtra-Regular.ttf
- </font>
- </family>
- <family lang="und-Shaw">
- <font weight="400" style="normal" postScriptName="NotoSansShavian">
- NotoSansShavian-Regular.ttf
- </font>
- </family>
- <family lang="und-Sund">
- <font weight="400" style="normal" postScriptName="NotoSansSundanese">
- NotoSansSundanese-Regular.ttf
- </font>
- </family>
- <family lang="und-Sylo">
- <font weight="400" style="normal" postScriptName="NotoSansSylotiNagri">
- NotoSansSylotiNagri-Regular.ttf
- </font>
- </family>
- <!-- Esrangela should precede Eastern and Western Syriac, since it's our default form. -->
- <family lang="und-Syre">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacEstrangela">
- NotoSansSyriacEstrangela-Regular.ttf
- </font>
- </family>
- <family lang="und-Syrn">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacEastern">
- NotoSansSyriacEastern-Regular.ttf
- </font>
- </family>
- <family lang="und-Syrj">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacWestern">
- NotoSansSyriacWestern-Regular.ttf
- </font>
- </family>
- <family lang="und-Tglg">
- <font weight="400" style="normal" postScriptName="NotoSansTagalog">
- NotoSansTagalog-Regular.ttf
- </font>
- </family>
- <family lang="und-Tagb">
- <font weight="400" style="normal" postScriptName="NotoSansTagbanwa">
- NotoSansTagbanwa-Regular.ttf
- </font>
- </family>
- <family lang="und-Lana">
- <font weight="400" style="normal" postScriptName="NotoSansTaiTham">
- NotoSansTaiTham-Regular.ttf
- </font>
- </family>
- <family lang="und-Tavt">
- <font weight="400" style="normal" postScriptName="NotoSansTaiViet">
- NotoSansTaiViet-Regular.ttf
- </font>
- </family>
- <family lang="und-Tibt">
- <font postScriptName="NotoSerifTibetan-Regular" supportedAxes="wght">
- NotoSerifTibetan-VF.ttf
- </font>
- </family>
- <family lang="und-Tfng">
- <font weight="400" style="normal">NotoSansTifinagh-Regular.otf</font>
- </family>
- <family lang="und-Ugar">
- <font weight="400" style="normal" postScriptName="NotoSansUgaritic">
- NotoSansUgaritic-Regular.ttf
- </font>
- </family>
- <family lang="und-Vaii">
- <font weight="400" style="normal" postScriptName="NotoSansVai">NotoSansVai-Regular.ttf
- </font>
- </family>
- <family>
- <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
- </family>
- <family lang="zh-Hans">
- <font weight="400" style="normal" index="2" postScriptName="NotoSansCJKjp-Regular">
- NotoSansCJK-Regular.ttc
- </font>
- <font weight="400" style="normal" index="2" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="zh-Hant,zh-Bopo">
- <font weight="400" style="normal" index="3" postScriptName="NotoSansCJKjp-Regular">
- NotoSansCJK-Regular.ttc
- </font>
- <font weight="400" style="normal" index="3" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="ja">
- <font weight="400" style="normal" index="0" postScriptName="NotoSansCJKjp-Regular">
- NotoSansCJK-Regular.ttc
- </font>
- <font weight="400" style="normal" index="0" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="ja">
- <font postScriptName="NotoSerifHentaigana-ExtraLight" supportedAxes="wght">
- NotoSerifHentaigana.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- </family>
- <family lang="ko">
- <font weight="400" style="normal" index="1" postScriptName="NotoSansCJKjp-Regular">
- NotoSansCJK-Regular.ttc
- </font>
- <font weight="400" style="normal" index="1" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="und-Zsye">
- <font weight="400" style="normal">NotoColorEmoji.ttf</font>
- </family>
- <family lang="und-Zsye">
- <font weight="400" style="normal">NotoColorEmojiFlags.ttf</font>
- </family>
- <family lang="und-Zsym">
- <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted2.ttf</font>
- </family>
- <!--
- Tai Le, Yi, Mongolian, and Phags-pa are intentionally kept last, to make sure they don't
- override the East Asian punctuation for Chinese.
- -->
- <family lang="und-Tale">
- <font weight="400" style="normal" postScriptName="NotoSansTaiLe">NotoSansTaiLe-Regular.ttf
- </font>
- </family>
- <family lang="und-Yiii">
- <font weight="400" style="normal" postScriptName="NotoSansYi">NotoSansYi-Regular.ttf</font>
- </family>
- <family lang="und-Mong">
- <font weight="400" style="normal" postScriptName="NotoSansMongolian">
- NotoSansMongolian-Regular.ttf
- </font>
- </family>
- <family lang="und-Phag">
- <font weight="400" style="normal" postScriptName="NotoSansPhagsPa">
- NotoSansPhagsPa-Regular.ttf
- </font>
- </family>
- <family lang="und-Hluw">
- <font weight="400" style="normal">NotoSansAnatolianHieroglyphs-Regular.otf</font>
- </family>
- <family lang="und-Bass">
- <font weight="400" style="normal">NotoSansBassaVah-Regular.otf</font>
- </family>
- <family lang="und-Bhks">
- <font weight="400" style="normal">NotoSansBhaiksuki-Regular.otf</font>
- </family>
- <family lang="und-Hatr">
- <font weight="400" style="normal">NotoSansHatran-Regular.otf</font>
- </family>
- <family lang="und-Lina">
- <font weight="400" style="normal">NotoSansLinearA-Regular.otf</font>
- </family>
- <family lang="und-Mani">
- <font weight="400" style="normal">NotoSansManichaean-Regular.otf</font>
- </family>
- <family lang="und-Marc">
- <font weight="400" style="normal">NotoSansMarchen-Regular.otf</font>
- </family>
- <family lang="und-Merc">
- <font weight="400" style="normal">NotoSansMeroitic-Regular.otf</font>
- </family>
- <family lang="und-Plrd">
- <font weight="400" style="normal">NotoSansMiao-Regular.otf</font>
- </family>
- <family lang="und-Mroo">
- <font weight="400" style="normal">NotoSansMro-Regular.otf</font>
- </family>
- <family lang="und-Mult">
- <font weight="400" style="normal">NotoSansMultani-Regular.otf</font>
- </family>
- <family lang="und-Nbat">
- <font weight="400" style="normal">NotoSansNabataean-Regular.otf</font>
- </family>
- <family lang="und-Newa">
- <font weight="400" style="normal">NotoSansNewa-Regular.otf</font>
- </family>
- <family lang="und-Narb">
- <font weight="400" style="normal">NotoSansOldNorthArabian-Regular.otf</font>
- </family>
- <family lang="und-Perm">
- <font weight="400" style="normal">NotoSansOldPermic-Regular.otf</font>
- </family>
- <family lang="und-Hmng">
- <font weight="400" style="normal">NotoSansPahawhHmong-Regular.otf</font>
- </family>
- <family lang="und-Palm">
- <font weight="400" style="normal">NotoSansPalmyrene-Regular.otf</font>
- </family>
- <family lang="und-Pauc">
- <font weight="400" style="normal">NotoSansPauCinHau-Regular.otf</font>
- </family>
- <family lang="und-Shrd">
- <font weight="400" style="normal">NotoSansSharada-Regular.otf</font>
- </family>
- <family lang="und-Sora">
- <font weight="400" style="normal">NotoSansSoraSompeng-Regular.otf</font>
- </family>
- <family lang="und-Gong">
- <font weight="400" style="normal">NotoSansGunjalaGondi-Regular.otf</font>
- </family>
- <family lang="und-Rohg">
- <font weight="400" style="normal">NotoSansHanifiRohingya-Regular.otf</font>
- </family>
- <family lang="und-Khoj">
- <font weight="400" style="normal">NotoSansKhojki-Regular.otf</font>
- </family>
- <family lang="und-Gonm">
- <font weight="400" style="normal">NotoSansMasaramGondi-Regular.otf</font>
- </family>
- <family lang="und-Wcho">
- <font weight="400" style="normal">NotoSansWancho-Regular.otf</font>
- </family>
- <family lang="und-Wara">
- <font weight="400" style="normal">NotoSansWarangCiti-Regular.otf</font>
- </family>
- <family lang="und-Gran">
- <font weight="400" style="normal">NotoSansGrantha-Regular.ttf</font>
- </family>
- <family lang="und-Modi">
- <font weight="400" style="normal">NotoSansModi-Regular.ttf</font>
- </family>
- <family lang="und-Dogr">
- <font weight="400" style="normal">NotoSerifDogra-Regular.ttf</font>
- </family>
- <family lang="und-Medf">
- <font postScriptName="NotoSansMedefaidrin-Regular" supportedAxes="wght">
- NotoSansMedefaidrin-VF.ttf
- </font>
- </family>
- <family lang="und-Soyo">
- <font postScriptName="NotoSansSoyombo-Regular" supportedAxes="wght">
- NotoSansSoyombo-VF.ttf
- </font>
- </family>
- <family lang="und-Takr">
- <font postScriptName="NotoSansTakri-Regular" supportedAxes="wght">
- NotoSansTakri-VF.ttf
- </font>
- </family>
- <family lang="und-Hmnp">
- <font postScriptName="NotoSerifHmongNyiakeng-Regular" supportedAxes="wght">
- NotoSerifNyiakengPuachueHmong-VF.ttf
- </font>
- </family>
- <family lang="und-Yezi">
- <font postScriptName="NotoSerifYezidi-Regular" supportedAxes="wght">
- NotoSerifYezidi-VF.ttf
- </font>
- </family>
-</familyset>
diff --git a/data/fonts/font_fallback_cjkvf.xml b/data/fonts/font_fallback_cjkvf.xml
deleted file mode 100644
index 407d70410bbc..000000000000
--- a/data/fonts/font_fallback_cjkvf.xml
+++ /dev/null
@@ -1,966 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- In this file, all fonts without names are added to the default list.
- Fonts are chosen based on a match: full BCP-47 language tag including
- script, then just language, and finally order (the first font containing
- the glyph).
-
- Order of appearance is also the tiebreaker for weight matching. This is
- the reason why the 900 weights of Roboto precede the 700 weights - we
- prefer the former when an 800 weight is requested. Since bold spans
- effectively add 300 to the weight, this ensures that 900 is the bold
- paired with the 500 weight, ensuring adequate contrast.
-
-
- The font_fallback.xml defines the list of font used by the system.
-
- `familyset` node:
- A `familyset` element must be a root node of the font_fallback.xml. No attributes are allowed
- to `familyset` node.
- The `familyset` node can contains `family` and `alias` nodes. Any other nodes will be ignored.
-
- `family` node:
- A `family` node defines a single font family definition.
- A font family is a set of fonts for drawing text in various styles such as weight, slant.
- There are three types of families, default family, named family and locale fallback family.
-
- The default family is a special family node appeared the first node of the `familyset` node.
- The default family is used as first priority fallback.
- Only `name` attribute can be used for default family node. If the `name` attribute is
- specified, This family will also works as named family.
-
- The named family is a family that has name attribute. The named family defines a new fallback.
- For example, if the name attribute is "serif", it creates serif fallback. Developers can
- access the fallback by using Typeface#create API.
- The named family can not have attribute other than `name` attribute. The `name` attribute
- cannot be empty.
-
- The locale fallback family is a font family that is used for fallback. The fallback family is
- used when the named family or default family cannot be used. The locale fallback family can
- have `lang` attribute and `variant` attribute. The `lang` attribute is an optional comma
- separated BCP-47i language tag. The `variant` is an optional attribute that can be one one
- `element`, `compact`. If a `variant` attribute is not specified, it is treated as default.
-
- `alias` node:
- An `alias` node defines a alias of named family with changing weight offset. An `alias` node
- can have mandatory `name` and `to` attribute and optional `weight` attribute. This `alias`
- defines new fallback that has the name of specified `name` attribute. The fallback list is
- the same to the fallback that of the name specified with `to` attribute. If `weight` attribute
- is specified, the base weight offset is shifted to the specified value. For example, if the
- `weight` is 500, the output text is drawn with 500 of weight.
-
- `font` node:
- A `font` node defines a single font definition. There are two types of fonts, static font and
- variable font.
-
- A static font can have `weight`, `style`, `index` and `postScriptName` attributes. A `weight`
- is a mandatory attribute that defines the weight of the font. Any number between 0 to 1000 is
- valid. A `style` is a mandatory attribute that defines the style of the font. A 'style'
- attribute can be `normal` or `italic`. An `index` is an optional attribute that defines the
- index of the font collection. If this is not specified, it is treated as 0. If the font file
- is not a font collection, this attribute is ignored. A `postScriptName` attribute is an
- optional attribute. A PostScript name is used for identifying target of system font update.
- If this is not specified, the system assumes the filename is same to PostScript name of the
- font file. For example, if the font file is "Roboto-Regular.ttf", the system assume the
- PostScript name of this font is "Roboto-Regular".
-
- A variable font can be only defined for the variable font file. A variable font can have
- `axis` child nodes for specifying axis values. A variable font can have all attribute of
- static font and can have additional `supportedAxes` attribute. A `supportedAxes` attribute
- is a comma separated supported axis tags. As of Android V, only `wght` and `ital` axes can
- be specified.
-
- If `supportedAxes` attribute is not specified, this `font` node works as static font of the
- single instance of variable font specified with `axis` children.
-
- If `supportedAxes` attribute is specified, the system dynamically create font instance for the
- given weight and style value. If `wght` is specified in `supportedAxes` attribute the `weight`
- attribute and `axis` child that has `wght` tag become optional and ignored because it is
- determined by system at runtime. Similarly, if `ital` is specified in `supportedAxes`
- attribute, the `style` attribute and `axis` child that has `ital` tag become optional and
- ignored.
-
- `axis` node:
- An `axis` node defines a font variation value for a tag. An `axis` node can have two mandatory
- attributes, `tag` and `value`. If the font is variable font and the same tag `axis` node is
- specified in `supportedAxes` attribute, the style value works like a default instance.
--->
-<familyset>
- <!-- first font is default -->
- <family name="sans-serif">
- <font supportedAxes="wght,ital">Roboto-Regular.ttf
- <axis tag="wdth" stylevalue="100" />
- </font>
- </family>
-
-
- <!-- Note that aliases must come after the fonts they reference. -->
- <alias name="sans-serif-thin" to="sans-serif" weight="100" />
- <alias name="sans-serif-light" to="sans-serif" weight="300" />
- <alias name="sans-serif-medium" to="sans-serif" weight="500" />
- <alias name="sans-serif-black" to="sans-serif" weight="900" />
- <alias name="arial" to="sans-serif" />
- <alias name="helvetica" to="sans-serif" />
- <alias name="tahoma" to="sans-serif" />
- <alias name="verdana" to="sans-serif" />
-
- <family name="sans-serif-condensed">
- <font supportedAxes="wght,ital">Roboto-Regular.ttf
- <axis tag="wdth" stylevalue="75" />
- </font>
- </family>
- <alias name="sans-serif-condensed-light" to="sans-serif-condensed" weight="300" />
- <alias name="sans-serif-condensed-medium" to="sans-serif-condensed" weight="500" />
-
- <family name="serif">
- <font weight="400" style="normal" postScriptName="NotoSerif">NotoSerif-Regular.ttf</font>
- <font weight="700" style="normal">NotoSerif-Bold.ttf</font>
- <font weight="400" style="italic">NotoSerif-Italic.ttf</font>
- <font weight="700" style="italic">NotoSerif-BoldItalic.ttf</font>
- </family>
- <alias name="serif-bold" to="serif" weight="700" />
- <alias name="times" to="serif" />
- <alias name="times new roman" to="serif" />
- <alias name="palatino" to="serif" />
- <alias name="georgia" to="serif" />
- <alias name="baskerville" to="serif" />
- <alias name="goudy" to="serif" />
- <alias name="fantasy" to="serif" />
- <alias name="ITC Stone Serif" to="serif" />
-
- <family name="monospace">
- <font weight="400" style="normal">DroidSansMono.ttf</font>
- </family>
- <alias name="sans-serif-monospace" to="monospace" />
- <alias name="monaco" to="monospace" />
-
- <family name="serif-monospace">
- <font weight="400" style="normal" postScriptName="CutiveMono-Regular">CutiveMono.ttf</font>
- </family>
- <alias name="courier" to="serif-monospace" />
- <alias name="courier new" to="serif-monospace" />
-
- <family name="casual">
- <font weight="400" style="normal" postScriptName="ComingSoon-Regular">ComingSoon.ttf</font>
- </family>
-
- <family name="cursive">
- <font supportedAxes="wght">DancingScript-Regular.ttf</font>
- </family>
-
- <family name="sans-serif-smallcaps">
- <font weight="400" style="normal">CarroisGothicSC-Regular.ttf</font>
- </family>
-
- <family name="source-sans-pro">
- <font weight="400" style="normal">SourceSansPro-Regular.ttf</font>
- <font weight="400" style="italic">SourceSansPro-Italic.ttf</font>
- <font weight="600" style="normal">SourceSansPro-SemiBold.ttf</font>
- <font weight="600" style="italic">SourceSansPro-SemiBoldItalic.ttf</font>
- <font weight="700" style="normal">SourceSansPro-Bold.ttf</font>
- <font weight="700" style="italic">SourceSansPro-BoldItalic.ttf</font>
- </family>
- <alias name="source-sans-pro-semi-bold" to="source-sans-pro" weight="600"/>
-
- <family name="roboto-flex">
- <font supportedAxes="wght">RobotoFlex-Regular.ttf
- <axis tag="wdth" stylevalue="100" />
- </font>
- </family>
-
- <!-- fallback fonts -->
- <family lang="und-Arab" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoNaskhArabic">
- NotoNaskhArabic-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoNaskhArabic-Bold.ttf</font>
- </family>
- <family lang="und-Arab" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoNaskhArabicUI">
- NotoNaskhArabicUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoNaskhArabicUI-Bold.ttf</font>
- </family>
- <family lang="und-Ethi">
- <font postScriptName="NotoSansEthiopic-Regular" supportedAxes="wght">
- NotoSansEthiopic-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifEthiopic-Regular" supportedAxes="wght">
- NotoSerifEthiopic-VF.ttf
- </font>
- </family>
- <family lang="und-Hebr">
- <font weight="400" style="normal" postScriptName="NotoSansHebrew">
- NotoSansHebrew-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansHebrew-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifHebrew-Regular.ttf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifHebrew-Bold.ttf</font>
- </family>
- <family lang="und-Thai" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansThai">NotoSansThai-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThai-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">
- NotoSerifThai-Regular.ttf
- </font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifThai-Bold.ttf</font>
- </family>
- <family lang="und-Thai" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansThaiUI">
- NotoSansThaiUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThaiUI-Bold.ttf</font>
- </family>
- <family lang="und-Armn">
- <font postScriptName="NotoSansArmenian-Regular" supportedAxes="wght">
- NotoSansArmenian-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifArmenian-Regular" supportedAxes="wght">
- NotoSerifArmenian-VF.ttf
- </font>
- </family>
- <family lang="und-Geor,und-Geok">
- <font postScriptName="NotoSansGeorgian-Regular" supportedAxes="wght">
- NotoSansGeorgian-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifGeorgian-Regular" supportedAxes="wght">
- NotoSerifGeorgian-VF.ttf
- </font>
- </family>
- <family lang="und-Deva" variant="elegant">
- <font postScriptName="NotoSansDevanagari-Regular" supportedAxes="wght">
- NotoSansDevanagari-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifDevanagari-Regular" supportedAxes="wght">
- NotoSerifDevanagari-VF.ttf
- </font>
- </family>
- <family lang="und-Deva" variant="compact">
- <font postScriptName="NotoSansDevanagariUI-Regular" supportedAxes="wght">
- NotoSansDevanagariUI-VF.ttf
- </font>
- </family>
-
- <!-- All scripts of India should come after Devanagari, due to shared
- danda characters.
- -->
- <family lang="und-Gujr" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansGujarati">
- NotoSansGujarati-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansGujarati-Bold.ttf</font>
- <font style="normal" fallbackFor="serif" postScriptName="NotoSerifGujarati-Regular"
- supportedAxes="wght">
- NotoSerifGujarati-VF.ttf
- </font>
- </family>
- <family lang="und-Gujr" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansGujaratiUI">
- NotoSansGujaratiUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansGujaratiUI-Bold.ttf</font>
- </family>
- <family lang="und-Guru" variant="elegant">
- <font postScriptName="NotoSansGurmukhi-Regular" supportedAxes="wght">
- NotoSansGurmukhi-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifGurmukhi-Regular" supportedAxes="wght">
- NotoSerifGurmukhi-VF.ttf
- </font>
- </family>
- <family lang="und-Guru" variant="compact">
- <font postScriptName="NotoSansGurmukhiUI-Regular" supportedAxes="wght">
- NotoSansGurmukhiUI-VF.ttf
- </font>
- </family>
- <family lang="und-Taml" variant="elegant">
- <font postScriptName="NotoSansTamil-Regular" supportedAxes="wght">
- NotoSansTamil-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifTamil-Regular" supportedAxes="wght">
- NotoSerifTamil-VF.ttf
- </font>
- </family>
- <family lang="und-Taml" variant="compact">
- <font postScriptName="NotoSansTamilUI-Regular" supportedAxes="wght">
- NotoSansTamilUI-VF.ttf
- </font>
- </family>
- <family lang="und-Mlym" variant="elegant">
- <font postScriptName="NotoSansMalayalam-Regular" supportedAxes="wght">
- NotoSansMalayalam-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifMalayalam-Regular" supportedAxes="wght">
- NotoSerifMalayalam-VF.ttf
- </font>
- </family>
- <family lang="und-Mlym" variant="compact">
- <font postScriptName="NotoSansMalayalamUI-Regular" supportedAxes="wght">
- NotoSansMalayalamUI-VF.ttf
- </font>
- </family>
- <family lang="und-Beng" variant="elegant">
- <font postScriptName="NotoSansBengali-Regular" supportedAxes="wght">
- NotoSansBengali-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifBengali-Regular" supportedAxes="wght">
- NotoSerifBengali-VF.ttf
- </font>
- </family>
- <family lang="und-Beng" variant="compact">
- <font postScriptName="NotoSansBengaliUI-Regular" supportedAxes="wght">
- NotoSansBengaliUI-VF.ttf
- </font>
- </family>
- <family lang="und-Telu" variant="elegant">
- <font postScriptName="NotoSansTelugu-Regular" supportedAxes="wght">
- NotoSansTelugu-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifTelugu-Regular" supportedAxes="wght">
- NotoSerifTelugu-VF.ttf
- </font>
- </family>
- <family lang="und-Telu" variant="compact">
- <font postScriptName="NotoSansTeluguUI-Regular" supportedAxes="wght">
- NotoSansTeluguUI-VF.ttf
- </font>
- </family>
- <family lang="und-Knda" variant="elegant">
- <font postScriptName="NotoSansKannada-Regular" supportedAxes="wght">
- NotoSansKannada-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifKannada-Regular" supportedAxes="wght">
- NotoSerifKannada-VF.ttf
- </font>
- </family>
- <family lang="und-Knda" variant="compact">
- <font postScriptName="NotoSansKannadaUI-Regular" supportedAxes="wght">
- NotoSansKannadaUI-VF.ttf
- </font>
- </family>
- <family lang="und-Orya" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansOriya">NotoSansOriya-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansOriya-Bold.ttf</font>
- </family>
- <family lang="und-Orya" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansOriyaUI">
- NotoSansOriyaUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansOriyaUI-Bold.ttf</font>
- </family>
- <family lang="und-Sinh" variant="elegant">
- <font postScriptName="NotoSansSinhala-Regular" supportedAxes="wght">
- NotoSansSinhala-VF.ttf
- </font>
- <font fallbackFor="serif" postScriptName="NotoSerifSinhala-Regular" supportedAxes="wght">
- NotoSerifSinhala-VF.ttf
- </font>
- </family>
- <family lang="und-Sinh" variant="compact">
- <font postScriptName="NotoSansSinhalaUI-Regular" supportedAxes="wght">
- NotoSansSinhalaUI-VF.ttf
- </font>
- </family>
- <!-- TODO: NotoSansKhmer uses non-standard wght value, so cannot use auto-adjustment. -->
- <family lang="und-Khmr" variant="elegant">
- <font weight="100" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="26.0"/>
- </font>
- <font weight="200" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="39.0"/>
- </font>
- <font weight="300" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="58.0"/>
- </font>
- <font weight="400" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="90.0"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="108.0"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="128.0"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="151.0"/>
- </font>
- <font weight="800" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="169.0"/>
- </font>
- <font weight="900" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="190.0"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifKhmer-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifKhmer-Bold.otf</font>
- </family>
- <family lang="und-Khmr" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansKhmerUI">
- NotoSansKhmerUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansKhmerUI-Bold.ttf</font>
- </family>
- <family lang="und-Laoo" variant="elegant">
- <font weight="400" style="normal">NotoSansLao-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansLao-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">
- NotoSerifLao-Regular.ttf
- </font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifLao-Bold.ttf</font>
- </family>
- <family lang="und-Laoo" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansLaoUI">NotoSansLaoUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansLaoUI-Bold.ttf</font>
- </family>
- <family lang="und-Mymr" variant="elegant">
- <font weight="400" style="normal">NotoSansMyanmar-Regular.otf</font>
- <font weight="500" style="normal">NotoSansMyanmar-Medium.otf</font>
- <font weight="700" style="normal">NotoSansMyanmar-Bold.otf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifMyanmar-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifMyanmar-Bold.otf</font>
- </family>
- <family lang="und-Mymr" variant="compact">
- <font weight="400" style="normal">NotoSansMyanmarUI-Regular.otf</font>
- <font weight="500" style="normal">NotoSansMyanmarUI-Medium.otf</font>
- <font weight="700" style="normal">NotoSansMyanmarUI-Bold.otf</font>
- </family>
- <family lang="und-Thaa">
- <font weight="400" style="normal" postScriptName="NotoSansThaana">
- NotoSansThaana-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThaana-Bold.ttf</font>
- </family>
- <family lang="und-Cham">
- <font weight="400" style="normal" postScriptName="NotoSansCham">NotoSansCham-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
- </family>
- <family lang="und-Ahom">
- <font weight="400" style="normal">NotoSansAhom-Regular.otf</font>
- </family>
- <family lang="und-Adlm">
- <font postScriptName="NotoSansAdlam-Regular" supportedAxes="wght">
- NotoSansAdlam-VF.ttf
- </font>
- </family>
- <family lang="und-Avst">
- <font weight="400" style="normal" postScriptName="NotoSansAvestan">
- NotoSansAvestan-Regular.ttf
- </font>
- </family>
- <family lang="und-Bali">
- <font weight="400" style="normal" postScriptName="NotoSansBalinese">
- NotoSansBalinese-Regular.ttf
- </font>
- </family>
- <family lang="und-Bamu">
- <font weight="400" style="normal" postScriptName="NotoSansBamum">NotoSansBamum-Regular.ttf
- </font>
- </family>
- <family lang="und-Batk">
- <font weight="400" style="normal" postScriptName="NotoSansBatak">NotoSansBatak-Regular.ttf
- </font>
- </family>
- <family lang="und-Brah">
- <font weight="400" style="normal" postScriptName="NotoSansBrahmi">
- NotoSansBrahmi-Regular.ttf
- </font>
- </family>
- <family lang="und-Bugi">
- <font weight="400" style="normal" postScriptName="NotoSansBuginese">
- NotoSansBuginese-Regular.ttf
- </font>
- </family>
- <family lang="und-Buhd">
- <font weight="400" style="normal" postScriptName="NotoSansBuhid">NotoSansBuhid-Regular.ttf
- </font>
- </family>
- <family lang="und-Cans">
- <font weight="400" style="normal">
- NotoSansCanadianAboriginal-Regular.ttf
- </font>
- </family>
- <family lang="und-Cari">
- <font weight="400" style="normal" postScriptName="NotoSansCarian">
- NotoSansCarian-Regular.ttf
- </font>
- </family>
- <family lang="und-Cakm">
- <font weight="400" style="normal">NotoSansChakma-Regular.otf</font>
- </family>
- <family lang="und-Cher">
- <font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
- </family>
- <family lang="und-Copt">
- <font weight="400" style="normal" postScriptName="NotoSansCoptic">
- NotoSansCoptic-Regular.ttf
- </font>
- </family>
- <family lang="und-Xsux">
- <font weight="400" style="normal" postScriptName="NotoSansCuneiform">
- NotoSansCuneiform-Regular.ttf
- </font>
- </family>
- <family lang="und-Cprt">
- <font weight="400" style="normal" postScriptName="NotoSansCypriot">
- NotoSansCypriot-Regular.ttf
- </font>
- </family>
- <family lang="und-Dsrt">
- <font weight="400" style="normal" postScriptName="NotoSansDeseret">
- NotoSansDeseret-Regular.ttf
- </font>
- </family>
- <family lang="und-Egyp">
- <font weight="400" style="normal" postScriptName="NotoSansEgyptianHieroglyphs">
- NotoSansEgyptianHieroglyphs-Regular.ttf
- </font>
- </family>
- <family lang="und-Elba">
- <font weight="400" style="normal">NotoSansElbasan-Regular.otf</font>
- </family>
- <family lang="und-Glag">
- <font weight="400" style="normal" postScriptName="NotoSansGlagolitic">
- NotoSansGlagolitic-Regular.ttf
- </font>
- </family>
- <family lang="und-Goth">
- <font weight="400" style="normal" postScriptName="NotoSansGothic">
- NotoSansGothic-Regular.ttf
- </font>
- </family>
- <family lang="und-Hano">
- <font weight="400" style="normal" postScriptName="NotoSansHanunoo">
- NotoSansHanunoo-Regular.ttf
- </font>
- </family>
- <family lang="und-Armi">
- <font weight="400" style="normal" postScriptName="NotoSansImperialAramaic">
- NotoSansImperialAramaic-Regular.ttf
- </font>
- </family>
- <family lang="und-Phli">
- <font weight="400" style="normal" postScriptName="NotoSansInscriptionalPahlavi">
- NotoSansInscriptionalPahlavi-Regular.ttf
- </font>
- </family>
- <family lang="und-Prti">
- <font weight="400" style="normal" postScriptName="NotoSansInscriptionalParthian">
- NotoSansInscriptionalParthian-Regular.ttf
- </font>
- </family>
- <family lang="und-Java">
- <font weight="400" style="normal">NotoSansJavanese-Regular.otf</font>
- </family>
- <family lang="und-Kthi">
- <font weight="400" style="normal" postScriptName="NotoSansKaithi">
- NotoSansKaithi-Regular.ttf
- </font>
- </family>
- <family lang="und-Kali">
- <font weight="400" style="normal" postScriptName="NotoSansKayahLi">
- NotoSansKayahLi-Regular.ttf
- </font>
- </family>
- <family lang="und-Khar">
- <font weight="400" style="normal" postScriptName="NotoSansKharoshthi">
- NotoSansKharoshthi-Regular.ttf
- </font>
- </family>
- <family lang="und-Lepc">
- <font weight="400" style="normal" postScriptName="NotoSansLepcha">
- NotoSansLepcha-Regular.ttf
- </font>
- </family>
- <family lang="und-Limb">
- <font weight="400" style="normal" postScriptName="NotoSansLimbu">NotoSansLimbu-Regular.ttf
- </font>
- </family>
- <family lang="und-Linb">
- <font weight="400" style="normal" postScriptName="NotoSansLinearB">
- NotoSansLinearB-Regular.ttf
- </font>
- </family>
- <family lang="und-Lisu">
- <font weight="400" style="normal" postScriptName="NotoSansLisu">NotoSansLisu-Regular.ttf
- </font>
- </family>
- <family lang="und-Lyci">
- <font weight="400" style="normal" postScriptName="NotoSansLycian">
- NotoSansLycian-Regular.ttf
- </font>
- </family>
- <family lang="und-Lydi">
- <font weight="400" style="normal" postScriptName="NotoSansLydian">
- NotoSansLydian-Regular.ttf
- </font>
- </family>
- <family lang="und-Mand">
- <font weight="400" style="normal" postScriptName="NotoSansMandaic">
- NotoSansMandaic-Regular.ttf
- </font>
- </family>
- <family lang="und-Mtei">
- <font weight="400" style="normal" postScriptName="NotoSansMeeteiMayek">
- NotoSansMeeteiMayek-Regular.ttf
- </font>
- </family>
- <family lang="und-Talu">
- <font weight="400" style="normal" postScriptName="NotoSansNewTaiLue">
- NotoSansNewTaiLue-Regular.ttf
- </font>
- </family>
- <family lang="und-Nkoo">
- <font weight="400" style="normal" postScriptName="NotoSansNKo">NotoSansNKo-Regular.ttf
- </font>
- </family>
- <family lang="und-Ogam">
- <font weight="400" style="normal" postScriptName="NotoSansOgham">NotoSansOgham-Regular.ttf
- </font>
- </family>
- <family lang="und-Olck">
- <font weight="400" style="normal" postScriptName="NotoSansOlChiki">
- NotoSansOlChiki-Regular.ttf
- </font>
- </family>
- <family lang="und-Ital">
- <font weight="400" style="normal" postScriptName="NotoSansOldItalic">
- NotoSansOldItalic-Regular.ttf
- </font>
- </family>
- <family lang="und-Xpeo">
- <font weight="400" style="normal" postScriptName="NotoSansOldPersian">
- NotoSansOldPersian-Regular.ttf
- </font>
- </family>
- <family lang="und-Sarb">
- <font weight="400" style="normal" postScriptName="NotoSansOldSouthArabian">
- NotoSansOldSouthArabian-Regular.ttf
- </font>
- </family>
- <family lang="und-Orkh">
- <font weight="400" style="normal" postScriptName="NotoSansOldTurkic">
- NotoSansOldTurkic-Regular.ttf
- </font>
- </family>
- <family lang="und-Osge">
- <font weight="400" style="normal">NotoSansOsage-Regular.ttf</font>
- </family>
- <family lang="und-Osma">
- <font weight="400" style="normal" postScriptName="NotoSansOsmanya">
- NotoSansOsmanya-Regular.ttf
- </font>
- </family>
- <family lang="und-Phnx">
- <font weight="400" style="normal" postScriptName="NotoSansPhoenician">
- NotoSansPhoenician-Regular.ttf
- </font>
- </family>
- <family lang="und-Rjng">
- <font weight="400" style="normal" postScriptName="NotoSansRejang">
- NotoSansRejang-Regular.ttf
- </font>
- </family>
- <family lang="und-Runr">
- <font weight="400" style="normal" postScriptName="NotoSansRunic">NotoSansRunic-Regular.ttf
- </font>
- </family>
- <family lang="und-Samr">
- <font weight="400" style="normal" postScriptName="NotoSansSamaritan">
- NotoSansSamaritan-Regular.ttf
- </font>
- </family>
- <family lang="und-Saur">
- <font weight="400" style="normal" postScriptName="NotoSansSaurashtra">
- NotoSansSaurashtra-Regular.ttf
- </font>
- </family>
- <family lang="und-Shaw">
- <font weight="400" style="normal" postScriptName="NotoSansShavian">
- NotoSansShavian-Regular.ttf
- </font>
- </family>
- <family lang="und-Sund">
- <font weight="400" style="normal" postScriptName="NotoSansSundanese">
- NotoSansSundanese-Regular.ttf
- </font>
- </family>
- <family lang="und-Sylo">
- <font weight="400" style="normal" postScriptName="NotoSansSylotiNagri">
- NotoSansSylotiNagri-Regular.ttf
- </font>
- </family>
- <!-- Esrangela should precede Eastern and Western Syriac, since it's our default form. -->
- <family lang="und-Syre">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacEstrangela">
- NotoSansSyriacEstrangela-Regular.ttf
- </font>
- </family>
- <family lang="und-Syrn">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacEastern">
- NotoSansSyriacEastern-Regular.ttf
- </font>
- </family>
- <family lang="und-Syrj">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacWestern">
- NotoSansSyriacWestern-Regular.ttf
- </font>
- </family>
- <family lang="und-Tglg">
- <font weight="400" style="normal" postScriptName="NotoSansTagalog">
- NotoSansTagalog-Regular.ttf
- </font>
- </family>
- <family lang="und-Tagb">
- <font weight="400" style="normal" postScriptName="NotoSansTagbanwa">
- NotoSansTagbanwa-Regular.ttf
- </font>
- </family>
- <family lang="und-Lana">
- <font weight="400" style="normal" postScriptName="NotoSansTaiTham">
- NotoSansTaiTham-Regular.ttf
- </font>
- </family>
- <family lang="und-Tavt">
- <font weight="400" style="normal" postScriptName="NotoSansTaiViet">
- NotoSansTaiViet-Regular.ttf
- </font>
- </family>
- <family lang="und-Tibt">
- <font postScriptName="NotoSerifTibetan-Regular" supportedAxes="wght">
- NotoSerifTibetan-VF.ttf
- </font>
- </family>
- <family lang="und-Tfng">
- <font weight="400" style="normal">NotoSansTifinagh-Regular.otf</font>
- </family>
- <family lang="und-Ugar">
- <font weight="400" style="normal" postScriptName="NotoSansUgaritic">
- NotoSansUgaritic-Regular.ttf
- </font>
- </family>
- <family lang="und-Vaii">
- <font weight="400" style="normal" postScriptName="NotoSansVai">NotoSansVai-Regular.ttf
- </font>
- </family>
- <family>
- <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
- </family>
- <family lang="zh-Hans">
- <font weight="400" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular"
- supportedAxes="wght">
- NotoSansCJK-Regular.ttc
- <!-- The default instance of NotoSansCJK-Regular.ttc is wght=100, so specify wght=400
- for making regular style as default. -->
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="400" style="normal" index="2" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="zh-Hant,zh-Bopo">
- <font weight="400" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular"
- supportedAxes="wght">
- NotoSansCJK-Regular.ttc
- <!-- The default instance of NotoSansCJK-Regular.ttc is wght=100, so specify wght=400
- for making regular style as default. -->
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="400" style="normal" index="3" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="ja">
- <font weight="400" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular"
- supportedAxes="wght">
- NotoSansCJK-Regular.ttc
- <!-- The default instance of NotoSansCJK-Regular.ttc is wght=100, so specify wght=400
- for making regular style as default. -->
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="400" style="normal" index="0" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="ja">
- <font postScriptName="NotoSerifHentaigana-ExtraLight" supportedAxes="wght">
- NotoSerifHentaigana.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- </family>
- <family lang="ko">
- <font weight="400" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular"
- supportedAxes="wght">
- NotoSansCJK-Regular.ttc
- <!-- The default instance of NotoSansCJK-Regular.ttc is wght=100, so specify wght=400
- for making regular style as default. -->
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="400" style="normal" index="1" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="und-Zsye">
- <font weight="400" style="normal">NotoColorEmoji.ttf</font>
- </family>
- <family lang="und-Zsye">
- <font weight="400" style="normal">NotoColorEmojiFlags.ttf</font>
- </family>
- <family lang="und-Zsym">
- <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted2.ttf</font>
- </family>
- <!--
- Tai Le, Yi, Mongolian, and Phags-pa are intentionally kept last, to make sure they don't
- override the East Asian punctuation for Chinese.
- -->
- <family lang="und-Tale">
- <font weight="400" style="normal" postScriptName="NotoSansTaiLe">NotoSansTaiLe-Regular.ttf
- </font>
- </family>
- <family lang="und-Yiii">
- <font weight="400" style="normal" postScriptName="NotoSansYi">NotoSansYi-Regular.ttf</font>
- </family>
- <family lang="und-Mong">
- <font weight="400" style="normal" postScriptName="NotoSansMongolian">
- NotoSansMongolian-Regular.ttf
- </font>
- </family>
- <family lang="und-Phag">
- <font weight="400" style="normal" postScriptName="NotoSansPhagsPa">
- NotoSansPhagsPa-Regular.ttf
- </font>
- </family>
- <family lang="und-Hluw">
- <font weight="400" style="normal">NotoSansAnatolianHieroglyphs-Regular.otf</font>
- </family>
- <family lang="und-Bass">
- <font weight="400" style="normal">NotoSansBassaVah-Regular.otf</font>
- </family>
- <family lang="und-Bhks">
- <font weight="400" style="normal">NotoSansBhaiksuki-Regular.otf</font>
- </family>
- <family lang="und-Hatr">
- <font weight="400" style="normal">NotoSansHatran-Regular.otf</font>
- </family>
- <family lang="und-Lina">
- <font weight="400" style="normal">NotoSansLinearA-Regular.otf</font>
- </family>
- <family lang="und-Mani">
- <font weight="400" style="normal">NotoSansManichaean-Regular.otf</font>
- </family>
- <family lang="und-Marc">
- <font weight="400" style="normal">NotoSansMarchen-Regular.otf</font>
- </family>
- <family lang="und-Merc">
- <font weight="400" style="normal">NotoSansMeroitic-Regular.otf</font>
- </family>
- <family lang="und-Plrd">
- <font weight="400" style="normal">NotoSansMiao-Regular.otf</font>
- </family>
- <family lang="und-Mroo">
- <font weight="400" style="normal">NotoSansMro-Regular.otf</font>
- </family>
- <family lang="und-Mult">
- <font weight="400" style="normal">NotoSansMultani-Regular.otf</font>
- </family>
- <family lang="und-Nbat">
- <font weight="400" style="normal">NotoSansNabataean-Regular.otf</font>
- </family>
- <family lang="und-Newa">
- <font weight="400" style="normal">NotoSansNewa-Regular.otf</font>
- </family>
- <family lang="und-Narb">
- <font weight="400" style="normal">NotoSansOldNorthArabian-Regular.otf</font>
- </family>
- <family lang="und-Perm">
- <font weight="400" style="normal">NotoSansOldPermic-Regular.otf</font>
- </family>
- <family lang="und-Hmng">
- <font weight="400" style="normal">NotoSansPahawhHmong-Regular.otf</font>
- </family>
- <family lang="und-Palm">
- <font weight="400" style="normal">NotoSansPalmyrene-Regular.otf</font>
- </family>
- <family lang="und-Pauc">
- <font weight="400" style="normal">NotoSansPauCinHau-Regular.otf</font>
- </family>
- <family lang="und-Shrd">
- <font weight="400" style="normal">NotoSansSharada-Regular.otf</font>
- </family>
- <family lang="und-Sora">
- <font weight="400" style="normal">NotoSansSoraSompeng-Regular.otf</font>
- </family>
- <family lang="und-Gong">
- <font weight="400" style="normal">NotoSansGunjalaGondi-Regular.otf</font>
- </family>
- <family lang="und-Rohg">
- <font weight="400" style="normal">NotoSansHanifiRohingya-Regular.otf</font>
- </family>
- <family lang="und-Khoj">
- <font weight="400" style="normal">NotoSansKhojki-Regular.otf</font>
- </family>
- <family lang="und-Gonm">
- <font weight="400" style="normal">NotoSansMasaramGondi-Regular.otf</font>
- </family>
- <family lang="und-Wcho">
- <font weight="400" style="normal">NotoSansWancho-Regular.otf</font>
- </family>
- <family lang="und-Wara">
- <font weight="400" style="normal">NotoSansWarangCiti-Regular.otf</font>
- </family>
- <family lang="und-Gran">
- <font weight="400" style="normal">NotoSansGrantha-Regular.ttf</font>
- </family>
- <family lang="und-Modi">
- <font weight="400" style="normal">NotoSansModi-Regular.ttf</font>
- </family>
- <family lang="und-Dogr">
- <font weight="400" style="normal">NotoSerifDogra-Regular.ttf</font>
- </family>
- <family lang="und-Medf">
- <font postScriptName="NotoSansMedefaidrin-Regular" supportedAxes="wght">
- NotoSansMedefaidrin-VF.ttf
- </font>
- </family>
- <family lang="und-Soyo">
- <font postScriptName="NotoSansSoyombo-Regular" supportedAxes="wght">
- NotoSansSoyombo-VF.ttf
- </font>
- </family>
- <family lang="und-Takr">
- <font postScriptName="NotoSansTakri-Regular" supportedAxes="wght">
- NotoSansTakri-VF.ttf
- </font>
- </family>
- <family lang="und-Hmnp">
- <font postScriptName="NotoSerifHmongNyiakeng-Regular" supportedAxes="wght">
- NotoSerifNyiakengPuachueHmong-VF.ttf
- </font>
- </family>
- <family lang="und-Yezi">
- <font postScriptName="NotoSerifYezidi-Regular" supportedAxes="wght">
- NotoSerifYezidi-VF.ttf
- </font>
- </family>
-</familyset>
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index d1aa8e9734c2..8cbc3000c250 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -1409,24 +1409,123 @@
<font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
</family>
<family lang="zh-Hans">
- <font weight="400" style="normal" index="2" postScriptName="NotoSansCJKjp-Regular">
+ <font weight="100" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="100"/>
+ </font>
+ <font weight="200" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="200"/>
+ </font>
+ <font weight="300" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="300"/>
+ </font>
+ <font weight="400" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="800" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="800"/>
+ </font>
+ <font weight="900" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="900"/>
</font>
<font weight="400" style="normal" index="2" fallbackFor="serif"
postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
</font>
</family>
<family lang="zh-Hant,zh-Bopo">
- <font weight="400" style="normal" index="3" postScriptName="NotoSansCJKjp-Regular">
+ <font weight="100" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="100"/>
+ </font>
+ <font weight="200" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="200"/>
+ </font>
+ <font weight="300" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="300"/>
+ </font>
+ <font weight="400" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="800" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="800"/>
+ </font>
+ <font weight="900" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="900"/>
</font>
<font weight="400" style="normal" index="3" fallbackFor="serif"
postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
</font>
</family>
<family lang="ja">
- <font weight="400" style="normal" index="0" postScriptName="NotoSansCJKjp-Regular">
+ <font weight="100" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="100"/>
+ </font>
+ <font weight="200" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="200"/>
+ </font>
+ <font weight="300" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="300"/>
+ </font>
+ <font weight="400" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="800" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="800"/>
+ </font>
+ <font weight="900" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="900"/>
</font>
<font weight="400" style="normal" index="0" fallbackFor="serif"
postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
@@ -1443,8 +1542,41 @@
</font>
</family>
<family lang="ko">
- <font weight="400" style="normal" index="1" postScriptName="NotoSansCJKjp-Regular">
+ <font weight="100" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="100"/>
+ </font>
+ <font weight="200" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="200"/>
+ </font>
+ <font weight="300" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="300"/>
+ </font>
+ <font weight="400" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="400"/>
+ </font>
+ <font weight="500" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="500"/>
+ </font>
+ <font weight="600" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="600"/>
+ </font>
+ <font weight="700" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="700"/>
+ </font>
+ <font weight="800" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
+ NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="800"/>
+ </font>
+ <font weight="900" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
NotoSansCJK-Regular.ttc
+ <axis tag="wght" stylevalue="900"/>
</font>
<font weight="400" style="normal" index="1" fallbackFor="serif"
postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
diff --git a/data/fonts/fonts_cjkvf.xml b/data/fonts/fonts_cjkvf.xml
deleted file mode 100644
index 8cbc3000c250..000000000000
--- a/data/fonts/fonts_cjkvf.xml
+++ /dev/null
@@ -1,1795 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- DEPRECATED: This XML file is no longer a source of the font files installed
- in the system.
-
- For the device vendors: please add your font configurations to the
- platform/frameworks/base/data/font_fallback.xml and also add it to this XML
- file as much as possible for apps that reads this XML file.
-
- For the application developers: please stop reading this XML file and use
- android.graphics.fonts.SystemFonts#getAvailableFonts Java API or
- ASystemFontIterator_open NDK API for getting list of system installed
- font files.
-
- WARNING: Parsing of this file by third-party apps is not supported. The
- file, and the font files it refers to, will be renamed and/or moved out
- from their respective location in the next Android release, and/or the
- format or syntax of the file may change significantly. If you parse this
- file for information about system fonts, do it at your own risk. Your
- application will almost certainly break with the next major Android
- release.
-
- In this file, all fonts without names are added to the default list.
- Fonts are chosen based on a match: full BCP-47 language tag including
- script, then just language, and finally order (the first font containing
- the glyph).
-
- Order of appearance is also the tiebreaker for weight matching. This is
- the reason why the 900 weights of Roboto precede the 700 weights - we
- prefer the former when an 800 weight is requested. Since bold spans
- effectively add 300 to the weight, this ensures that 900 is the bold
- paired with the 500 weight, ensuring adequate contrast.
-
- TODO(rsheeter) update comment; ordering to match 800 to 900 is no longer required
--->
-<familyset version="23">
- <!-- first font is default -->
- <family name="sans-serif">
- <font weight="100" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="100" />
- </font>
- <font weight="200" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="200" />
- </font>
- <font weight="300" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="300" />
- </font>
- <font weight="400" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="500" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="500" />
- </font>
- <font weight="600" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="600" />
- </font>
- <font weight="700" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="700" />
- </font>
- <font weight="800" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="800" />
- </font>
- <font weight="900" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="900" />
- </font>
- <font weight="100" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="100" />
- </font>
- <font weight="200" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="200" />
- </font>
- <font weight="300" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="300" />
- </font>
- <font weight="400" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="500" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="500" />
- </font>
- <font weight="600" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="600" />
- </font>
- <font weight="700" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="700" />
- </font>
- <font weight="800" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="800" />
- </font>
- <font weight="900" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="900" />
- </font>
- </family>
-
-
- <!-- Note that aliases must come after the fonts they reference. -->
- <alias name="sans-serif-thin" to="sans-serif" weight="100" />
- <alias name="sans-serif-light" to="sans-serif" weight="300" />
- <alias name="sans-serif-medium" to="sans-serif" weight="500" />
- <alias name="sans-serif-black" to="sans-serif" weight="900" />
- <alias name="arial" to="sans-serif" />
- <alias name="helvetica" to="sans-serif" />
- <alias name="tahoma" to="sans-serif" />
- <alias name="verdana" to="sans-serif" />
-
- <family name="sans-serif-condensed">
- <font weight="100" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="100" />
- </font>
- <font weight="200" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="200" />
- </font>
- <font weight="300" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="300" />
- </font>
- <font weight="400" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="500" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="500" />
- </font>
- <font weight="600" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="600" />
- </font>
- <font weight="700" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="700" />
- </font>
- <font weight="800" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="800" />
- </font>
- <font weight="900" style="normal">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="0" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="900" />
- </font>
- <font weight="100" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="100" />
- </font>
- <font weight="200" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="200" />
- </font>
- <font weight="300" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="300" />
- </font>
- <font weight="400" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="500" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="500" />
- </font>
- <font weight="600" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="600" />
- </font>
- <font weight="700" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="700" />
- </font>
- <font weight="800" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="800" />
- </font>
- <font weight="900" style="italic">Roboto-Regular.ttf
- <axis tag="ital" stylevalue="1" />
- <axis tag="wdth" stylevalue="75" />
- <axis tag="wght" stylevalue="900" />
- </font>
- </family>
- <alias name="sans-serif-condensed-light" to="sans-serif-condensed" weight="300" />
- <alias name="sans-serif-condensed-medium" to="sans-serif-condensed" weight="500" />
-
- <family name="serif">
- <font weight="400" style="normal" postScriptName="NotoSerif">NotoSerif-Regular.ttf</font>
- <font weight="700" style="normal">NotoSerif-Bold.ttf</font>
- <font weight="400" style="italic">NotoSerif-Italic.ttf</font>
- <font weight="700" style="italic">NotoSerif-BoldItalic.ttf</font>
- </family>
- <alias name="serif-bold" to="serif" weight="700" />
- <alias name="times" to="serif" />
- <alias name="times new roman" to="serif" />
- <alias name="palatino" to="serif" />
- <alias name="georgia" to="serif" />
- <alias name="baskerville" to="serif" />
- <alias name="goudy" to="serif" />
- <alias name="fantasy" to="serif" />
- <alias name="ITC Stone Serif" to="serif" />
-
- <family name="monospace">
- <font weight="400" style="normal">DroidSansMono.ttf</font>
- </family>
- <alias name="sans-serif-monospace" to="monospace" />
- <alias name="monaco" to="monospace" />
-
- <family name="serif-monospace">
- <font weight="400" style="normal" postScriptName="CutiveMono-Regular">CutiveMono.ttf</font>
- </family>
- <alias name="courier" to="serif-monospace" />
- <alias name="courier new" to="serif-monospace" />
-
- <family name="casual">
- <font weight="400" style="normal" postScriptName="ComingSoon-Regular">ComingSoon.ttf</font>
- </family>
-
- <family name="cursive">
- <font weight="400" style="normal">DancingScript-Regular.ttf
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="700" style="normal">DancingScript-Regular.ttf
- <axis tag="wght" stylevalue="700" />
- </font>
- </family>
-
- <family name="sans-serif-smallcaps">
- <font weight="400" style="normal">CarroisGothicSC-Regular.ttf</font>
- </family>
-
- <family name="source-sans-pro">
- <font weight="400" style="normal">SourceSansPro-Regular.ttf</font>
- <font weight="400" style="italic">SourceSansPro-Italic.ttf</font>
- <font weight="600" style="normal">SourceSansPro-SemiBold.ttf</font>
- <font weight="600" style="italic">SourceSansPro-SemiBoldItalic.ttf</font>
- <font weight="700" style="normal">SourceSansPro-Bold.ttf</font>
- <font weight="700" style="italic">SourceSansPro-BoldItalic.ttf</font>
- </family>
- <alias name="source-sans-pro-semi-bold" to="source-sans-pro" weight="600"/>
-
- <family name="roboto-flex">
- <font weight="100" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="100" />
- </font>
- <font weight="200" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="200" />
- </font>
- <font weight="300" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="300" />
- </font>
- <font weight="400" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="500" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="500" />
- </font>
- <font weight="600" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="600" />
- </font>
- <font weight="700" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="700" />
- </font>
- <font weight="800" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="800" />
- </font>
- <font weight="900" style="normal">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="0" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="900" />
- </font>
- <font weight="100" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="100" />
- </font>
- <font weight="200" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="200" />
- </font>
- <font weight="300" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="300" />
- </font>
- <font weight="400" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="400" />
- </font>
- <font weight="500" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="500" />
- </font>
- <font weight="600" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="600" />
- </font>
- <font weight="700" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="700" />
- </font>
- <font weight="800" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="800" />
- </font>
- <font weight="900" style="italic">RobotoFlex-Regular.ttf
- <axis tag="slnt" stylevalue="-10" />
- <axis tag="wdth" stylevalue="100" />
- <axis tag="wght" stylevalue="900" />
- </font>
- </family>
-
- <!-- fallback fonts -->
- <family lang="und-Arab" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoNaskhArabic">
- NotoNaskhArabic-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoNaskhArabic-Bold.ttf</font>
- </family>
- <family lang="und-Arab" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoNaskhArabicUI">
- NotoNaskhArabicUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoNaskhArabicUI-Bold.ttf</font>
- </family>
- <family lang="und-Ethi">
- <font weight="400" style="normal" postScriptName="NotoSansEthiopic-Regular">
- NotoSansEthiopic-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansEthiopic-Regular">
- NotoSansEthiopic-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansEthiopic-Regular">
- NotoSansEthiopic-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansEthiopic-Regular">
- NotoSansEthiopic-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifEthiopic-Regular">NotoSerifEthiopic-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifEthiopic-Regular">NotoSerifEthiopic-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifEthiopic-Regular">NotoSerifEthiopic-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifEthiopic-Regular">NotoSerifEthiopic-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Hebr">
- <font weight="400" style="normal" postScriptName="NotoSansHebrew">
- NotoSansHebrew-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansHebrew-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifHebrew-Regular.ttf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifHebrew-Bold.ttf</font>
- </family>
- <family lang="und-Thai" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansThai">NotoSansThai-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThai-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">
- NotoSerifThai-Regular.ttf
- </font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifThai-Bold.ttf</font>
- </family>
- <family lang="und-Thai" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansThaiUI">
- NotoSansThaiUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThaiUI-Bold.ttf</font>
- </family>
- <family lang="und-Armn">
- <font weight="400" style="normal" postScriptName="NotoSansArmenian-Regular">
- NotoSansArmenian-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansArmenian-Regular">
- NotoSansArmenian-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansArmenian-Regular">
- NotoSansArmenian-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansArmenian-Regular">
- NotoSansArmenian-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifArmenian-Regular">NotoSerifArmenian-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifArmenian-Regular">NotoSerifArmenian-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifArmenian-Regular">NotoSerifArmenian-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifArmenian-Regular">NotoSerifArmenian-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Geor,und-Geok">
- <font weight="400" style="normal" postScriptName="NotoSansGeorgian-Regular">
- NotoSansGeorgian-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansGeorgian-Regular">
- NotoSansGeorgian-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansGeorgian-Regular">
- NotoSansGeorgian-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansGeorgian-Regular">
- NotoSansGeorgian-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGeorgian-Regular">NotoSerifGeorgian-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGeorgian-Regular">NotoSerifGeorgian-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGeorgian-Regular">NotoSerifGeorgian-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGeorgian-Regular">NotoSerifGeorgian-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Deva" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansDevanagari-Regular">
- NotoSansDevanagari-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansDevanagari-Regular">
- NotoSansDevanagari-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansDevanagari-Regular">
- NotoSansDevanagari-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansDevanagari-Regular">
- NotoSansDevanagari-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifDevanagari-Regular">NotoSerifDevanagari-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifDevanagari-Regular">NotoSerifDevanagari-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifDevanagari-Regular">NotoSerifDevanagari-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifDevanagari-Regular">NotoSerifDevanagari-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Deva" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansDevanagariUI-Regular">
- NotoSansDevanagariUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansDevanagariUI-Regular">
- NotoSansDevanagariUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansDevanagariUI-Regular">
- NotoSansDevanagariUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansDevanagariUI-Regular">
- NotoSansDevanagariUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
-
- <!-- All scripts of India should come after Devanagari, due to shared
- danda characters.
- -->
- <family lang="und-Gujr" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansGujarati">
- NotoSansGujarati-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansGujarati-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGujarati-Regular">NotoSerifGujarati-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGujarati-Regular">NotoSerifGujarati-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGujarati-Regular">NotoSerifGujarati-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGujarati-Regular">NotoSerifGujarati-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Gujr" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansGujaratiUI">
- NotoSansGujaratiUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansGujaratiUI-Bold.ttf</font>
- </family>
- <family lang="und-Guru" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansGurmukhi-Regular">
- NotoSansGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansGurmukhi-Regular">
- NotoSansGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansGurmukhi-Regular">
- NotoSansGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansGurmukhi-Regular">
- NotoSansGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGurmukhi-Regular">NotoSerifGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGurmukhi-Regular">NotoSerifGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGurmukhi-Regular">NotoSerifGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifGurmukhi-Regular">NotoSerifGurmukhi-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Guru" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansGurmukhiUI-Regular">
- NotoSansGurmukhiUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansGurmukhiUI-Regular">
- NotoSansGurmukhiUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansGurmukhiUI-Regular">
- NotoSansGurmukhiUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansGurmukhiUI-Regular">
- NotoSansGurmukhiUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Taml" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansTamil-Regular">
- NotoSansTamil-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansTamil-Regular">
- NotoSansTamil-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansTamil-Regular">
- NotoSansTamil-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansTamil-Regular">
- NotoSansTamil-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTamil-Regular">NotoSerifTamil-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTamil-Regular">NotoSerifTamil-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTamil-Regular">NotoSerifTamil-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTamil-Regular">NotoSerifTamil-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Taml" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansTamilUI-Regular">
- NotoSansTamilUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansTamilUI-Regular">
- NotoSansTamilUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansTamilUI-Regular">
- NotoSansTamilUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansTamilUI-Regular">
- NotoSansTamilUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Mlym" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansMalayalam-Regular">
- NotoSansMalayalam-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansMalayalam-Regular">
- NotoSansMalayalam-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansMalayalam-Regular">
- NotoSansMalayalam-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansMalayalam-Regular">
- NotoSansMalayalam-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifMalayalam-Regular">NotoSerifMalayalam-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifMalayalam-Regular">NotoSerifMalayalam-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifMalayalam-Regular">NotoSerifMalayalam-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifMalayalam-Regular">NotoSerifMalayalam-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Mlym" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansMalayalamUI-Regular">
- NotoSansMalayalamUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansMalayalamUI-Regular">
- NotoSansMalayalamUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansMalayalamUI-Regular">
- NotoSansMalayalamUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansMalayalamUI-Regular">
- NotoSansMalayalamUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Beng" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansBengali-Regular">
- NotoSansBengali-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansBengali-Regular">
- NotoSansBengali-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansBengali-Regular">
- NotoSansBengali-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansBengali-Regular">
- NotoSansBengali-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifBengali-Regular">NotoSerifBengali-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifBengali-Regular">NotoSerifBengali-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifBengali-Regular">NotoSerifBengali-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifBengali-Regular">NotoSerifBengali-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Beng" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansBengaliUI-Regular">
- NotoSansBengaliUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansBengaliUI-Regular">
- NotoSansBengaliUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansBengaliUI-Regular">
- NotoSansBengaliUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansBengaliUI-Regular">
- NotoSansBengaliUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Telu" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansTelugu-Regular">
- NotoSansTelugu-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansTelugu-Regular">
- NotoSansTelugu-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansTelugu-Regular">
- NotoSansTelugu-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansTelugu-Regular">
- NotoSansTelugu-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTelugu-Regular">NotoSerifTelugu-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTelugu-Regular">NotoSerifTelugu-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTelugu-Regular">NotoSerifTelugu-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifTelugu-Regular">NotoSerifTelugu-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Telu" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansTeluguUI-Regular">
- NotoSansTeluguUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansTeluguUI-Regular">
- NotoSansTeluguUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansTeluguUI-Regular">
- NotoSansTeluguUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansTeluguUI-Regular">
- NotoSansTeluguUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Knda" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansKannada-Regular">
- NotoSansKannada-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansKannada-Regular">
- NotoSansKannada-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansKannada-Regular">
- NotoSansKannada-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansKannada-Regular">
- NotoSansKannada-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifKannada-Regular">NotoSerifKannada-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifKannada-Regular">NotoSerifKannada-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifKannada-Regular">NotoSerifKannada-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifKannada-Regular">NotoSerifKannada-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Knda" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansKannadaUI-Regular">
- NotoSansKannadaUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansKannadaUI-Regular">
- NotoSansKannadaUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansKannadaUI-Regular">
- NotoSansKannadaUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansKannadaUI-Regular">
- NotoSansKannadaUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Orya" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansOriya">NotoSansOriya-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansOriya-Bold.ttf</font>
- </family>
- <family lang="und-Orya" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansOriyaUI">
- NotoSansOriyaUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansOriyaUI-Bold.ttf</font>
- </family>
- <family lang="und-Sinh" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansSinhala-Regular">
- NotoSansSinhala-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansSinhala-Regular">
- NotoSansSinhala-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansSinhala-Regular">
- NotoSansSinhala-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansSinhala-Regular">
- NotoSansSinhala-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifSinhala-Regular">NotoSerifSinhala-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifSinhala-Regular">NotoSerifSinhala-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifSinhala-Regular">NotoSerifSinhala-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" fallbackFor="serif"
- postScriptName="NotoSerifSinhala-Regular">NotoSerifSinhala-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Sinh" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansSinhalaUI-Regular">
- NotoSansSinhalaUI-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansSinhalaUI-Regular">
- NotoSansSinhalaUI-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansSinhalaUI-Regular">
- NotoSansSinhalaUI-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansSinhalaUI-Regular">
- NotoSansSinhalaUI-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Khmr" variant="elegant">
- <font weight="100" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="26.0"/>
- </font>
- <font weight="200" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="39.0"/>
- </font>
- <font weight="300" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="58.0"/>
- </font>
- <font weight="400" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="90.0"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="108.0"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="128.0"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="151.0"/>
- </font>
- <font weight="800" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="169.0"/>
- </font>
- <font weight="900" style="normal" postScriptName="NotoSansKhmer-Regular">
- NotoSansKhmer-VF.ttf
- <axis tag="wdth" stylevalue="100.0"/>
- <axis tag="wght" stylevalue="190.0"/>
- </font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifKhmer-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifKhmer-Bold.otf</font>
- </family>
- <family lang="und-Khmr" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansKhmerUI">
- NotoSansKhmerUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansKhmerUI-Bold.ttf</font>
- </family>
- <family lang="und-Laoo" variant="elegant">
- <font weight="400" style="normal">NotoSansLao-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansLao-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif">
- NotoSerifLao-Regular.ttf
- </font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifLao-Bold.ttf</font>
- </family>
- <family lang="und-Laoo" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansLaoUI">NotoSansLaoUI-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansLaoUI-Bold.ttf</font>
- </family>
- <family lang="und-Mymr" variant="elegant">
- <font weight="400" style="normal">NotoSansMyanmar-Regular.otf</font>
- <font weight="500" style="normal">NotoSansMyanmar-Medium.otf</font>
- <font weight="700" style="normal">NotoSansMyanmar-Bold.otf</font>
- <font weight="400" style="normal" fallbackFor="serif">NotoSerifMyanmar-Regular.otf</font>
- <font weight="700" style="normal" fallbackFor="serif">NotoSerifMyanmar-Bold.otf</font>
- </family>
- <family lang="und-Mymr" variant="compact">
- <font weight="400" style="normal">NotoSansMyanmarUI-Regular.otf</font>
- <font weight="500" style="normal">NotoSansMyanmarUI-Medium.otf</font>
- <font weight="700" style="normal">NotoSansMyanmarUI-Bold.otf</font>
- </family>
- <family lang="und-Thaa">
- <font weight="400" style="normal" postScriptName="NotoSansThaana">
- NotoSansThaana-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansThaana-Bold.ttf</font>
- </family>
- <family lang="und-Cham">
- <font weight="400" style="normal" postScriptName="NotoSansCham">NotoSansCham-Regular.ttf
- </font>
- <font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
- </family>
- <family lang="und-Ahom">
- <font weight="400" style="normal">NotoSansAhom-Regular.otf</font>
- </family>
- <family lang="und-Adlm">
- <font weight="400" style="normal" postScriptName="NotoSansAdlam-Regular">
- NotoSansAdlam-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansAdlam-Regular">
- NotoSansAdlam-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansAdlam-Regular">
- NotoSansAdlam-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansAdlam-Regular">
- NotoSansAdlam-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Avst">
- <font weight="400" style="normal" postScriptName="NotoSansAvestan">
- NotoSansAvestan-Regular.ttf
- </font>
- </family>
- <family lang="und-Bali">
- <font weight="400" style="normal" postScriptName="NotoSansBalinese">
- NotoSansBalinese-Regular.ttf
- </font>
- </family>
- <family lang="und-Bamu">
- <font weight="400" style="normal" postScriptName="NotoSansBamum">NotoSansBamum-Regular.ttf
- </font>
- </family>
- <family lang="und-Batk">
- <font weight="400" style="normal" postScriptName="NotoSansBatak">NotoSansBatak-Regular.ttf
- </font>
- </family>
- <family lang="und-Brah">
- <font weight="400" style="normal" postScriptName="NotoSansBrahmi">
- NotoSansBrahmi-Regular.ttf
- </font>
- </family>
- <family lang="und-Bugi">
- <font weight="400" style="normal" postScriptName="NotoSansBuginese">
- NotoSansBuginese-Regular.ttf
- </font>
- </family>
- <family lang="und-Buhd">
- <font weight="400" style="normal" postScriptName="NotoSansBuhid">NotoSansBuhid-Regular.ttf
- </font>
- </family>
- <family lang="und-Cans">
- <font weight="400" style="normal">
- NotoSansCanadianAboriginal-Regular.ttf
- </font>
- </family>
- <family lang="und-Cari">
- <font weight="400" style="normal" postScriptName="NotoSansCarian">
- NotoSansCarian-Regular.ttf
- </font>
- </family>
- <family lang="und-Cakm">
- <font weight="400" style="normal">NotoSansChakma-Regular.otf</font>
- </family>
- <family lang="und-Cher">
- <font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
- </family>
- <family lang="und-Copt">
- <font weight="400" style="normal" postScriptName="NotoSansCoptic">
- NotoSansCoptic-Regular.ttf
- </font>
- </family>
- <family lang="und-Xsux">
- <font weight="400" style="normal" postScriptName="NotoSansCuneiform">
- NotoSansCuneiform-Regular.ttf
- </font>
- </family>
- <family lang="und-Cprt">
- <font weight="400" style="normal" postScriptName="NotoSansCypriot">
- NotoSansCypriot-Regular.ttf
- </font>
- </family>
- <family lang="und-Dsrt">
- <font weight="400" style="normal" postScriptName="NotoSansDeseret">
- NotoSansDeseret-Regular.ttf
- </font>
- </family>
- <family lang="und-Egyp">
- <font weight="400" style="normal" postScriptName="NotoSansEgyptianHieroglyphs">
- NotoSansEgyptianHieroglyphs-Regular.ttf
- </font>
- </family>
- <family lang="und-Elba">
- <font weight="400" style="normal">NotoSansElbasan-Regular.otf</font>
- </family>
- <family lang="und-Glag">
- <font weight="400" style="normal" postScriptName="NotoSansGlagolitic">
- NotoSansGlagolitic-Regular.ttf
- </font>
- </family>
- <family lang="und-Goth">
- <font weight="400" style="normal" postScriptName="NotoSansGothic">
- NotoSansGothic-Regular.ttf
- </font>
- </family>
- <family lang="und-Hano">
- <font weight="400" style="normal" postScriptName="NotoSansHanunoo">
- NotoSansHanunoo-Regular.ttf
- </font>
- </family>
- <family lang="und-Armi">
- <font weight="400" style="normal" postScriptName="NotoSansImperialAramaic">
- NotoSansImperialAramaic-Regular.ttf
- </font>
- </family>
- <family lang="und-Phli">
- <font weight="400" style="normal" postScriptName="NotoSansInscriptionalPahlavi">
- NotoSansInscriptionalPahlavi-Regular.ttf
- </font>
- </family>
- <family lang="und-Prti">
- <font weight="400" style="normal" postScriptName="NotoSansInscriptionalParthian">
- NotoSansInscriptionalParthian-Regular.ttf
- </font>
- </family>
- <family lang="und-Java">
- <font weight="400" style="normal">NotoSansJavanese-Regular.otf</font>
- </family>
- <family lang="und-Kthi">
- <font weight="400" style="normal" postScriptName="NotoSansKaithi">
- NotoSansKaithi-Regular.ttf
- </font>
- </family>
- <family lang="und-Kali">
- <font weight="400" style="normal" postScriptName="NotoSansKayahLi">
- NotoSansKayahLi-Regular.ttf
- </font>
- </family>
- <family lang="und-Khar">
- <font weight="400" style="normal" postScriptName="NotoSansKharoshthi">
- NotoSansKharoshthi-Regular.ttf
- </font>
- </family>
- <family lang="und-Lepc">
- <font weight="400" style="normal" postScriptName="NotoSansLepcha">
- NotoSansLepcha-Regular.ttf
- </font>
- </family>
- <family lang="und-Limb">
- <font weight="400" style="normal" postScriptName="NotoSansLimbu">NotoSansLimbu-Regular.ttf
- </font>
- </family>
- <family lang="und-Linb">
- <font weight="400" style="normal" postScriptName="NotoSansLinearB">
- NotoSansLinearB-Regular.ttf
- </font>
- </family>
- <family lang="und-Lisu">
- <font weight="400" style="normal" postScriptName="NotoSansLisu">NotoSansLisu-Regular.ttf
- </font>
- </family>
- <family lang="und-Lyci">
- <font weight="400" style="normal" postScriptName="NotoSansLycian">
- NotoSansLycian-Regular.ttf
- </font>
- </family>
- <family lang="und-Lydi">
- <font weight="400" style="normal" postScriptName="NotoSansLydian">
- NotoSansLydian-Regular.ttf
- </font>
- </family>
- <family lang="und-Mand">
- <font weight="400" style="normal" postScriptName="NotoSansMandaic">
- NotoSansMandaic-Regular.ttf
- </font>
- </family>
- <family lang="und-Mtei">
- <font weight="400" style="normal" postScriptName="NotoSansMeeteiMayek">
- NotoSansMeeteiMayek-Regular.ttf
- </font>
- </family>
- <family lang="und-Talu">
- <font weight="400" style="normal" postScriptName="NotoSansNewTaiLue">
- NotoSansNewTaiLue-Regular.ttf
- </font>
- </family>
- <family lang="und-Nkoo">
- <font weight="400" style="normal" postScriptName="NotoSansNKo">NotoSansNKo-Regular.ttf
- </font>
- </family>
- <family lang="und-Ogam">
- <font weight="400" style="normal" postScriptName="NotoSansOgham">NotoSansOgham-Regular.ttf
- </font>
- </family>
- <family lang="und-Olck">
- <font weight="400" style="normal" postScriptName="NotoSansOlChiki">
- NotoSansOlChiki-Regular.ttf
- </font>
- </family>
- <family lang="und-Ital">
- <font weight="400" style="normal" postScriptName="NotoSansOldItalic">
- NotoSansOldItalic-Regular.ttf
- </font>
- </family>
- <family lang="und-Xpeo">
- <font weight="400" style="normal" postScriptName="NotoSansOldPersian">
- NotoSansOldPersian-Regular.ttf
- </font>
- </family>
- <family lang="und-Sarb">
- <font weight="400" style="normal" postScriptName="NotoSansOldSouthArabian">
- NotoSansOldSouthArabian-Regular.ttf
- </font>
- </family>
- <family lang="und-Orkh">
- <font weight="400" style="normal" postScriptName="NotoSansOldTurkic">
- NotoSansOldTurkic-Regular.ttf
- </font>
- </family>
- <family lang="und-Osge">
- <font weight="400" style="normal">NotoSansOsage-Regular.ttf</font>
- </family>
- <family lang="und-Osma">
- <font weight="400" style="normal" postScriptName="NotoSansOsmanya">
- NotoSansOsmanya-Regular.ttf
- </font>
- </family>
- <family lang="und-Phnx">
- <font weight="400" style="normal" postScriptName="NotoSansPhoenician">
- NotoSansPhoenician-Regular.ttf
- </font>
- </family>
- <family lang="und-Rjng">
- <font weight="400" style="normal" postScriptName="NotoSansRejang">
- NotoSansRejang-Regular.ttf
- </font>
- </family>
- <family lang="und-Runr">
- <font weight="400" style="normal" postScriptName="NotoSansRunic">NotoSansRunic-Regular.ttf
- </font>
- </family>
- <family lang="und-Samr">
- <font weight="400" style="normal" postScriptName="NotoSansSamaritan">
- NotoSansSamaritan-Regular.ttf
- </font>
- </family>
- <family lang="und-Saur">
- <font weight="400" style="normal" postScriptName="NotoSansSaurashtra">
- NotoSansSaurashtra-Regular.ttf
- </font>
- </family>
- <family lang="und-Shaw">
- <font weight="400" style="normal" postScriptName="NotoSansShavian">
- NotoSansShavian-Regular.ttf
- </font>
- </family>
- <family lang="und-Sund">
- <font weight="400" style="normal" postScriptName="NotoSansSundanese">
- NotoSansSundanese-Regular.ttf
- </font>
- </family>
- <family lang="und-Sylo">
- <font weight="400" style="normal" postScriptName="NotoSansSylotiNagri">
- NotoSansSylotiNagri-Regular.ttf
- </font>
- </family>
- <!-- Esrangela should precede Eastern and Western Syriac, since it's our default form. -->
- <family lang="und-Syre">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacEstrangela">
- NotoSansSyriacEstrangela-Regular.ttf
- </font>
- </family>
- <family lang="und-Syrn">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacEastern">
- NotoSansSyriacEastern-Regular.ttf
- </font>
- </family>
- <family lang="und-Syrj">
- <font weight="400" style="normal" postScriptName="NotoSansSyriacWestern">
- NotoSansSyriacWestern-Regular.ttf
- </font>
- </family>
- <family lang="und-Tglg">
- <font weight="400" style="normal" postScriptName="NotoSansTagalog">
- NotoSansTagalog-Regular.ttf
- </font>
- </family>
- <family lang="und-Tagb">
- <font weight="400" style="normal" postScriptName="NotoSansTagbanwa">
- NotoSansTagbanwa-Regular.ttf
- </font>
- </family>
- <family lang="und-Lana">
- <font weight="400" style="normal" postScriptName="NotoSansTaiTham">
- NotoSansTaiTham-Regular.ttf
- </font>
- </family>
- <family lang="und-Tavt">
- <font weight="400" style="normal" postScriptName="NotoSansTaiViet">
- NotoSansTaiViet-Regular.ttf
- </font>
- </family>
- <family lang="und-Tibt">
- <font weight="400" style="normal" postScriptName="NotoSerifTibetan-Regular">
- NotoSerifTibetan-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSerifTibetan-Regular">
- NotoSerifTibetan-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSerifTibetan-Regular">
- NotoSerifTibetan-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSerifTibetan-Regular">
- NotoSerifTibetan-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Tfng">
- <font weight="400" style="normal">NotoSansTifinagh-Regular.otf</font>
- </family>
- <family lang="und-Ugar">
- <font weight="400" style="normal" postScriptName="NotoSansUgaritic">
- NotoSansUgaritic-Regular.ttf
- </font>
- </family>
- <family lang="und-Vaii">
- <font weight="400" style="normal" postScriptName="NotoSansVai">NotoSansVai-Regular.ttf
- </font>
- </family>
- <family>
- <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
- </family>
- <family lang="zh-Hans">
- <font weight="100" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="100"/>
- </font>
- <font weight="200" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="200"/>
- </font>
- <font weight="300" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="300"/>
- </font>
- <font weight="400" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="800" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="800"/>
- </font>
- <font weight="900" style="normal" index="2" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="900"/>
- </font>
- <font weight="400" style="normal" index="2" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="zh-Hant,zh-Bopo">
- <font weight="100" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="100"/>
- </font>
- <font weight="200" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="200"/>
- </font>
- <font weight="300" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="300"/>
- </font>
- <font weight="400" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="800" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="800"/>
- </font>
- <font weight="900" style="normal" index="3" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="900"/>
- </font>
- <font weight="400" style="normal" index="3" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="ja">
- <font weight="100" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="100"/>
- </font>
- <font weight="200" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="200"/>
- </font>
- <font weight="300" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="300"/>
- </font>
- <font weight="400" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="800" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="800"/>
- </font>
- <font weight="900" style="normal" index="0" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="900"/>
- </font>
- <font weight="400" style="normal" index="0" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="ja">
- <font weight="400" style="normal" postScriptName="NotoSerifHentaigana-ExtraLight">
- NotoSerifHentaigana.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSerifHentaigana-ExtraLight">
- NotoSerifHentaigana.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="ko">
- <font weight="100" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="100"/>
- </font>
- <font weight="200" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="200"/>
- </font>
- <font weight="300" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="300"/>
- </font>
- <font weight="400" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="700"/>
- </font>
- <font weight="800" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="800"/>
- </font>
- <font weight="900" style="normal" index="1" postScriptName="NotoSansCJKJP-Regular">
- NotoSansCJK-Regular.ttc
- <axis tag="wght" stylevalue="900"/>
- </font>
- <font weight="400" style="normal" index="1" fallbackFor="serif"
- postScriptName="NotoSerifCJKjp-Regular">NotoSerifCJK-Regular.ttc
- </font>
- </family>
- <family lang="und-Zsye" ignore="true">
- <font weight="400" style="normal">NotoColorEmojiLegacy.ttf</font>
- </family>
- <family lang="und-Zsye">
- <font weight="400" style="normal">NotoColorEmoji.ttf</font>
- </family>
- <family lang="und-Zsye">
- <font weight="400" style="normal">NotoColorEmojiFlags.ttf</font>
- </family>
- <family lang="und-Zsym">
- <font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted2.ttf</font>
- </family>
- <!--
- Tai Le, Yi, Mongolian, and Phags-pa are intentionally kept last, to make sure they don't
- override the East Asian punctuation for Chinese.
- -->
- <family lang="und-Tale">
- <font weight="400" style="normal" postScriptName="NotoSansTaiLe">NotoSansTaiLe-Regular.ttf
- </font>
- </family>
- <family lang="und-Yiii">
- <font weight="400" style="normal" postScriptName="NotoSansYi">NotoSansYi-Regular.ttf</font>
- </family>
- <family lang="und-Mong">
- <font weight="400" style="normal" postScriptName="NotoSansMongolian">
- NotoSansMongolian-Regular.ttf
- </font>
- </family>
- <family lang="und-Phag">
- <font weight="400" style="normal" postScriptName="NotoSansPhagsPa">
- NotoSansPhagsPa-Regular.ttf
- </font>
- </family>
- <family lang="und-Hluw">
- <font weight="400" style="normal">NotoSansAnatolianHieroglyphs-Regular.otf</font>
- </family>
- <family lang="und-Bass">
- <font weight="400" style="normal">NotoSansBassaVah-Regular.otf</font>
- </family>
- <family lang="und-Bhks">
- <font weight="400" style="normal">NotoSansBhaiksuki-Regular.otf</font>
- </family>
- <family lang="und-Hatr">
- <font weight="400" style="normal">NotoSansHatran-Regular.otf</font>
- </family>
- <family lang="und-Lina">
- <font weight="400" style="normal">NotoSansLinearA-Regular.otf</font>
- </family>
- <family lang="und-Mani">
- <font weight="400" style="normal">NotoSansManichaean-Regular.otf</font>
- </family>
- <family lang="und-Marc">
- <font weight="400" style="normal">NotoSansMarchen-Regular.otf</font>
- </family>
- <family lang="und-Merc">
- <font weight="400" style="normal">NotoSansMeroitic-Regular.otf</font>
- </family>
- <family lang="und-Plrd">
- <font weight="400" style="normal">NotoSansMiao-Regular.otf</font>
- </family>
- <family lang="und-Mroo">
- <font weight="400" style="normal">NotoSansMro-Regular.otf</font>
- </family>
- <family lang="und-Mult">
- <font weight="400" style="normal">NotoSansMultani-Regular.otf</font>
- </family>
- <family lang="und-Nbat">
- <font weight="400" style="normal">NotoSansNabataean-Regular.otf</font>
- </family>
- <family lang="und-Newa">
- <font weight="400" style="normal">NotoSansNewa-Regular.otf</font>
- </family>
- <family lang="und-Narb">
- <font weight="400" style="normal">NotoSansOldNorthArabian-Regular.otf</font>
- </family>
- <family lang="und-Perm">
- <font weight="400" style="normal">NotoSansOldPermic-Regular.otf</font>
- </family>
- <family lang="und-Hmng">
- <font weight="400" style="normal">NotoSansPahawhHmong-Regular.otf</font>
- </family>
- <family lang="und-Palm">
- <font weight="400" style="normal">NotoSansPalmyrene-Regular.otf</font>
- </family>
- <family lang="und-Pauc">
- <font weight="400" style="normal">NotoSansPauCinHau-Regular.otf</font>
- </family>
- <family lang="und-Shrd">
- <font weight="400" style="normal">NotoSansSharada-Regular.otf</font>
- </family>
- <family lang="und-Sora">
- <font weight="400" style="normal">NotoSansSoraSompeng-Regular.otf</font>
- </family>
- <family lang="und-Gong">
- <font weight="400" style="normal">NotoSansGunjalaGondi-Regular.otf</font>
- </family>
- <family lang="und-Rohg">
- <font weight="400" style="normal">NotoSansHanifiRohingya-Regular.otf</font>
- </family>
- <family lang="und-Khoj">
- <font weight="400" style="normal">NotoSansKhojki-Regular.otf</font>
- </family>
- <family lang="und-Gonm">
- <font weight="400" style="normal">NotoSansMasaramGondi-Regular.otf</font>
- </family>
- <family lang="und-Wcho">
- <font weight="400" style="normal">NotoSansWancho-Regular.otf</font>
- </family>
- <family lang="und-Wara">
- <font weight="400" style="normal">NotoSansWarangCiti-Regular.otf</font>
- </family>
- <family lang="und-Gran">
- <font weight="400" style="normal">NotoSansGrantha-Regular.ttf</font>
- </family>
- <family lang="und-Modi">
- <font weight="400" style="normal">NotoSansModi-Regular.ttf</font>
- </family>
- <family lang="und-Dogr">
- <font weight="400" style="normal">NotoSerifDogra-Regular.ttf</font>
- </family>
- <family lang="und-Medf">
- <font weight="400" style="normal" postScriptName="NotoSansMedefaidrin-Regular">
- NotoSansMedefaidrin-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansMedefaidrin-Regular">
- NotoSansMedefaidrin-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansMedefaidrin-Regular">
- NotoSansMedefaidrin-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansMedefaidrin-Regular">
- NotoSansMedefaidrin-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Soyo">
- <font weight="400" style="normal" postScriptName="NotoSansSoyombo-Regular">
- NotoSansSoyombo-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansSoyombo-Regular">
- NotoSansSoyombo-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansSoyombo-Regular">
- NotoSansSoyombo-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansSoyombo-Regular">
- NotoSansSoyombo-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Takr">
- <font weight="400" style="normal" postScriptName="NotoSansTakri-Regular">
- NotoSansTakri-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSansTakri-Regular">
- NotoSansTakri-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSansTakri-Regular">
- NotoSansTakri-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSansTakri-Regular">
- NotoSansTakri-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Hmnp">
- <font weight="400" style="normal" postScriptName="NotoSerifHmongNyiakeng-Regular">
- NotoSerifNyiakengPuachueHmong-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSerifHmongNyiakeng-Regular">
- NotoSerifNyiakengPuachueHmong-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSerifHmongNyiakeng-Regular">
- NotoSerifNyiakengPuachueHmong-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSerifHmongNyiakeng-Regular">
- NotoSerifNyiakengPuachueHmong-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
- <family lang="und-Yezi">
- <font weight="400" style="normal" postScriptName="NotoSerifYezidi-Regular">
- NotoSerifYezidi-VF.ttf
- <axis tag="wght" stylevalue="400"/>
- </font>
- <font weight="500" style="normal" postScriptName="NotoSerifYezidi-Regular">
- NotoSerifYezidi-VF.ttf
- <axis tag="wght" stylevalue="500"/>
- </font>
- <font weight="600" style="normal" postScriptName="NotoSerifYezidi-Regular">
- NotoSerifYezidi-VF.ttf
- <axis tag="wght" stylevalue="600"/>
- </font>
- <font weight="700" style="normal" postScriptName="NotoSerifYezidi-Regular">
- NotoSerifYezidi-VF.ttf
- <axis tag="wght" stylevalue="700"/>
- </font>
- </family>
-</familyset>
diff --git a/keystore/java/android/security/OWNERS b/keystore/java/android/security/OWNERS
index 32759b2402a9..43052866b938 100644
--- a/keystore/java/android/security/OWNERS
+++ b/keystore/java/android/security/OWNERS
@@ -1,2 +1,2 @@
-per-file *.java,*.aidl = eranm@google.com,pgrafov@google.com,rubinxu@google.com
+per-file *.java,*.aidl = drysdale@google.com,jbires@google.com,pgrafov@google.com,rubinxu@google.com
per-file KeyStoreManager.java = mpgroover@google.com
diff --git a/keystore/tests/OWNERS b/keystore/tests/OWNERS
index 86c31f403da0..0f94ddcee47f 100644
--- a/keystore/tests/OWNERS
+++ b/keystore/tests/OWNERS
@@ -1,4 +1,7 @@
+# Android HW Trust team
+drysdale@google.com
+jbires@google.com
+
# Android Enterprise security team
-eranm@google.com
pgrafov@google.com
rubinxu@google.com
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
index a3d2d7f4dcdf..438532725686 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/area/WindowAreaComponentImpl.java
@@ -16,6 +16,10 @@
package androidx.window.extensions.area;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FEATURE_REAR_DISPLAY;
+import static android.hardware.devicestate.DeviceState.PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY;
+import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE_IDENTIFIER;
import android.app.Activity;
@@ -23,6 +27,7 @@ import android.content.Context;
import android.hardware.devicestate.DeviceState;
import android.hardware.devicestate.DeviceStateManager;
import android.hardware.devicestate.DeviceStateRequest;
+import android.hardware.devicestate.feature.flags.Flags;
import android.hardware.display.DisplayManager;
import android.util.ArraySet;
import android.util.DisplayMetrics;
@@ -72,18 +77,18 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
@GuardedBy("mLock")
private final ArraySet<Consumer<ExtensionWindowAreaStatus>>
mRearDisplayPresentationStatusListeners = new ArraySet<>();
- private final int mRearDisplayState;
+ private int mRearDisplayState = INVALID_DEVICE_STATE_IDENTIFIER;
private final int mConcurrentDisplayState;
@NonNull
- private final int[] mFoldedDeviceStates;
+ private int[] mFoldedDeviceStates = new int[0];
private long mRearDisplayAddress = INVALID_DISPLAY_ADDRESS;
@WindowAreaSessionState
private int mRearDisplaySessionStatus = WindowAreaComponent.SESSION_STATE_INACTIVE;
@GuardedBy("mLock")
- private int mCurrentDeviceState = INVALID_DEVICE_STATE_IDENTIFIER;
+ private DeviceState mCurrentDeviceState = INVALID_DEVICE_STATE;
@GuardedBy("mLock")
- private int[] mCurrentSupportedDeviceStates;
+ private List<DeviceState> mCurrentSupportedDeviceStates;
@GuardedBy("mLock")
private DeviceStateRequest mRearDisplayStateRequest;
@@ -103,16 +108,25 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
mDisplayManager = context.getSystemService(DisplayManager.class);
mExecutor = context.getMainExecutor();
- // TODO(b/329436166): Update the usage of device state manager API's
- mCurrentSupportedDeviceStates = getSupportedStateIdentifiers(
- mDeviceStateManager.getSupportedDeviceStates());
- mFoldedDeviceStates = context.getResources().getIntArray(
- R.array.config_foldedDeviceStates);
+ mCurrentSupportedDeviceStates = mDeviceStateManager.getSupportedDeviceStates();
- // TODO(b/236022708) Move rear display state to device state config file
- mRearDisplayState = context.getResources().getInteger(
- R.integer.config_deviceStateRearDisplay);
+ if (Flags.deviceStatePropertyMigration()) {
+ for (int i = 0; i < mCurrentSupportedDeviceStates.size(); i++) {
+ DeviceState state = mCurrentSupportedDeviceStates.get(i);
+ if (state.hasProperty(PROPERTY_FEATURE_REAR_DISPLAY)) {
+ mRearDisplayState = state.getIdentifier();
+ break;
+ }
+ }
+ } else {
+ mFoldedDeviceStates = context.getResources().getIntArray(
+ R.array.config_foldedDeviceStates);
+ // TODO(b/236022708) Move rear display state to device state config file
+ mRearDisplayState = context.getResources().getInteger(
+ R.integer.config_deviceStateRearDisplay);
+ }
+ // TODO(b/374351956) Use DeviceState API when the dual display state is always returned
mConcurrentDisplayState = context.getResources().getInteger(
R.integer.config_deviceStateConcurrentRearDisplay);
@@ -147,7 +161,7 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
mRearDisplayStatusListeners.add(consumer);
// If current device state is still invalid, the initial value has not been provided.
- if (mCurrentDeviceState == INVALID_DEVICE_STATE_IDENTIFIER) {
+ if (mCurrentDeviceState.getIdentifier() == INVALID_DEVICE_STATE_IDENTIFIER) {
return;
}
consumer.accept(getCurrentRearDisplayModeStatus());
@@ -312,7 +326,7 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
mRearDisplayPresentationStatusListeners.add(consumer);
// If current device state is still invalid, the initial value has not been provided
- if (mCurrentDeviceState == INVALID_DEVICE_STATE_IDENTIFIER) {
+ if (mCurrentDeviceState.getIdentifier() == INVALID_DEVICE_STATE_IDENTIFIER) {
return;
}
@WindowAreaStatus int currentStatus = getCurrentRearDisplayPresentationModeStatus();
@@ -452,8 +466,7 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
@Override
public void onSupportedStatesChanged(@NonNull List<DeviceState> supportedStates) {
synchronized (mLock) {
- // TODO(b/329436166): Update the usage of device state manager API's
- mCurrentSupportedDeviceStates = getSupportedStateIdentifiers(supportedStates);
+ mCurrentSupportedDeviceStates = supportedStates;
updateRearDisplayStatusListeners(getCurrentRearDisplayModeStatus());
updateRearDisplayPresentationStatusListeners(
getCurrentRearDisplayPresentationModeStatus());
@@ -463,8 +476,7 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
@Override
public void onDeviceStateChanged(@NonNull DeviceState state) {
synchronized (mLock) {
- // TODO(b/329436166): Update the usage of device state manager API's
- mCurrentDeviceState = state.getIdentifier();
+ mCurrentDeviceState = state;
updateRearDisplayStatusListeners(getCurrentRearDisplayModeStatus());
updateRearDisplayPresentationStatusListeners(
getCurrentRearDisplayPresentationModeStatus());
@@ -477,7 +489,8 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
return WindowAreaComponent.STATUS_UNSUPPORTED;
}
- if (!ArrayUtils.contains(mCurrentSupportedDeviceStates, mRearDisplayState)) {
+ if (!deviceStateListContainsIdentifier(mCurrentSupportedDeviceStates,
+ mRearDisplayState)) {
return WindowAreaComponent.STATUS_UNAVAILABLE;
}
@@ -488,15 +501,6 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
return WindowAreaComponent.STATUS_AVAILABLE;
}
- // TODO(b/329436166): Remove and update the usage of device state manager API's
- private int[] getSupportedStateIdentifiers(@NonNull List<DeviceState> states) {
- int[] identifiers = new int[states.size()];
- for (int i = 0; i < states.size(); i++) {
- identifiers[i] = states.get(i).getIdentifier();
- }
- return identifiers;
- }
-
/**
* Helper method to determine if a rear display session is currently active by checking
* if the current device state is that which corresponds to {@code mRearDisplayState}.
@@ -505,7 +509,31 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
*/
@GuardedBy("mLock")
private boolean isRearDisplayActive() {
- return mCurrentDeviceState == mRearDisplayState;
+ if (Flags.deviceStatePropertyApi()) {
+ return mCurrentDeviceState.hasProperty(PROPERTY_FEATURE_REAR_DISPLAY);
+ } else {
+ return mCurrentDeviceState.getIdentifier() == mRearDisplayState;
+ }
+ }
+
+ @GuardedBy("mLock")
+ private boolean isRearDisplayPresentationModeActive() {
+ if (Flags.deviceStatePropertyApi()) {
+ return mCurrentDeviceState.hasProperty(PROPERTY_FEATURE_DUAL_DISPLAY_INTERNAL_DEFAULT);
+ } else {
+ return mCurrentDeviceState.getIdentifier() == mConcurrentDisplayState;
+ }
+ }
+
+ @GuardedBy("mLock")
+ private boolean deviceStateListContainsIdentifier(List<DeviceState> deviceStates,
+ int identifier) {
+ for (int i = 0; i < deviceStates.size(); i++) {
+ if (deviceStates.get(i).getIdentifier() == identifier) {
+ return true;
+ }
+ }
+ return false;
}
@GuardedBy("mLock")
@@ -526,12 +554,12 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
return WindowAreaComponent.STATUS_UNSUPPORTED;
}
- if (mCurrentDeviceState == mConcurrentDisplayState) {
+ if (isRearDisplayPresentationModeActive()) {
return WindowAreaComponent.STATUS_ACTIVE;
}
- if (!ArrayUtils.contains(mCurrentSupportedDeviceStates, mConcurrentDisplayState)
- || isDeviceFolded()) {
+ if (!deviceStateListContainsIdentifier(mCurrentSupportedDeviceStates,
+ mConcurrentDisplayState) || isDeviceFolded()) {
return WindowAreaComponent.STATUS_UNAVAILABLE;
}
return WindowAreaComponent.STATUS_AVAILABLE;
@@ -539,7 +567,12 @@ public class WindowAreaComponentImpl implements WindowAreaComponent,
@GuardedBy("mLock")
private boolean isDeviceFolded() {
- return ArrayUtils.contains(mFoldedDeviceStates, mCurrentDeviceState);
+ if (Flags.deviceStatePropertyApi()) {
+ return mCurrentDeviceState.hasProperty(
+ PROPERTY_FOLDABLE_DISPLAY_CONFIGURATION_OUTER_PRIMARY);
+ } else {
+ return ArrayUtils.contains(mFoldedDeviceStates, mCurrentDeviceState.getIdentifier());
+ }
}
@GuardedBy("mLock")
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
index 6ad2f088ce95..220fc6f82a71 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java
@@ -54,6 +54,7 @@ class BackupHelper {
@NonNull
private final BackupIdler mBackupIdler = new BackupIdler();
private boolean mBackupIdlerScheduled;
+ private boolean mSaveEmbeddingState = false;
private final List<ParcelableTaskContainerData> mParcelableTaskContainerDataList =
new ArrayList<>();
@@ -71,11 +72,32 @@ class BackupHelper {
}
}
+ void setAutoSaveEmbeddingState(boolean saveEmbeddingState) {
+ if (mSaveEmbeddingState == saveEmbeddingState) {
+ return;
+ }
+
+ Log.i(TAG, "Set save embedding state: " + saveEmbeddingState);
+ mSaveEmbeddingState = saveEmbeddingState;
+ if (!mSaveEmbeddingState) {
+ removeSavedState();
+ return;
+ }
+
+ if (!hasPendingStateToRestore() && !mController.getTaskContainers().isEmpty()) {
+ scheduleBackup();
+ }
+ }
/**
* Schedules a back-up request. It is no-op if there was a request scheduled and not yet
* completed.
*/
void scheduleBackup() {
+ if (!mSaveEmbeddingState) {
+ // TODO(b/289875940): enabled internally for broader testing.
+ return;
+ }
+
if (!mBackupIdlerScheduled) {
mBackupIdlerScheduled = true;
Looper.getMainLooper().getQueue().addIdleHandler(mBackupIdler);
@@ -128,7 +150,6 @@ class BackupHelper {
final List<TaskFragmentInfo> infos = savedState.getParcelableArrayList(
KEY_RESTORE_TASK_FRAGMENTS_INFO, TaskFragmentInfo.class);
for (TaskFragmentInfo info : infos) {
- if (DEBUG) Log.d(TAG, "Retrieved: " + info);
mTaskFragmentInfos.put(info.getFragmentToken(), info);
mPresenter.updateTaskFragmentInfo(info);
}
@@ -140,6 +161,11 @@ class BackupHelper {
if (DEBUG) Log.d(TAG, "Retrieved: " + info);
mTaskFragmentParentInfos.put(info.getTaskId(), info);
}
+
+ if (DEBUG) {
+ Log.d(TAG, "Retrieved task-fragment info: " + infos.size() + ", task info: "
+ + parentInfos.size());
+ }
}
void abortTaskContainerRebuilding(@NonNull WindowContainerTransaction wct) {
@@ -148,7 +174,6 @@ class BackupHelper {
final TaskFragmentInfo info = mTaskFragmentInfos.valueAt(i);
mPresenter.deleteTaskFragment(wct, info.getFragmentToken());
}
-
removeSavedState();
}
@@ -190,6 +215,9 @@ class BackupHelper {
final ArrayMap<String, EmbeddingRule> embeddingRuleMap = new ArrayMap<>();
for (EmbeddingRule rule : rules) {
embeddingRuleMap.put(rule.getTag(), rule);
+ if (DEBUG) {
+ Log.d(TAG, "Tag: " + rule.getTag() + " rule: " + rule);
+ }
}
boolean restoredAny = false;
@@ -201,7 +229,7 @@ class BackupHelper {
// has unknown tag, unable to restore.
if (DEBUG) {
Log.d(TAG, "Rebuilding TaskContainer abort! Unknown Tag. Task#"
- + parcelableTaskContainerData.mTaskId);
+ + parcelableTaskContainerData.mTaskId + ", tags = " + tags);
}
continue;
}
@@ -217,7 +245,7 @@ class BackupHelper {
final TaskContainer taskContainer = new TaskContainer(parcelableTaskContainerData,
mController, mTaskFragmentInfos);
- if (DEBUG) Log.d(TAG, "Created TaskContainer " + taskContainer);
+ if (DEBUG) Log.d(TAG, "Created TaskContainer " + taskContainer.getTaskId());
mController.addTaskContainer(taskContainer.getTaskId(), taskContainer);
for (ParcelableSplitContainerData splitData :
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 3368e2eab3ad..60e1a506ab73 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -2886,6 +2886,18 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
return getActiveSplitForContainer(container) != null;
}
+
+ @Override
+ public void setAutoSaveEmbeddingState(boolean saveEmbeddingState) {
+ if (!Flags.aeBackStackRestore()) {
+ return;
+ }
+
+ synchronized (mLock) {
+ mPresenter.setAutoSaveEmbeddingState(saveEmbeddingState);
+ }
+ }
+
void scheduleBackup() {
synchronized (mLock) {
mPresenter.scheduleBackup();
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index b498ee2ff438..9a2f32e9ee99 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -183,6 +183,10 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
}
}
+ void setAutoSaveEmbeddingState(boolean saveEmbeddingState) {
+ mBackupHelper.setAutoSaveEmbeddingState(saveEmbeddingState);
+ }
+
void scheduleBackup() {
mBackupHelper.scheduleBackup();
}
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index b453f1d4e936..6928409fd819 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -48,8 +48,6 @@ import androidx.window.extensions.embedding.SplitAttributes.SplitType;
import androidx.window.extensions.embedding.SplitAttributes.SplitType.ExpandContainersSplitType;
import androidx.window.extensions.embedding.SplitAttributes.SplitType.RatioSplitType;
-import com.android.window.flags.Flags;
-
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -634,11 +632,7 @@ class TaskContainer {
// pin container.
updateAlwaysOnTopOverlayIfNecessary();
- // TODO(b/289875940): Making backup-restore as an opt-in solution, before the flag goes
- // to next-food.
- if (Flags.aeBackStackRestore()) {
- mSplitController.scheduleBackup();
- }
+ mSplitController.scheduleBackup();
}
private void updateAlwaysOnTopOverlayIfNecessary() {
diff --git a/libs/WindowManager/Shell/AndroidManifest.xml b/libs/WindowManager/Shell/AndroidManifest.xml
index 1260796810c2..b2ac640a468d 100644
--- a/libs/WindowManager/Shell/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/AndroidManifest.xml
@@ -25,6 +25,7 @@
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
<uses-permission android:name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE" />
<uses-permission android:name="android.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION" />
+ <uses-permission android:name="android.permission.MANAGE_KEY_GESTURES" />
<application>
<activity
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/UiEventSubject.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/UiEventSubject.kt
new file mode 100644
index 000000000000..2d6df43f67e0
--- /dev/null
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/UiEventSubject.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2024 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.bubbles
+
+import com.android.internal.logging.testing.UiEventLoggerFake.FakeUiEvent
+import com.google.common.truth.FailureMetadata
+import com.google.common.truth.Subject
+import com.google.common.truth.Truth
+
+/** Subclass of [Subject] to simplify verifying [FakeUiEvent] data */
+class UiEventSubject(metadata: FailureMetadata, private val actual: FakeUiEvent) :
+ Subject(metadata, actual) {
+
+ /** Check that [FakeUiEvent] contains the expected data from the [bubble] passed id */
+ fun hasBubbleInfo(bubble: Bubble) {
+ check("uid").that(actual.uid).isEqualTo(bubble.appUid)
+ check("packageName").that(actual.packageName).isEqualTo(bubble.packageName)
+ check("instanceId").that(actual.instanceId).isEqualTo(bubble.instanceId)
+ }
+
+ companion object {
+ @JvmStatic
+ fun assertThat(event: FakeUiEvent): UiEventSubject =
+ Truth.assertAbout(Factory(::UiEventSubject)).that(event)
+ }
+}
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/UiEventSubjectTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/UiEventSubjectTest.kt
new file mode 100644
index 000000000000..af238d033aee
--- /dev/null
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/UiEventSubjectTest.kt
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2024 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.bubbles
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.InstanceId
+import com.android.internal.logging.testing.UiEventLoggerFake
+import com.android.internal.logging.testing.UiEventLoggerFake.FakeUiEvent
+import com.android.wm.shell.bubbles.UiEventSubject.Companion.assertThat
+import com.google.common.truth.ExpectFailure.assertThat
+import com.google.common.truth.ExpectFailure.expectFailure
+import com.google.common.truth.Subject
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.mock
+import org.mockito.kotlin.whenever
+
+/** Test for [UiEventSubject] */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class UiEventSubjectTest {
+
+ private val uiEventSubjectFactory =
+ Subject.Factory<UiEventSubject, FakeUiEvent> { metadata, actual ->
+ UiEventSubject(metadata, actual)
+ }
+
+ private lateinit var uiEventLoggerFake: UiEventLoggerFake
+
+ @Before
+ fun setUp() {
+ uiEventLoggerFake = UiEventLoggerFake()
+ }
+
+ @Test
+ fun test_bubbleLogEvent_hasBubbleInfo() {
+ val bubble =
+ createBubble(
+ appUid = 1,
+ packageName = "test",
+ instanceId = InstanceId.fakeInstanceId(2),
+ )
+ BubbleLogger(uiEventLoggerFake).log(bubble, BubbleLogger.Event.BUBBLE_BAR_BUBBLE_POSTED)
+ val uiEvent = uiEventLoggerFake.logs.first()
+
+ // Check that fields match the expected values
+ assertThat(uiEvent.uid).isEqualTo(1)
+ assertThat(uiEvent.packageName).isEqualTo("test")
+ assertThat(uiEvent.instanceId.id).isEqualTo(2)
+
+ // Check that hasBubbleInfo condition passes
+ assertThat(uiEvent).hasBubbleInfo(bubble)
+ }
+
+ @Test
+ fun test_bubbleLogEvent_uidMismatch() {
+ val bubble =
+ createBubble(
+ appUid = 1,
+ packageName = "test",
+ instanceId = InstanceId.fakeInstanceId(2),
+ )
+ BubbleLogger(uiEventLoggerFake).log(bubble, BubbleLogger.Event.BUBBLE_BAR_BUBBLE_POSTED)
+ val uiEvent = uiEventLoggerFake.logs.first()
+
+ // Change uid to have a mismatch
+ val otherBubble = bubble.copy(appUid = 99)
+
+ val failure = expectFailure { test ->
+ test.about(uiEventSubjectFactory).that(uiEvent).hasBubbleInfo(otherBubble)
+ }
+ assertThat(failure).factValue("value of").isEqualTo("uiEvent.uid")
+ }
+
+ @Test
+ fun test_bubbleLogEvent_packageNameMismatch() {
+ val bubble =
+ createBubble(
+ appUid = 1,
+ packageName = "test",
+ instanceId = InstanceId.fakeInstanceId(2),
+ )
+ BubbleLogger(uiEventLoggerFake).log(bubble, BubbleLogger.Event.BUBBLE_BAR_BUBBLE_POSTED)
+ val uiEvent = uiEventLoggerFake.logs.first()
+
+ // Change package name to have a mismatch
+ val otherBubble = bubble.copy(packageName = "somethingelse")
+
+ val failure = expectFailure { test ->
+ test.about(uiEventSubjectFactory).that(uiEvent).hasBubbleInfo(otherBubble)
+ }
+ assertThat(failure).factValue("value of").isEqualTo("uiEvent.packageName")
+ }
+
+ @Test
+ fun test_bubbleLogEvent_instanceIdMismatch() {
+ val bubble =
+ createBubble(
+ appUid = 1,
+ packageName = "test",
+ instanceId = InstanceId.fakeInstanceId(2),
+ )
+ BubbleLogger(uiEventLoggerFake).log(bubble, BubbleLogger.Event.BUBBLE_BAR_BUBBLE_POSTED)
+ val uiEvent = uiEventLoggerFake.logs.first()
+
+ // Change instance id to have a mismatch
+ val otherBubble = bubble.copy(instanceId = InstanceId.fakeInstanceId(99))
+
+ val failure = expectFailure { test ->
+ test.about(uiEventSubjectFactory).that(uiEvent).hasBubbleInfo(otherBubble)
+ }
+ assertThat(failure).factValue("value of").isEqualTo("uiEvent.instanceId")
+ }
+
+ private fun createBubble(appUid: Int, packageName: String, instanceId: InstanceId): Bubble {
+ return mock(Bubble::class.java).apply {
+ whenever(getAppUid()).thenReturn(appUid)
+ whenever(getPackageName()).thenReturn(packageName)
+ whenever(getInstanceId()).thenReturn(instanceId)
+ }
+ }
+
+ private fun Bubble.copy(
+ appUid: Int = this.appUid,
+ packageName: String = this.packageName,
+ instanceId: InstanceId = this.instanceId,
+ ): Bubble {
+ return createBubble(appUid, packageName, instanceId)
+ }
+}
diff --git a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt
index fa9d2baa78d9..08d647de4a51 100644
--- a/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt
+++ b/libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/bar/BubbleBarExpandedViewTest.kt
@@ -40,6 +40,7 @@ import com.android.wm.shell.bubbles.BubbleTaskView
import com.android.wm.shell.bubbles.BubbleTaskViewFactory
import com.android.wm.shell.bubbles.DeviceConfig
import com.android.wm.shell.bubbles.RegionSamplingProvider
+import com.android.wm.shell.bubbles.UiEventSubject.Companion.assertThat
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.shared.bubbles.BubbleBarLocation
import com.android.wm.shell.shared.handles.RegionSamplingHelper
@@ -47,16 +48,14 @@ import com.android.wm.shell.taskview.TaskView
import com.android.wm.shell.taskview.TaskViewTaskController
import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.MoreExecutors.directExecutor
+import java.util.Collections
+import java.util.concurrent.Executor
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.mock
-import org.mockito.kotlin.spy
-import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
-import java.util.Collections
-import java.util.concurrent.Executor
/** Tests for [BubbleBarExpandedViewTest] */
@SmallTest
@@ -82,7 +81,7 @@ class BubbleBarExpandedViewTest {
private var testableRegionSamplingHelper: TestableRegionSamplingHelper? = null
private var regionSamplingProvider: TestRegionSamplingProvider? = null
- private val bubbleLogger = spy(BubbleLogger(UiEventLoggerFake()))
+ private val uiEventLoggerFake = UiEventLoggerFake()
@Before
fun setUp() {
@@ -116,7 +115,7 @@ class BubbleBarExpandedViewTest {
bubbleExpandedView.initialize(
expandedViewManager,
positioner,
- bubbleLogger,
+ BubbleLogger(uiEventLoggerFake),
false /* isOverflow */,
bubbleTaskView,
mainExecutor,
@@ -223,7 +222,10 @@ class BubbleBarExpandedViewTest {
bubbleExpandedView.findViewWithTag<View>(BubbleBarMenuView.DISMISS_ACTION_TAG)
assertThat(dismissMenuItem).isNotNull()
getInstrumentation().runOnMainSync { dismissMenuItem.performClick() }
- verify(bubbleLogger).log(bubble, BubbleLogger.Event.BUBBLE_BAR_BUBBLE_DISMISSED_APP_MENU)
+ assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
+ assertThat(uiEventLoggerFake.logs[0].eventId)
+ .isEqualTo(BubbleLogger.Event.BUBBLE_BAR_BUBBLE_DISMISSED_APP_MENU.id)
+ assertThat(uiEventLoggerFake.logs[0]).hasBubbleInfo(bubble)
}
private inner class FakeBubbleTaskViewFactory : BubbleTaskViewFactory {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
index 9ca9b730fb06..4569cf31dab1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationRunner.java
@@ -26,6 +26,7 @@ import android.util.Log;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationTarget;
+import android.view.SurfaceControl;
import android.window.IBackAnimationRunner;
import android.window.IOnBackInvokedCallback;
@@ -34,6 +35,8 @@ import com.android.internal.jank.Cuj.CujType;
import com.android.internal.jank.InteractionJankMonitor;
import com.android.wm.shell.shared.annotations.ShellMainThread;
+import java.lang.ref.WeakReference;
+
/**
* Used to register the animation callback and runner, it will trigger result if gesture was finish
* before it received IBackAnimationRunner#onAnimationStart, so the controller could continue
@@ -101,6 +104,40 @@ public class BackAnimationRunner {
return mCallback;
}
+ private Runnable mFinishedCallback;
+ private RemoteAnimationTarget[] mApps;
+ private IRemoteAnimationFinishedCallback mRemoteCallback;
+
+ private static class RemoteAnimationFinishedStub extends IRemoteAnimationFinishedCallback.Stub {
+ //the binder callback should not hold strong reference to it to avoid memory leak.
+ private WeakReference<BackAnimationRunner> mRunnerRef;
+
+ private RemoteAnimationFinishedStub(BackAnimationRunner runner) {
+ mRunnerRef = new WeakReference<>(runner);
+ }
+
+ @Override
+ public void onAnimationFinished() {
+ BackAnimationRunner runner = mRunnerRef.get();
+ if (runner == null) {
+ return;
+ }
+ if (runner.shouldMonitorCUJ(runner.mApps)) {
+ InteractionJankMonitor.getInstance().end(runner.mCujType);
+ }
+
+ runner.mFinishedCallback.run();
+ for (int i = runner.mApps.length - 1; i >= 0; --i) {
+ SurfaceControl sc = runner.mApps[i].leash;
+ if (sc != null && sc.isValid()) {
+ sc.release();
+ }
+ }
+ runner.mApps = null;
+ runner.mFinishedCallback = null;
+ }
+ }
+
/**
* Called from {@link IBackAnimationRunner}, it will deliver these
* {@link RemoteAnimationTarget}s to the corresponding runner.
@@ -108,16 +145,9 @@ public class BackAnimationRunner {
void startAnimation(RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers,
RemoteAnimationTarget[] nonApps, Runnable finishedCallback) {
InteractionJankMonitor interactionJankMonitor = InteractionJankMonitor.getInstance();
- final IRemoteAnimationFinishedCallback callback =
- new IRemoteAnimationFinishedCallback.Stub() {
- @Override
- public void onAnimationFinished() {
- if (shouldMonitorCUJ(apps)) {
- interactionJankMonitor.end(mCujType);
- }
- finishedCallback.run();
- }
- };
+ mFinishedCallback = finishedCallback;
+ mApps = apps;
+ if (mRemoteCallback == null) mRemoteCallback = new RemoteAnimationFinishedStub(this);
mWaitingAnimation = false;
if (shouldMonitorCUJ(apps)) {
interactionJankMonitor.begin(
@@ -125,7 +155,7 @@ public class BackAnimationRunner {
}
try {
getRunner().onAnimationStart(TRANSIT_OLD_UNSET, apps, wallpapers,
- nonApps, callback);
+ nonApps, mRemoteCallback);
} catch (RemoteException e) {
Log.w(TAG, "Failed call onAnimationStart", e);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 03a851bb9507..4c2588984500 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -24,6 +24,7 @@ import android.annotation.Nullable;
import android.app.KeyguardManager;
import android.content.Context;
import android.content.pm.LauncherApps;
+import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.UserManager;
import android.view.Choreographer;
@@ -266,7 +267,8 @@ public abstract class WMShellModule {
AppHandleEducationController appHandleEducationController,
WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
Optional<DesktopActivityOrientationChangeHandler> desktopActivityOrientationHandler,
- FocusTransitionObserver focusTransitionObserver) {
+ FocusTransitionObserver focusTransitionObserver,
+ DesktopModeEventLogger desktopModeEventLogger) {
if (DesktopModeStatus.canEnterDesktopMode(context)) {
return new DesktopModeWindowDecorViewModel(
context,
@@ -294,7 +296,8 @@ public abstract class WMShellModule {
appHandleEducationController,
windowDecorCaptionHandleRepository,
desktopActivityOrientationHandler,
- focusTransitionObserver);
+ focusTransitionObserver,
+ desktopModeEventLogger);
}
return new CaptionWindowDecorViewModel(
context,
@@ -644,7 +647,10 @@ public abstract class WMShellModule {
@ShellMainThread Handler mainHandler,
Optional<DesktopTasksLimiter> desktopTasksLimiter,
Optional<RecentTasksController> recentTasksController,
- InteractionJankMonitor interactionJankMonitor) {
+ InteractionJankMonitor interactionJankMonitor,
+ InputManager inputManager,
+ FocusTransitionObserver focusTransitionObserver,
+ DesktopModeEventLogger desktopModeEventLogger) {
return new DesktopTasksController(context, shellInit, shellCommandHandler, shellController,
displayController, shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer,
dragAndDropController, transitions, keyguardManager,
@@ -655,7 +661,9 @@ public abstract class WMShellModule {
desktopRepository,
desktopModeLoggerTransitionObserver, launchAdjacentController,
recentsTransitionHandler, multiInstanceHelper, mainExecutor, desktopTasksLimiter,
- recentTasksController.orElse(null), interactionJankMonitor, mainHandler);
+ recentTasksController.orElse(null), interactionJankMonitor, mainHandler,
+ inputManager, focusTransitionObserver,
+ desktopModeEventLogger);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandler.kt
index 320c003f41eb..9d4926b47def 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandler.kt
@@ -71,7 +71,7 @@ class DesktopFullImmersiveTransitionHandler(
/** Whether there is an immersive transition that hasn't completed yet. */
private val inProgress: Boolean
- get() = state != null
+ get() = state != null || pendingExternalExitTransitions.isNotEmpty()
private val rectEvaluator = RectEvaluator()
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
index 435019929cbd..df9fc59b925e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandler.kt
@@ -58,9 +58,9 @@ class DesktopMixedTransitionHandler(
freeformTaskTransitionHandler.startMinimizedModeTransition(wct)
/** Starts close transition and handles or delegates desktop task close animation. */
- override fun startRemoveTransition(wct: WindowContainerTransaction?) {
+ override fun startRemoveTransition(wct: WindowContainerTransaction?): IBinder {
requireNotNull(wct)
- transitions.startTransition(WindowManager.TRANSIT_CLOSE, wct, /* handler= */ this)
+ return transitions.startTransition(WindowManager.TRANSIT_CLOSE, wct, /* handler= */ this)
}
/** Returns null, as it only handles transitions started from Shell. */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
index 8ebe503a3816..255ca6e2511f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeEventLogger.kt
@@ -16,11 +16,20 @@
package com.android.wm.shell.desktopmode
+import android.app.ActivityManager.RunningTaskInfo
+import android.util.Size
+import android.view.InputDevice.SOURCE_MOUSE
+import android.view.InputDevice.SOURCE_TOUCHSCREEN
+import android.view.MotionEvent
+import android.view.MotionEvent.TOOL_TYPE_FINGER
+import android.view.MotionEvent.TOOL_TYPE_MOUSE
+import android.view.MotionEvent.TOOL_TYPE_STYLUS
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.protolog.ProtoLog
import com.android.internal.util.FrameworkStatsLog
import com.android.window.flags.Flags
import com.android.wm.shell.EventLogTags
+import com.android.wm.shell.common.DisplayController
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
import java.security.SecureRandom
import java.util.Random
@@ -176,7 +185,13 @@ class DesktopModeEventLogger {
* Logs that a task resize event is starting with [taskSizeUpdate] within a Desktop mode
* session.
*/
- fun logTaskResizingStarted(taskSizeUpdate: TaskSizeUpdate) {
+ fun logTaskResizingStarted(
+ resizeTrigger: ResizeTrigger,
+ motionEvent: MotionEvent?,
+ taskInfo: RunningTaskInfo,
+ displayController: DisplayController? = null,
+ displayLayoutSize: Size? = null,
+ ) {
if (!Flags.enableResizingMetrics()) return
val sessionId = currentSessionId.get()
@@ -188,11 +203,19 @@ class DesktopModeEventLogger {
return
}
+ val taskSizeUpdate = createTaskSizeUpdate(
+ resizeTrigger,
+ motionEvent,
+ taskInfo,
+ displayController = displayController,
+ displayLayoutSize = displayLayoutSize,
+ )
+
ProtoLog.v(
WM_SHELL_DESKTOP_MODE,
- "DesktopModeLogger: Logging task resize is starting, session: %s taskId: %s",
+ "DesktopModeLogger: Logging task resize is starting, session: %s, taskSizeUpdate: %s",
sessionId,
- taskSizeUpdate.instanceId
+ taskSizeUpdate
)
logTaskSizeUpdated(
FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__START_RESIZING_STAGE,
@@ -203,7 +226,15 @@ class DesktopModeEventLogger {
/**
* Logs that a task resize event is ending with [taskSizeUpdate] within a Desktop mode session.
*/
- fun logTaskResizingEnded(taskSizeUpdate: TaskSizeUpdate) {
+ fun logTaskResizingEnded(
+ resizeTrigger: ResizeTrigger,
+ motionEvent: MotionEvent?,
+ taskInfo: RunningTaskInfo,
+ taskHeight: Int? = null,
+ taskWidth: Int? = null,
+ displayController: DisplayController? = null,
+ displayLayoutSize: Size? = null,
+ ) {
if (!Flags.enableResizingMetrics()) return
val sessionId = currentSessionId.get()
@@ -215,18 +246,61 @@ class DesktopModeEventLogger {
return
}
+ val taskSizeUpdate = createTaskSizeUpdate(
+ resizeTrigger,
+ motionEvent,
+ taskInfo,
+ taskHeight,
+ taskWidth,
+ displayController,
+ displayLayoutSize,
+ )
+
ProtoLog.v(
WM_SHELL_DESKTOP_MODE,
- "DesktopModeLogger: Logging task resize is ending, session: %s taskId: %s",
+ "DesktopModeLogger: Logging task resize is ending, session: %s, taskSizeUpdate: %s",
sessionId,
- taskSizeUpdate.instanceId
+ taskSizeUpdate
)
+
logTaskSizeUpdated(
FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__END_RESIZING_STAGE,
sessionId, taskSizeUpdate
)
}
+ private fun createTaskSizeUpdate(
+ resizeTrigger: ResizeTrigger,
+ motionEvent: MotionEvent?,
+ taskInfo: RunningTaskInfo,
+ taskHeight: Int? = null,
+ taskWidth: Int? = null,
+ displayController: DisplayController? = null,
+ displayLayoutSize: Size? = null,
+ ): TaskSizeUpdate {
+ val taskBounds = taskInfo.configuration.windowConfiguration.bounds
+
+ val height = taskHeight ?: taskBounds.height()
+ val width = taskWidth ?: taskBounds.width()
+
+ val displaySize = when {
+ displayLayoutSize != null -> displayLayoutSize.height * displayLayoutSize.width
+ displayController != null -> displayController.getDisplayLayout(taskInfo.displayId)
+ ?.let { it.height() * it.width() }
+ else -> null
+ }
+
+ return TaskSizeUpdate(
+ resizeTrigger,
+ getInputMethodFromMotionEvent(motionEvent),
+ taskInfo.taskId,
+ taskInfo.effectiveUid,
+ height,
+ width,
+ displaySize,
+ )
+ }
+
fun logTaskInfoStateInit() {
logTaskUpdate(
FrameworkStatsLog.DESKTOP_MODE_SESSION_TASK_UPDATE__TASK_EVENT__TASK_INIT_STATSD,
@@ -238,7 +312,8 @@ class DesktopModeEventLogger {
taskHeight = 0,
taskWidth = 0,
taskX = 0,
- taskY = 0)
+ taskY = 0
+ )
)
}
@@ -314,7 +389,7 @@ class DesktopModeEventLogger {
/* task_width */
taskSizeUpdate.taskWidth,
/* display_area */
- taskSizeUpdate.displayArea
+ taskSizeUpdate.displayArea ?: -1
)
}
@@ -364,9 +439,24 @@ class DesktopModeEventLogger {
val uid: Int,
val taskHeight: Int,
val taskWidth: Int,
- val displayArea: Int,
+ val displayArea: Int?,
)
+ private fun getInputMethodFromMotionEvent(e: MotionEvent?): InputMethod {
+ if (e == null) return InputMethod.UNKNOWN_INPUT_METHOD
+
+ val toolType = e.getToolType(
+ e.findPointerIndex(e.getPointerId(0))
+ )
+ return when {
+ toolType == TOOL_TYPE_STYLUS -> InputMethod.STYLUS
+ toolType == TOOL_TYPE_MOUSE -> InputMethod.MOUSE
+ toolType == TOOL_TYPE_FINGER && e.source == SOURCE_MOUSE -> InputMethod.TOUCHPAD
+ toolType == TOOL_TYPE_FINGER && e.source == SOURCE_TOUCHSCREEN -> InputMethod.TOUCH
+ else -> InputMethod.UNKNOWN_INPUT_METHOD
+ }
+ }
+
// Default value used when the task was not minimized.
@VisibleForTesting
const val UNSET_MINIMIZE_REASON =
@@ -499,6 +589,10 @@ class DesktopModeEventLogger {
FrameworkStatsLog
.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__SNAP_RIGHT_MENU_RESIZE_TRIGGER
),
+ MAXIMIZE_MENU(
+ FrameworkStatsLog
+ .DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__MAXIMIZE_MENU_RESIZE_TRIGGER
+ ),
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
index eeb7ac852070..85a3126d9de6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopRepository.kt
@@ -30,7 +30,6 @@ import androidx.core.util.valueIterator
import com.android.internal.protolog.ProtoLog
import com.android.window.flags.Flags
import com.android.wm.shell.desktopmode.persistence.DesktopPersistentRepository
-import com.android.wm.shell.desktopmode.persistence.DesktopTask
import com.android.wm.shell.desktopmode.persistence.DesktopTaskState
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
import com.android.wm.shell.shared.annotations.ShellMainThread
@@ -124,7 +123,8 @@ class DesktopRepository (
if (!Flags.enableDesktopWindowingPersistence()) return
// TODO: b/365962554 - Handle the case that user moves to desktop before it's initialized
mainCoroutineScope.launch {
- val desktop = persistentRepository.readDesktop()
+ val desktop = persistentRepository.readDesktop() ?: return@launch
+
val maxTasks =
DesktopModeStatus.getMaxTaskLimit(context).takeIf { it > 0 }
?: desktop.zOrderedTasksCount
@@ -132,13 +132,11 @@ class DesktopRepository (
desktop.zOrderedTasksList
// Reverse it so we initialize the repo from bottom to top.
.reversed()
- .map { taskId ->
- desktop.tasksByTaskIdMap.getOrDefault(
- taskId,
- DesktopTask.getDefaultInstance()
- )
+ .mapNotNull { taskId ->
+ desktop.tasksByTaskIdMap[taskId]?.takeIf {
+ it.desktopTaskState == DesktopTaskState.VISIBLE
+ }
}
- .filter { task -> task.desktopTaskState == DesktopTaskState.VISIBLE }
.take(maxTasks)
.forEach { task ->
addOrMoveFreeformTaskToTop(desktop.displayId, task.taskId)
@@ -522,6 +520,7 @@ class DesktopRepository (
"${innerPrefix}freeformTasksInZOrder=${data.freeformTasksInZOrder.toDumpString()}"
)
pw.println("${innerPrefix}minimizedTasks=${data.minimizedTasks.toDumpString()}")
+ pw.println("${innerPrefix}fullImmersiveTaskId=${data.fullImmersiveTaskId}")
}
}
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 29e302a0f0cc..69776cd4740a 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
@@ -35,6 +35,9 @@ import android.graphics.Point
import android.graphics.PointF
import android.graphics.Rect
import android.graphics.Region
+import android.hardware.input.InputManager
+import android.hardware.input.InputManager.KeyGestureEventHandler
+import android.hardware.input.KeyGestureEvent
import android.os.Binder
import android.os.Handler
import android.os.IBinder
@@ -42,6 +45,8 @@ import android.os.SystemProperties
import android.util.Size
import android.view.Display.DEFAULT_DISPLAY
import android.view.DragEvent
+import android.view.KeyEvent
+import android.view.MotionEvent
import android.view.SurfaceControl
import android.view.WindowManager.TRANSIT_CHANGE
import android.view.WindowManager.TRANSIT_CLOSE
@@ -57,6 +62,7 @@ import android.window.TransitionInfo
import android.window.TransitionRequestInfo
import android.window.WindowContainerTransaction
import androidx.annotation.BinderThread
+import com.android.hardware.input.Flags.useKeyGestureEventHandler
import com.android.internal.annotations.VisibleForTesting
import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_HOLD
import com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_RELEASE
@@ -65,6 +71,7 @@ import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.policy.ScreenDecorationsUtils
import com.android.internal.protolog.ProtoLog
import com.android.window.flags.Flags
+import com.android.window.flags.Flags.enableMoveToNextDisplayShortcut
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.common.DisplayController
@@ -78,12 +85,13 @@ import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SingleInstanceRemoteListener
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.compatui.isTopActivityExemptFromDesktopWindowing
-import com.android.wm.shell.desktopmode.DesktopRepository.VisibleTasksListener
import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.DragStartState
import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType
+import com.android.wm.shell.desktopmode.DesktopRepository.VisibleTasksListener
import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.DragToDesktopStateListener
import com.android.wm.shell.desktopmode.minimize.DesktopWindowLimitRemoteHandler
import com.android.wm.shell.draganddrop.DragAndDropController
+import com.android.wm.shell.freeform.FreeformTaskTransitionStarter
import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE
import com.android.wm.shell.recents.RecentTasksController
import com.android.wm.shell.recents.RecentsTransitionHandler
@@ -92,7 +100,6 @@ import com.android.wm.shell.shared.ShellSharedConstants
import com.android.wm.shell.shared.TransitionUtil
import com.android.wm.shell.shared.annotations.ExternalThread
import com.android.wm.shell.shared.annotations.ShellMainThread
-import com.android.wm.shell.freeform.FreeformTaskTransitionStarter
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.DESKTOP_DENSITY_OVERRIDE
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus.useDesktopOverrideDensity
@@ -105,6 +112,7 @@ import com.android.wm.shell.sysui.ShellCommandHandler
import com.android.wm.shell.sysui.ShellController
import com.android.wm.shell.sysui.ShellInit
import com.android.wm.shell.sysui.UserChangeListener
+import com.android.wm.shell.transition.FocusTransitionObserver
import com.android.wm.shell.transition.OneShotRemoteHandler
import com.android.wm.shell.transition.Transitions
import com.android.wm.shell.windowdecor.DragPositioningCallbackUtility
@@ -118,7 +126,7 @@ import java.io.PrintWriter
import java.util.Optional
import java.util.concurrent.Executor
import java.util.function.Consumer
-
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger
/** Handles moving tasks in and out of desktop */
class DesktopTasksController(
private val context: Context,
@@ -149,11 +157,15 @@ class DesktopTasksController(
private val recentTasksController: RecentTasksController?,
private val interactionJankMonitor: InteractionJankMonitor,
@ShellMainThread private val handler: Handler,
+ private val inputManager: InputManager,
+ private val focusTransitionObserver: FocusTransitionObserver,
+ private val desktopModeEventLogger: DesktopModeEventLogger,
) :
RemoteCallable<DesktopTasksController>,
Transitions.TransitionHandler,
DragAndDropController.DragAndDropListener,
- UserChangeListener {
+ UserChangeListener,
+ KeyGestureEventHandler {
private val desktopMode: DesktopModeImpl
private var visualIndicator: DesktopModeVisualIndicator? = null
@@ -226,6 +238,9 @@ class DesktopTasksController(
}
)
dragAndDropController.addListener(this)
+ if (useKeyGestureEventHandler() && enableMoveToNextDisplayShortcut()) {
+ inputManager.registerKeyGestureEventHandler(this)
+ }
}
@VisibleForTesting
@@ -409,7 +424,7 @@ class DesktopTasksController(
interactionJankMonitor.begin(taskSurface, context, handler,
CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_HOLD)
dragToDesktopTransitionHandler.startDragToDesktopTransition(
- taskInfo,
+ taskInfo.taskId,
dragToDesktopValueAnimator
)
}
@@ -461,7 +476,12 @@ class DesktopTasksController(
* @param displayId display id of the window that's being closed
* @param taskId task id of the window that's being closed
*/
- fun onDesktopWindowClose(wct: WindowContainerTransaction, displayId: Int, taskId: Int) {
+ fun onDesktopWindowClose(
+ wct: WindowContainerTransaction,
+ displayId: Int,
+ taskInfo: RunningTaskInfo,
+ ): ((IBinder) -> Unit)? {
+ val taskId = taskInfo.taskId
if (taskRepository.isOnlyVisibleNonClosingTask(taskId)) {
removeWallpaperActivity(wct)
}
@@ -472,6 +492,7 @@ class DesktopTasksController(
taskId
)
)
+ return immersiveTransitionHandler.exitImmersiveIfApplicable(wct, taskInfo)
}
fun minimizeTask(taskInfo: RunningTaskInfo) {
@@ -728,7 +749,11 @@ class DesktopTasksController(
* bounds) and a free floating state (either the last saved bounds if available or the default
* bounds otherwise).
*/
- fun toggleDesktopTaskSize(taskInfo: RunningTaskInfo) {
+ fun toggleDesktopTaskSize(
+ taskInfo: RunningTaskInfo,
+ resizeTrigger: ResizeTrigger,
+ motionEvent: MotionEvent?,
+ ) {
val displayLayout = displayController.getDisplayLayout(taskInfo.displayId) ?: return
val stableBounds = Rect().apply { displayLayout.getStableBounds(this) }
@@ -775,7 +800,10 @@ class DesktopTasksController(
taskbarDesktopTaskListener?.onTaskbarCornerRoundingUpdate(doesAnyTaskRequireTaskbarRounding)
val wct = WindowContainerTransaction().setBounds(taskInfo.token, destinationBounds)
-
+ desktopModeEventLogger.logTaskResizingEnded(
+ resizeTrigger, motionEvent, taskInfo, destinationBounds.height(),
+ destinationBounds.width(), displayController
+ )
toggleResizeDesktopTaskTransitionHandler.startTransition(wct)
}
@@ -865,9 +893,19 @@ class DesktopTasksController(
taskInfo: RunningTaskInfo,
taskSurface: SurfaceControl,
currentDragBounds: Rect,
- position: SnapPosition
+ position: SnapPosition,
+ resizeTrigger: ResizeTrigger,
+ motionEvent: MotionEvent?,
) {
val destinationBounds = getSnapBounds(taskInfo, position)
+ desktopModeEventLogger.logTaskResizingEnded(
+ resizeTrigger,
+ motionEvent,
+ taskInfo,
+ destinationBounds.height(),
+ destinationBounds.width(),
+ displayController,
+ )
if (destinationBounds == taskInfo.configuration.windowConfiguration.bounds) {
// Handle the case where we attempt to snap resize when already snap resized: the task
// position won't need to change but we want to animate the surface going back to the
@@ -896,7 +934,8 @@ class DesktopTasksController(
position: SnapPosition,
taskSurface: SurfaceControl,
currentDragBounds: Rect,
- dragStartBounds: Rect
+ dragStartBounds: Rect,
+ motionEvent: MotionEvent,
) {
releaseVisualIndicator()
if (!taskInfo.isResizeable && DISABLE_NON_RESIZABLE_APP_SNAP_RESIZE.isTrue()) {
@@ -913,10 +952,25 @@ class DesktopTasksController(
isResizable = taskInfo.isResizeable,
)
} else {
+ val resizeTrigger = if (position == SnapPosition.LEFT) {
+ ResizeTrigger.DRAG_LEFT
+ } else {
+ ResizeTrigger.DRAG_RIGHT
+ }
+ desktopModeEventLogger.logTaskResizingStarted(
+ resizeTrigger, motionEvent, taskInfo, displayController
+ )
interactionJankMonitor.begin(
taskSurface, context, handler, CUJ_DESKTOP_MODE_SNAP_RESIZE, "drag_resizable"
)
- snapToHalfScreen(taskInfo, taskSurface, currentDragBounds, position)
+ snapToHalfScreen(
+ taskInfo,
+ taskSurface,
+ currentDragBounds,
+ position,
+ resizeTrigger,
+ motionEvent,
+ )
}
}
@@ -1581,12 +1635,26 @@ class DesktopTasksController(
getFocusedFreeformTask(displayId)?.let { requestSplit(it, leftOrTop) }
}
+ /** Move the focused desktop task in given `displayId` to next display. */
+ fun moveFocusedTaskToNextDisplay(displayId: Int) {
+ getFocusedFreeformTask(displayId)?.let { moveToNextDisplay(it.taskId) }
+ }
+
private fun getFocusedFreeformTask(displayId: Int): RunningTaskInfo? {
return shellTaskOrganizer.getRunningTasks(displayId).find { taskInfo ->
taskInfo.isFocused && taskInfo.windowingMode == WINDOWING_MODE_FREEFORM
}
}
+ // TODO(b/364154795): wait for the completion of moveToNextDisplay transition, otherwise it will
+ // pick a wrong task when a user quickly perform other actions with keyboard shortcuts after
+ // moveToNextDisplay.
+ private fun getGloballyFocusedFreeformTask(): RunningTaskInfo? =
+ shellTaskOrganizer.getRunningTasks().find { taskInfo ->
+ taskInfo.windowingMode == WINDOWING_MODE_FREEFORM &&
+ focusTransitionObserver.hasGlobalFocus(taskInfo)
+ }
+
/**
* Requests a task be transitioned from desktop to split select. Applies needed windowing
* changes if this transition is enabled.
@@ -1702,6 +1770,7 @@ class DesktopTasksController(
currentDragBounds: Rect,
validDragArea: Rect,
dragStartBounds: Rect,
+ motionEvent: MotionEvent,
) {
if (taskInfo.configuration.windowConfiguration.windowingMode != WINDOWING_MODE_FREEFORM) {
return
@@ -1722,12 +1791,22 @@ class DesktopTasksController(
}
IndicatorType.TO_SPLIT_LEFT_INDICATOR -> {
handleSnapResizingTask(
- taskInfo, SnapPosition.LEFT, taskSurface, currentDragBounds, dragStartBounds
+ taskInfo,
+ SnapPosition.LEFT,
+ taskSurface,
+ currentDragBounds,
+ dragStartBounds,
+ motionEvent,
)
}
IndicatorType.TO_SPLIT_RIGHT_INDICATOR -> {
handleSnapResizingTask(
- taskInfo, SnapPosition.RIGHT, taskSurface, currentDragBounds, dragStartBounds
+ taskInfo,
+ SnapPosition.RIGHT,
+ taskSurface,
+ currentDragBounds,
+ dragStartBounds,
+ motionEvent,
)
}
IndicatorType.NO_INDICATOR -> {
@@ -1941,6 +2020,31 @@ class DesktopTasksController(
taskRepository.dump(pw, innerPrefix)
}
+ override fun handleKeyGestureEvent(
+ event: KeyGestureEvent,
+ focusedToken: IBinder?
+ ): Boolean {
+ if (!isKeyGestureSupported(event.keyGestureType)) return false
+ when (event.keyGestureType) {
+ KeyGestureEvent.KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY -> {
+ if (event.keycodes.contains(KeyEvent.KEYCODE_D) &&
+ event.hasModifiers(KeyEvent.META_CTRL_ON or KeyEvent.META_META_ON)) {
+ logV("Key gesture MOVE_TO_NEXT_DISPLAY is handled")
+ getGloballyFocusedFreeformTask()?.let { moveToNextDisplay(it.taskId) }
+ return true
+ }
+ return false
+ }
+ else -> return false
+ }
+ }
+
+ override fun isKeyGestureSupported(gestureType: Int): Boolean = when (gestureType) {
+ KeyGestureEvent.KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY
+ -> enableMoveToNextDisplayShortcut()
+ else -> false
+ }
+
/** The interface for calls from outside the shell, within the host process. */
@ExternalThread
private inner class DesktopModeImpl : DesktopMode {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
index 34c2f1e760a2..d7d55195d4cf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandler.kt
@@ -109,8 +109,8 @@ sealed class DragToDesktopTransitionHandler(
* after one of the "end" or "cancel" transitions is merged into this transition.
*/
fun startDragToDesktopTransition(
- taskInfo: RunningTaskInfo,
- dragToDesktopAnimator: MoveToDesktopAnimator
+ taskId: Int,
+ dragToDesktopAnimator: MoveToDesktopAnimator,
) {
if (inProgress) {
ProtoLog.v(
@@ -137,26 +137,23 @@ sealed class DragToDesktopTransitionHandler(
)
val wct = WindowContainerTransaction()
wct.sendPendingIntent(pendingIntent, launchHomeIntent, Bundle())
- // The home launch done above will result in an attempt to move the task to pip if
- // applicable, resulting in a broken state. Prevent that here.
- wct.setDoNotPip(taskInfo.token)
val startTransitionToken =
transitions.startTransition(TRANSIT_DESKTOP_MODE_START_DRAG_TO_DESKTOP, wct, this)
transitionState =
- if (isSplitTask(taskInfo.taskId)) {
+ if (isSplitTask(taskId)) {
val otherTask =
- getOtherSplitTask(taskInfo.taskId)
+ getOtherSplitTask(taskId)
?: throw IllegalStateException("Expected split task to have a counterpart.")
TransitionState.FromSplit(
- draggedTaskId = taskInfo.taskId,
+ draggedTaskId = taskId,
dragAnimator = dragToDesktopAnimator,
startTransitionToken = startTransitionToken,
otherSplitTask = otherTask
)
} else {
TransitionState.FromFullscreen(
- draggedTaskId = taskInfo.taskId,
+ draggedTaskId = taskId,
dragAnimator = dragToDesktopAnimator,
startTransitionToken = startTransitionToken
)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepository.kt
index 3f41d7cf4e86..2d11e02bd3c6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepository.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepository.kt
@@ -73,15 +73,14 @@ class DesktopPersistentRepository(
*/
private suspend fun getDesktopRepositoryState(
userId: Int = DEFAULT_USER_ID
- ): DesktopRepositoryState =
+ ): DesktopRepositoryState? =
try {
dataStoreFlow
.first()
- .desktopRepoByUserMap
- .getOrDefault(userId, DesktopRepositoryState.getDefaultInstance())
+ .desktopRepoByUserMap[userId]
} catch (e: Exception) {
Log.e(TAG, "Unable to read from datastore", e)
- DesktopRepositoryState.getDefaultInstance()
+ null
}
/**
@@ -91,13 +90,13 @@ class DesktopPersistentRepository(
suspend fun readDesktop(
userId: Int = DEFAULT_USER_ID,
desktopId: Int = DEFAULT_DESKTOP_ID,
- ): Desktop =
+ ): Desktop? =
try {
val repository = getDesktopRepositoryState(userId)
- repository.getDesktopOrThrow(desktopId)
+ repository?.getDesktopOrThrow(desktopId)
} catch (e: Exception) {
Log.e(TAG, "Unable to get desktop info from persistent repository", e)
- Desktop.getDefaultInstance()
+ null
}
/** Adds or updates a desktop stored in the datastore */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
index 6aaf001d46f3..58337ece0991 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionHandler.java
@@ -99,9 +99,11 @@ public class FreeformTaskTransitionHandler
@Override
- public void startRemoveTransition(WindowContainerTransaction wct) {
+ public IBinder startRemoveTransition(WindowContainerTransaction wct) {
final int type = WindowManager.TRANSIT_CLOSE;
- mPendingTransitionTokens.add(mTransitions.startTransition(type, wct, this));
+ final IBinder transition = mTransitions.startTransition(type, wct, this);
+ mPendingTransitionTokens.add(transition);
+ return transition;
}
@Override
@@ -229,8 +231,7 @@ public class FreeformTaskTransitionHandler
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
SurfaceControl sc = change.getLeash();
finishT.hide(sc);
- Rect startBounds = new Rect(change.getTaskInfo().configuration.windowConfiguration
- .getBounds());
+ final Rect startBounds = new Rect(change.getStartAbsBounds());
animator.addUpdateListener(animation -> {
t.setPosition(sc, startBounds.left,
startBounds.top + (animation.getAnimatedFraction() * screenHeight));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java
index ea68a694c3b9..5984d486f838 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionStarter.java
@@ -48,6 +48,7 @@ public interface FreeformTaskTransitionStarter {
*
* @param wct the {@link WindowContainerTransaction} that closes the task
*
+ * @return the started transition
*/
- void startRemoveTransition(WindowContainerTransaction wct);
+ IBinder startRemoveTransition(WindowContainerTransaction wct);
} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
index b36b1f84d21f..3e6d36ce0ca3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
@@ -110,12 +110,12 @@ public interface SplitScreen {
void registerSplitAnimationListener(@NonNull SplitInvocationListener listener,
@NonNull Executor executor);
- /** Called when device waking up finished. */
- void onFinishedWakingUp();
-
/** Called when device starts going to sleep (screen off). */
void onStartedGoingToSleep();
+ /** Called when device wakes up. */
+ void onStartedWakingUp();
+
/** Called when requested to go to fullscreen from the current active split app. */
void goToFullscreenFromSplit();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index a23b576beebc..6398d31b4f82 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -471,14 +471,14 @@ public class SplitScreenController implements SplitDragPolicy.Starter,
mStageCoordinator.onKeyguardStateChanged(visible, occluded);
}
- public void onFinishedWakingUp() {
- mStageCoordinator.onFinishedWakingUp();
- }
-
public void onStartedGoingToSleep() {
mStageCoordinator.onStartedGoingToSleep();
}
+ public void onStartedWakingUp() {
+ mStageCoordinator.onStartedWakingUp();
+ }
+
public void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) {
mStageCoordinator.exitSplitScreenOnHide(exitSplitScreenOnHide);
}
@@ -1084,13 +1084,13 @@ public class SplitScreenController implements SplitDragPolicy.Starter,
}
@Override
- public void onFinishedWakingUp() {
- mMainExecutor.execute(SplitScreenController.this::onFinishedWakingUp);
+ public void onStartedGoingToSleep() {
+ mMainExecutor.execute(SplitScreenController.this::onStartedGoingToSleep);
}
@Override
- public void onStartedGoingToSleep() {
- mMainExecutor.execute(SplitScreenController.this::onStartedGoingToSleep);
+ public void onStartedWakingUp() {
+ mMainExecutor.execute(SplitScreenController.this::onStartedWakingUp);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 3e76403de51b..7893267d014a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -1138,14 +1138,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
"onKeyguardVisibilityChanged: active=%b occludingTaskRunning=%b",
active, occludingTaskRunning);
setDividerVisibility(!mKeyguardActive, null);
-
- if (active && occludingTaskRunning) {
- dismissSplitKeepingLastActiveStage(EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
- }
}
- void onFinishedWakingUp() {
- ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onFinishedWakingUp");
+ void onStartedWakingUp() {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onStartedWakingUp");
if (mBreakOnNextWake) {
dismissSplitKeepingLastActiveStage(EXIT_REASON_DEVICE_FOLDED);
}
@@ -1908,60 +1904,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
}
- /** Callback when split roots have child or haven't under it.
- * NOTICE: This only be called on legacy transition. */
- @Override
- public void onStageHasChildrenChanged(StageTaskListener stageListener) {
- ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onStageHasChildrenChanged: isMainStage=%b",
- stageListener == mMainStage);
- final boolean hasChildren = stageListener.mHasChildren;
- final boolean isSideStage = stageListener == mSideStage;
- if (!hasChildren && !mIsExiting && isSplitActive()) {
- if (isSideStage && mMainStage.mVisible) {
- // Exit to main stage if side stage no longer has children.
- mSplitLayout.flingDividerToDismiss(
- mSideStagePosition == SPLIT_POSITION_BOTTOM_OR_RIGHT,
- EXIT_REASON_APP_FINISHED);
- } else if (!isSideStage && mSideStage.mVisible) {
- // Exit to side stage if main stage no longer has children.
- mSplitLayout.flingDividerToDismiss(
- mSideStagePosition != SPLIT_POSITION_BOTTOM_OR_RIGHT,
- EXIT_REASON_APP_FINISHED);
- } else if (!isSplitScreenVisible() && mSplitRequest == null) {
- // Dismiss split screen in the background once any sides of the split become empty.
- exitSplitScreen(null /* childrenToTop */, EXIT_REASON_APP_FINISHED);
- }
- } else if (isSideStage && hasChildren && !isSplitActive()) {
- final WindowContainerTransaction wct = new WindowContainerTransaction();
- prepareEnterSplitScreen(wct);
-
- mSyncQueue.queue(wct);
- mSyncQueue.runInSync(t -> {
- if (mIsDropEntering) {
- updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */);
- mIsDropEntering = false;
- mSkipEvictingMainStageChildren = false;
- } else {
- mShowDecorImmediately = true;
- mSplitLayout.flingDividerToCenter(/*finishCallback*/ null);
- }
- });
- }
- if (mMainStage.mHasChildren && mSideStage.mHasChildren) {
- mShouldUpdateRecents = true;
- clearRequestIfPresented();
- updateRecentTasksSplitPair();
-
- if (!mLogger.hasStartedSession() && !mLogger.hasValidEnterSessionId()) {
- mLogger.enterRequested(null /*enterSessionId*/, ENTER_REASON_MULTI_INSTANCE);
- }
- mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
- getMainStagePosition(), mMainStage.getTopChildTaskUid(),
- getSideStagePosition(), mSideStage.getTopChildTaskUid(),
- mSplitLayout.isLeftRightSplit());
- }
- }
-
@Override
public void onNoLongerSupportMultiWindow(StageTaskListener stageTaskListener,
ActivityManager.RunningTaskInfo taskInfo) {
@@ -2485,6 +2427,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
final int transitType = info.getType();
TransitionInfo.Change pipChange = null;
int closingSplitTaskId = -1;
+ // This array tracks if we are sending stages TO_BACK in this transition.
+ // TODO (b/349828130): Update for n apps
+ boolean[] stagesSentToBack = new boolean[2];
+
for (int iC = 0; iC < info.getChanges().size(); ++iC) {
final TransitionInfo.Change change = info.getChanges().get(iC);
if (change.getMode() == TRANSIT_CHANGE
@@ -2552,23 +2498,31 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
continue;
}
+ final int taskId = taskInfo.taskId;
if (isOpeningType(change.getMode())) {
- if (!stage.containsTask(taskInfo.taskId)) {
+ if (!stage.containsTask(taskId)) {
Log.w(TAG, "Expected onTaskAppeared on " + stage + " to have been called"
- + " with " + taskInfo.taskId + " before startAnimation().");
- record.addRecord(stage, true, taskInfo.taskId);
+ + " with " + taskId + " before startAnimation().");
+ record.addRecord(stage, true, taskId);
}
} else if (change.getMode() == TRANSIT_CLOSE) {
- if (stage.containsTask(taskInfo.taskId)) {
- record.addRecord(stage, false, taskInfo.taskId);
+ if (stage.containsTask(taskId)) {
+ record.addRecord(stage, false, taskId);
Log.w(TAG, "Expected onTaskVanished on " + stage + " to have been called"
- + " with " + taskInfo.taskId + " before startAnimation().");
+ + " with " + taskId + " before startAnimation().");
}
}
if (isClosingType(change.getMode()) &&
- getStageOfTask(change.getTaskInfo().taskId) != STAGE_TYPE_UNDEFINED) {
- // If either one of the 2 stages is closing we're assuming we'll break split
- closingSplitTaskId = change.getTaskInfo().taskId;
+ getStageOfTask(taskId) != STAGE_TYPE_UNDEFINED) {
+
+ // Record which stages are getting sent to back
+ if (change.getMode() == TRANSIT_TO_BACK) {
+ stagesSentToBack[getStageOfTask(taskId)] = true;
+ }
+
+ // (For PiP transitions) If either one of the 2 stages is closing we're assuming
+ // we'll break split
+ closingSplitTaskId = taskId;
}
}
@@ -2594,6 +2548,21 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return true;
}
+ // If keyguard is active, check to see if we have our TO_BACK transitions in order.
+ // This array should either be all false (no split stages sent to back) or all true
+ // (all stages sent to back). In any other case (which can happen with SHOW_ABOVE_LOCKED
+ // apps) we should break split.
+ if (mKeyguardActive) {
+ boolean isFirstStageSentToBack = stagesSentToBack[0];
+ for (boolean b : stagesSentToBack) {
+ // Compare each boolean to the first one. If any are different, break split.
+ if (b != isFirstStageSentToBack) {
+ dismissSplitKeepingLastActiveStage(EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
+ break;
+ }
+ }
+ }
+
final ArraySet<StageTaskListener> dismissStages = record.getShouldDismissedStage();
if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0
|| dismissStages.size() == 1) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 6313231b449e..b33f3e98f350 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -75,8 +75,6 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
public interface StageListenerCallbacks {
void onRootTaskAppeared();
- void onStageHasChildrenChanged(StageTaskListener stageTaskListener);
-
void onStageVisibilityChanged(StageTaskListener stageTaskListener);
void onChildTaskStatusChanged(StageTaskListener stage, int taskId, boolean present,
@@ -207,7 +205,10 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
mIconProvider);
mHasRootTask = true;
mCallbacks.onRootTaskAppeared();
- sendStatusChanged();
+ if (mVisible != mRootTaskInfo.isVisible) {
+ mVisible = mRootTaskInfo.isVisible;
+ mCallbacks.onStageVisibilityChanged(this);
+ }
mSyncQueue.runInSync(t -> mDimLayer =
SurfaceUtils.makeDimLayer(t, mRootLeash, "Dim layer"));
} else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
@@ -498,22 +499,6 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
return true;
}
- private void sendStatusChanged() {
- boolean hasChildren = mChildrenTaskInfo.size() > 0;
- boolean visible = mRootTaskInfo.isVisible;
- if (!mHasRootTask) return;
-
- if (mHasChildren != hasChildren) {
- mHasChildren = hasChildren;
- mCallbacks.onStageHasChildrenChanged(this);
- }
-
- if (mVisible != visible) {
- mVisible = visible;
- mCallbacks.onStageVisibilityChanged(this);
- }
- }
-
@Override
@CallSuper
public void dump(@NonNull PrintWriter pw, String prefix) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
index 509cb85c96cd..fde01eefee17 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java
@@ -274,6 +274,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
closeDragResizeListener();
mDragResizeListener = new DragResizeInputListener(
mContext,
+ mTaskInfo,
mHandler,
mChoreographer,
mDisplay.getDisplayId(),
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 9e089b2460f6..a775cbc6c9f3 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
@@ -32,6 +32,7 @@ import static android.view.WindowInsets.Type.statusBars;
import static com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_ENTER_MODE_APP_HANDLE_MENU;
import static com.android.wm.shell.compatui.AppCompatUtils.isTopActivityExemptFromDesktopWindowing;
+import static com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_FULLSCREEN_INDICATOR;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_LEFT_INDICATOR;
import static com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType.TO_SPLIT_RIGHT_INDICATOR;
@@ -56,6 +57,7 @@ import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.input.InputManager;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -102,6 +104,7 @@ import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler;
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger;
import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator;
import com.android.wm.shell.desktopmode.DesktopRepository;
import com.android.wm.shell.desktopmode.DesktopTasksController;
@@ -133,6 +136,7 @@ import com.android.wm.shell.windowdecor.viewholder.AppHeaderViewHolder;
import kotlin.Pair;
import kotlin.Unit;
+import kotlin.jvm.functions.Function1;
import kotlinx.coroutines.ExperimentalCoroutinesApi;
@@ -219,6 +223,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
};
private final TaskPositionerFactory mTaskPositionerFactory;
private final FocusTransitionObserver mFocusTransitionObserver;
+ private final DesktopModeEventLogger mDesktopModeEventLogger;
public DesktopModeWindowDecorViewModel(
Context context,
@@ -246,7 +251,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
AppHandleEducationController appHandleEducationController,
WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler,
- FocusTransitionObserver focusTransitionObserver) {
+ FocusTransitionObserver focusTransitionObserver,
+ DesktopModeEventLogger desktopModeEventLogger) {
this(
context,
shellExecutor,
@@ -279,7 +285,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
windowDecorCaptionHandleRepository,
activityOrientationChangeHandler,
new TaskPositionerFactory(),
- focusTransitionObserver);
+ focusTransitionObserver,
+ desktopModeEventLogger);
}
@VisibleForTesting
@@ -315,7 +322,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
Optional<DesktopActivityOrientationChangeHandler> activityOrientationChangeHandler,
TaskPositionerFactory taskPositionerFactory,
- FocusTransitionObserver focusTransitionObserver) {
+ FocusTransitionObserver focusTransitionObserver,
+ DesktopModeEventLogger desktopModeEventLogger) {
mContext = context;
mMainExecutor = shellExecutor;
mMainHandler = mainHandler;
@@ -376,6 +384,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
};
mTaskPositionerFactory = taskPositionerFactory;
mFocusTransitionObserver = focusTransitionObserver;
+ mDesktopModeEventLogger = desktopModeEventLogger;
shellInit.addInitCallback(this::onInit, this);
}
@@ -545,15 +554,20 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
>= MANAGE_WINDOWS_MINIMUM_INSTANCES);
}
- private void onMaximizeOrRestore(int taskId, String source) {
+ private void onMaximizeOrRestore(int taskId, String source, ResizeTrigger resizeTrigger,
+ MotionEvent motionEvent) {
final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
if (decoration == null) {
return;
}
+ mDesktopModeEventLogger.logTaskResizingStarted(resizeTrigger, motionEvent,
+ decoration.mTaskInfo,
+ mDisplayController, /* displayLayoutSize= */ null);
mInteractionJankMonitor.begin(
decoration.mTaskSurface, mContext, mMainHandler,
Cuj.CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW, source);
- mDesktopTasksController.toggleDesktopTaskSize(decoration.mTaskInfo);
+ mDesktopTasksController.toggleDesktopTaskSize(decoration.mTaskInfo, resizeTrigger,
+ motionEvent);
decoration.closeHandleMenu();
decoration.closeMaximizeMenu();
}
@@ -566,7 +580,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
mDesktopTasksController.toggleDesktopTaskFullImmersiveState(decoration.mTaskInfo);
}
- private void onSnapResize(int taskId, boolean left) {
+ private void onSnapResize(int taskId, boolean left, MotionEvent motionEvent) {
final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId);
if (decoration == null) {
return;
@@ -577,13 +591,20 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
Toast.makeText(mContext,
R.string.desktop_mode_non_resizable_snap_text, Toast.LENGTH_SHORT).show();
} else {
+ ResizeTrigger resizeTrigger =
+ left ? ResizeTrigger.SNAP_LEFT_MENU : ResizeTrigger.SNAP_RIGHT_MENU;
+ mDesktopModeEventLogger.logTaskResizingStarted(resizeTrigger, motionEvent,
+ decoration.mTaskInfo,
+ mDisplayController, /* displayLayoutSize= */ null);
mInteractionJankMonitor.begin(decoration.mTaskSurface, mContext, mMainHandler,
Cuj.CUJ_DESKTOP_MODE_SNAP_RESIZE, "maximize_menu_resizable");
mDesktopTasksController.snapToHalfScreen(
decoration.mTaskInfo,
decoration.mTaskSurface,
decoration.mTaskInfo.configuration.windowConfiguration.getBounds(),
- left ? SnapPosition.LEFT : SnapPosition.RIGHT);
+ left ? SnapPosition.LEFT : SnapPosition.RIGHT,
+ resizeTrigger,
+ motionEvent);
}
decoration.closeHandleMenu();
@@ -735,6 +756,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
private boolean mTouchscreenInUse;
private boolean mHasLongClicked;
private int mDragPointerId = -1;
+ private MotionEvent mMotionEvent;
private DesktopModeTouchEventListener(
RunningTaskInfo taskInfo,
@@ -767,8 +789,13 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
SplitScreenController.EXIT_REASON_DESKTOP_MODE);
} else {
WindowContainerTransaction wct = new WindowContainerTransaction();
- mDesktopTasksController.onDesktopWindowClose(wct, mDisplayId, mTaskId);
- mTaskOperations.closeTask(mTaskToken, wct);
+ final Function1<IBinder, Unit> runOnTransitionStart =
+ mDesktopTasksController.onDesktopWindowClose(
+ wct, mDisplayId, decoration.mTaskInfo);
+ final IBinder transition = mTaskOperations.closeTask(mTaskToken, wct);
+ if (transition != null && runOnTransitionStart != null) {
+ runOnTransitionStart.invoke(transition);
+ }
}
} else if (id == R.id.back_button) {
mTaskOperations.injectBackKey(mDisplayId);
@@ -791,7 +818,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
} else {
// Full immersive is disabled or task doesn't request/support it, so just
// toggle between maximize/restore states.
- onMaximizeOrRestore(decoration.mTaskInfo.taskId, "caption_bar_button");
+ onMaximizeOrRestore(decoration.mTaskInfo.taskId, "caption_bar_button",
+ ResizeTrigger.MAXIMIZE_BUTTON, mMotionEvent);
}
} else if (id == R.id.minimize_window) {
mDesktopTasksController.minimizeTask(decoration.mTaskInfo);
@@ -800,6 +828,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
@Override
public boolean onTouch(View v, MotionEvent e) {
+ mMotionEvent = e;
final int id = v.getId();
final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId);
if ((e.getSource() & SOURCE_TOUCHSCREEN) == SOURCE_TOUCHSCREEN) {
@@ -890,6 +919,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
*/
@Override
public boolean onGenericMotion(View v, MotionEvent ev) {
+ mMotionEvent = ev;
final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(mTaskId);
final int id = v.getId();
if (ev.getAction() == ACTION_HOVER_ENTER && id == R.id.maximize_window) {
@@ -1033,7 +1063,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
taskInfo, decoration.mTaskSurface, position,
new PointF(e.getRawX(dragPointerIdx), e.getRawY(dragPointerIdx)),
newTaskBounds, decoration.calculateValidDragArea(),
- new Rect(mOnDragStartInitialBounds));
+ new Rect(mOnDragStartInitialBounds), e);
if (touchingButton && !mHasLongClicked) {
// We need the input event to not be consumed here to end the ripple
// effect on the touched button. We will reset drag state in the ensuing
@@ -1080,7 +1110,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
// Disallow double-tap to resize when in full immersive.
return false;
}
- onMaximizeOrRestore(mTaskId, "double_tap");
+ onMaximizeOrRestore(mTaskId, "double_tap", ResizeTrigger.DOUBLE_TAP_APP_HEADER, e);
return true;
}
}
@@ -1477,7 +1507,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
mGenericLinksParser,
mAssistContentRequester,
mMultiInstanceHelper,
- mWindowDecorCaptionHandleRepository);
+ mWindowDecorCaptionHandleRepository,
+ mDesktopModeEventLogger);
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
final TaskPositioner taskPositioner = mTaskPositionerFactory.create(
@@ -1494,15 +1525,16 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel,
final DesktopModeTouchEventListener touchEventListener =
new DesktopModeTouchEventListener(taskInfo, taskPositioner);
windowDecoration.setOnMaximizeOrRestoreClickListener(() -> {
- onMaximizeOrRestore(taskInfo.taskId, "maximize_menu");
+ onMaximizeOrRestore(taskInfo.taskId, "maximize_menu", ResizeTrigger.MAXIMIZE_MENU,
+ touchEventListener.mMotionEvent);
return Unit.INSTANCE;
});
windowDecoration.setOnLeftSnapClickListener(() -> {
- onSnapResize(taskInfo.taskId, true /* isLeft */);
+ onSnapResize(taskInfo.taskId, /* isLeft= */ true, touchEventListener.mMotionEvent);
return Unit.INSTANCE;
});
windowDecoration.setOnRightSnapClickListener(() -> {
- onSnapResize(taskInfo.taskId, false /* isLeft */);
+ onSnapResize(taskInfo.taskId, /* isLeft= */ false, touchEventListener.mMotionEvent);
return Unit.INSTANCE;
});
windowDecoration.setOnToDesktopClickListener(desktopModeTransitionSource -> {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 6eb20b9e3ae5..d94f3a9a70c6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -94,6 +94,7 @@ import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.desktopmode.CaptionState;
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger;
import com.android.wm.shell.desktopmode.DesktopRepository;
import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository;
import com.android.wm.shell.shared.annotations.ShellBackgroundThread;
@@ -216,7 +217,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
AppToWebGenericLinksParser genericLinksParser,
AssistContentRequester assistContentRequester,
MultiInstanceHelper multiInstanceHelper,
- WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository) {
+ WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
+ DesktopModeEventLogger desktopModeEventLogger) {
this (context, userContext, displayController, splitScreenController, desktopRepository,
taskOrganizer, taskInfo, taskSurface, handler, bgExecutor, choreographer, syncQueue,
appHeaderViewHolderFactory, rootTaskDisplayAreaOrganizer, genericLinksParser,
@@ -227,7 +229,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
new SurfaceControlViewHostFactory() {},
DefaultMaximizeMenuFactory.INSTANCE,
DefaultHandleMenuFactory.INSTANCE, multiInstanceHelper,
- windowDecorCaptionHandleRepository);
+ windowDecorCaptionHandleRepository, desktopModeEventLogger);
}
DesktopModeWindowDecoration(
@@ -256,11 +258,12 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
MaximizeMenuFactory maximizeMenuFactory,
HandleMenuFactory handleMenuFactory,
MultiInstanceHelper multiInstanceHelper,
- WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository) {
+ WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
+ DesktopModeEventLogger desktopModeEventLogger) {
super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface,
surfaceControlBuilderSupplier, surfaceControlTransactionSupplier,
windowContainerTransactionSupplier, surfaceControlSupplier,
- surfaceControlViewHostFactory);
+ surfaceControlViewHostFactory, desktopModeEventLogger);
mSplitScreenController = splitScreenController;
mHandler = handler;
mBgExecutor = bgExecutor;
@@ -605,6 +608,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
Trace.beginSection("DesktopModeWindowDecoration#relayout-DragResizeInputListener");
mDragResizeListener = new DragResizeInputListener(
mContext,
+ mTaskInfo,
mHandler,
mChoreographer,
mDisplay.getDisplayId(),
@@ -612,7 +616,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
mDragPositioningCallback,
mSurfaceControlBuilderSupplier,
mSurfaceControlTransactionSupplier,
- mDisplayController);
+ mDisplayController,
+ mDesktopModeEventLogger);
Trace.endSection();
}
@@ -1700,7 +1705,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
AppToWebGenericLinksParser genericLinksParser,
AssistContentRequester assistContentRequester,
MultiInstanceHelper multiInstanceHelper,
- WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository) {
+ WindowDecorCaptionHandleRepository windowDecorCaptionHandleRepository,
+ DesktopModeEventLogger desktopModeEventLogger) {
return new DesktopModeWindowDecoration(
context,
userContext,
@@ -1719,7 +1725,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
genericLinksParser,
assistContentRequester,
multiInstanceHelper,
- windowDecorCaptionHandleRepository);
+ windowDecorCaptionHandleRepository,
+ desktopModeEventLogger);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
index 4ff394e2b1a9..420409705b05 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeInputListener.java
@@ -29,10 +29,12 @@ import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_LEFT;
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_RIGHT;
import static com.android.wm.shell.windowdecor.DragPositioningCallback.CTRL_TYPE_TOP;
+import static com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.isEdgeResizePermitted;
import static com.android.wm.shell.windowdecor.DragResizeWindowGeometry.isEventFromTouchscreen;
import android.annotation.NonNull;
+import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
@@ -59,6 +61,7 @@ import android.window.InputTransferToken;
import com.android.internal.protolog.ProtoLog;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger;
import java.util.function.Consumer;
import java.util.function.Supplier;
@@ -83,14 +86,17 @@ class DragResizeInputListener implements AutoCloseable {
private final TaskResizeInputEventReceiver mInputEventReceiver;
private final Context mContext;
+ private final RunningTaskInfo mTaskInfo;
private final SurfaceControl mInputSinkSurface;
private final IBinder mSinkClientToken;
private final InputChannel mSinkInputChannel;
private final DisplayController mDisplayController;
+ private final DesktopModeEventLogger mDesktopModeEventLogger;
private final Region mTouchRegion = new Region();
DragResizeInputListener(
Context context,
+ RunningTaskInfo taskInfo,
Handler handler,
Choreographer choreographer,
int displayId,
@@ -98,12 +104,15 @@ class DragResizeInputListener implements AutoCloseable {
DragPositioningCallback callback,
Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
- DisplayController displayController) {
+ DisplayController displayController,
+ DesktopModeEventLogger desktopModeEventLogger) {
mContext = context;
+ mTaskInfo = taskInfo;
mSurfaceControlTransactionSupplier = surfaceControlTransactionSupplier;
mDisplayId = displayId;
mDecorationSurface = decorationSurface;
mDisplayController = displayController;
+ mDesktopModeEventLogger = desktopModeEventLogger;
mClientToken = new Binder();
final InputTransferToken inputTransferToken = new InputTransferToken();
mInputChannel = new InputChannel();
@@ -125,11 +134,12 @@ class DragResizeInputListener implements AutoCloseable {
e.rethrowFromSystemServer();
}
- mInputEventReceiver = new TaskResizeInputEventReceiver(context, mInputChannel, callback,
+ mInputEventReceiver = new TaskResizeInputEventReceiver(context, mTaskInfo, mInputChannel,
+ callback,
handler, choreographer, () -> {
final DisplayLayout layout = mDisplayController.getDisplayLayout(mDisplayId);
return new Size(layout.width(), layout.height());
- }, this::updateSinkInputChannel);
+ }, this::updateSinkInputChannel, mDesktopModeEventLogger);
mInputEventReceiver.setTouchSlop(ViewConfiguration.get(context).getScaledTouchSlop());
mInputSinkSurface = surfaceControlBuilderSupplier.get()
@@ -163,6 +173,22 @@ class DragResizeInputListener implements AutoCloseable {
}
}
+ DragResizeInputListener(
+ Context context,
+ RunningTaskInfo taskInfo,
+ Handler handler,
+ Choreographer choreographer,
+ int displayId,
+ SurfaceControl decorationSurface,
+ DragPositioningCallback callback,
+ Supplier<SurfaceControl.Builder> surfaceControlBuilderSupplier,
+ Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
+ DisplayController displayController) {
+ this(context, taskInfo, handler, choreographer, displayId, decorationSurface, callback,
+ surfaceControlBuilderSupplier, surfaceControlTransactionSupplier, displayController,
+ new DesktopModeEventLogger());
+ }
+
/**
* Updates the geometry (the touch region) of this drag resize handler.
*
@@ -274,6 +300,7 @@ class DragResizeInputListener implements AutoCloseable {
private static class TaskResizeInputEventReceiver extends InputEventReceiver implements
DragDetector.MotionEventHandler {
@NonNull private final Context mContext;
+ @NonNull private final RunningTaskInfo mTaskInfo;
private final InputManager mInputManager;
@NonNull private final InputChannel mInputChannel;
@NonNull private final DragPositioningCallback mCallback;
@@ -282,6 +309,7 @@ class DragResizeInputListener implements AutoCloseable {
@NonNull private final DragDetector mDragDetector;
@NonNull private final Supplier<Size> mDisplayLayoutSizeSupplier;
@NonNull private final Consumer<Region> mTouchRegionConsumer;
+ @NonNull private final DesktopModeEventLogger mDesktopModeEventLogger;
private final Rect mTmpRect = new Rect();
private boolean mConsumeBatchEventScheduled;
private DragResizeWindowGeometry mDragResizeWindowGeometry;
@@ -293,15 +321,24 @@ class DragResizeInputListener implements AutoCloseable {
// resize events. For example, if multiple fingers are touching the screen, then each one
// has a separate pointer id, but we only accept drag input from one.
private int mDragPointerId = -1;
+ // The type of resizing that is currently being done. Used to track the same resize trigger
+ // on start and end of the resizing action.
+ private ResizeTrigger mResizeTrigger = ResizeTrigger.UNKNOWN_RESIZE_TRIGGER;
+ // The last MotionEvent on ACTION_DOWN, used to track the input tool type and source for
+ // logging the start and end of the resizing action.
+ private MotionEvent mLastMotionEventOnDown;
private TaskResizeInputEventReceiver(@NonNull Context context,
+ @NonNull RunningTaskInfo taskInfo,
@NonNull InputChannel inputChannel,
@NonNull DragPositioningCallback callback, @NonNull Handler handler,
@NonNull Choreographer choreographer,
@NonNull Supplier<Size> displayLayoutSizeSupplier,
- @NonNull Consumer<Region> touchRegionConsumer) {
+ @NonNull Consumer<Region> touchRegionConsumer,
+ @NonNull DesktopModeEventLogger desktopModeEventLogger) {
super(inputChannel, handler.getLooper());
mContext = context;
+ mTaskInfo = taskInfo;
mInputManager = context.getSystemService(InputManager.class);
mInputChannel = inputChannel;
mCallback = callback;
@@ -322,6 +359,7 @@ class DragResizeInputListener implements AutoCloseable {
ViewConfiguration.get(mContext).getScaledTouchSlop());
mDisplayLayoutSizeSupplier = displayLayoutSizeSupplier;
mTouchRegionConsumer = touchRegionConsumer;
+ mDesktopModeEventLogger = desktopModeEventLogger;
}
/**
@@ -395,6 +433,7 @@ class DragResizeInputListener implements AutoCloseable {
@Override
public boolean handleMotionEvent(View v, MotionEvent e) {
boolean result = false;
+
// Check if this is a touch event vs mouse event.
// Touch events are tracked in four corners. Other events are tracked in resize edges.
switch (e.getActionMasked()) {
@@ -416,6 +455,13 @@ class DragResizeInputListener implements AutoCloseable {
"%s: Handling action down, update ctrlType to %d", TAG, ctrlType);
mDragStartTaskBounds = mCallback.onDragPositioningStart(ctrlType,
rawX, rawY);
+ mLastMotionEventOnDown = e;
+ mResizeTrigger = (ctrlType == CTRL_TYPE_BOTTOM || ctrlType == CTRL_TYPE_TOP
+ || ctrlType == CTRL_TYPE_RIGHT || ctrlType == CTRL_TYPE_LEFT)
+ ? ResizeTrigger.EDGE : ResizeTrigger.CORNER;
+ mDesktopModeEventLogger.logTaskResizingStarted(mResizeTrigger,
+ e, mTaskInfo, /* displayController= */ null,
+ /* displayLayoutSize= */ mDisplayLayoutSizeSupplier.get());
// Increase the input sink region to cover the whole screen; this is to
// prevent input and focus from going to other tasks during a drag resize.
updateInputSinkRegionForDrag(mDragStartTaskBounds);
@@ -464,6 +510,12 @@ class DragResizeInputListener implements AutoCloseable {
if (taskBounds.equals(mDragStartTaskBounds)) {
mTouchRegionConsumer.accept(mTouchRegion);
}
+
+ mDesktopModeEventLogger.logTaskResizingEnded(mResizeTrigger,
+ mLastMotionEventOnDown, mTaskInfo, taskBounds.height(),
+ taskBounds.width(),
+ /* displayController= */ null,
+ /* displayLayoutSize= */ mDisplayLayoutSizeSupplier.get());
}
mShouldHandleEvents = false;
mDragPointerId = -1;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
index 33d1c260cb84..844ceb304bde 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DragResizeWindowGeometry.java
@@ -181,7 +181,7 @@ final class DragResizeWindowGeometry {
}
private boolean isInEdgeResizeBounds(float x, float y) {
- return calculateEdgeResizeCtrlType(x, y) != 0;
+ return calculateEdgeResizeCtrlType(x, y) != CTRL_TYPE_UNDEFINED;
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
index 61b93932013c..bc85d2b40748 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java
@@ -76,13 +76,14 @@ class TaskOperations {
closeTask(taskToken, new WindowContainerTransaction());
}
- void closeTask(WindowContainerToken taskToken, WindowContainerTransaction wct) {
+ IBinder closeTask(WindowContainerToken taskToken, WindowContainerTransaction wct) {
wct.removeTask(taskToken);
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
- mTransitionStarter.startRemoveTransition(wct);
+ return mTransitionStarter.startRemoveTransition(wct);
} else {
mSyncQueue.queue(wct);
}
+ return null;
}
IBinder minimizeTask(WindowContainerToken taskToken) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 6b3b357f2f7b..34cc0986c83f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -58,6 +58,7 @@ import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.windowdecor.WindowDecoration.RelayoutParams.OccludingCaptionElement;
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewHostViewContainer;
@@ -111,6 +112,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
final Context mContext;
final @NonNull Context mUserContext;
final @NonNull DisplayController mDisplayController;
+ final @NonNull DesktopModeEventLogger mDesktopModeEventLogger;
final ShellTaskOrganizer mTaskOrganizer;
final Supplier<SurfaceControl.Builder> mSurfaceControlBuilderSupplier;
final Supplier<SurfaceControl.Transaction> mSurfaceControlTransactionSupplier;
@@ -163,7 +165,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
this(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface,
SurfaceControl.Builder::new, SurfaceControl.Transaction::new,
WindowContainerTransaction::new, SurfaceControl::new,
- new SurfaceControlViewHostFactory() {});
+ new SurfaceControlViewHostFactory() {}, new DesktopModeEventLogger());
}
WindowDecoration(
@@ -177,13 +179,16 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
Supplier<SurfaceControl> surfaceControlSupplier,
- SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
+ SurfaceControlViewHostFactory surfaceControlViewHostFactory,
+ @NonNull DesktopModeEventLogger desktopModeEventLogger
+ ) {
mContext = context;
mUserContext = userContext;
mDisplayController = displayController;
mTaskOrganizer = taskOrganizer;
mTaskInfo = taskInfo;
mTaskSurface = cloneSurfaceControl(taskSurface, surfaceControlSupplier);
+ mDesktopModeEventLogger = desktopModeEventLogger;
mSurfaceControlBuilderSupplier = surfaceControlBuilderSupplier;
mSurfaceControlTransactionSupplier = surfaceControlTransactionSupplier;
mWindowContainerTransactionSupplier = windowContainerTransactionSupplier;
diff --git a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
index b7ddfd1fc6eb..4fe66f3357a3 100644
--- a/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
+++ b/libs/WindowManager/Shell/tests/e2e/desktopmode/flicker-service/src/com/android/wm/shell/flicker/DesktopModeFlickerScenarios.kt
@@ -298,12 +298,18 @@ class DesktopModeFlickerScenarios {
FlickerConfigEntry(
scenarioId = ScenarioId("MAXIMIZE_APP"),
extractor =
- TaggedScenarioExtractorBuilder()
- .setTargetTag(CujType.CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW)
- .setTransitionMatcher(
- TaggedCujTransitionMatcher(associatedTransitionRequired = false)
- )
- .build(),
+ ShellTransitionScenarioExtractor(
+ transitionMatcher =
+ object : ITransitionMatcher {
+ override fun findAll(
+ transitions: Collection<Transition>
+ ): Collection<Transition> {
+ return transitions.filter {
+ it.type == TransitionType.DESKTOP_MODE_TOGGLE_RESIZE
+ }
+ }
+ }
+ ),
assertions = AssertionTemplates.DESKTOP_MODE_APP_VISIBILITY_ASSERTIONS +
listOf(
AppLayerIncreasesInSize(DESKTOP_MODE_APP),
@@ -316,12 +322,18 @@ class DesktopModeFlickerScenarios {
FlickerConfigEntry(
scenarioId = ScenarioId("MAXIMIZE_APP_NON_RESIZABLE"),
extractor =
- TaggedScenarioExtractorBuilder()
- .setTargetTag(CujType.CUJ_DESKTOP_MODE_MAXIMIZE_WINDOW)
- .setTransitionMatcher(
- TaggedCujTransitionMatcher(associatedTransitionRequired = false)
- )
- .build(),
+ ShellTransitionScenarioExtractor(
+ transitionMatcher =
+ object : ITransitionMatcher {
+ override fun findAll(
+ transitions: Collection<Transition>
+ ): Collection<Transition> {
+ return transitions.filter {
+ it.type == TransitionType.DESKTOP_MODE_TOGGLE_RESIZE
+ }
+ }
+ }
+ ),
assertions =
AssertionTemplates.DESKTOP_MODE_APP_VISIBILITY_ASSERTIONS +
listOf(
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java
index e6bd05b82be9..f935ac76bbeb 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/TestRunningTaskInfoBuilder.java
@@ -40,6 +40,8 @@ public final class TestRunningTaskInfoBuilder {
private WindowContainerToken mToken = createMockWCToken();
private int mParentTaskId = INVALID_TASK_ID;
+ private int mUid = INVALID_TASK_ID;
+ private int mTaskId = INVALID_TASK_ID;
private Intent mBaseIntent = new Intent();
private @WindowConfiguration.ActivityType int mActivityType = ACTIVITY_TYPE_STANDARD;
private @WindowConfiguration.WindowingMode int mWindowingMode = WINDOWING_MODE_UNDEFINED;
@@ -73,6 +75,18 @@ public final class TestRunningTaskInfoBuilder {
return this;
}
+ /** Sets the task info's effective UID. */
+ public TestRunningTaskInfoBuilder setUid(int uid) {
+ mUid = uid;
+ return this;
+ }
+
+ /** Sets the task info's UID. */
+ public TestRunningTaskInfoBuilder setTaskId(int taskId) {
+ mTaskId = taskId;
+ return this;
+ }
+
/**
* Set {@link ActivityManager.RunningTaskInfo#baseIntent} for the task info, by default
* an empty intent is assigned
@@ -132,7 +146,8 @@ public final class TestRunningTaskInfoBuilder {
public ActivityManager.RunningTaskInfo build() {
final ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
- info.taskId = sNextTaskId++;
+ info.taskId = (mTaskId == INVALID_TASK_ID) ? sNextTaskId++ : mTaskId;
+ info.effectiveUid = mUid;
info.baseIntent = mBaseIntent;
info.parentTaskId = mParentTaskId;
info.displayId = mDisplayId;
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandlerTest.kt
index b13746814f58..ef99b000d759 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopFullImmersiveTransitionHandlerTest.kt
@@ -52,6 +52,7 @@ import org.mockito.Mockito.mock
import org.mockito.kotlin.any
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
@@ -366,7 +367,7 @@ class DesktopFullImmersiveTransitionHandlerTest : ShellTestCase() {
immersive = false
)
- immersiveHandler.exitImmersiveIfApplicable(wct, task.taskId)
+ immersiveHandler.exitImmersiveIfApplicable(wct, task)
assertThat(wct.hasBoundsChange(task.token)).isFalse()
}
@@ -384,12 +385,12 @@ class DesktopFullImmersiveTransitionHandlerTest : ShellTestCase() {
immersive = true
)
- immersiveHandler.exitImmersiveIfApplicable(wct, task.taskId)?.invoke(transition)
+ immersiveHandler.exitImmersiveIfApplicable(wct, task)?.invoke(transition)
assertThat(immersiveHandler.pendingExternalExitTransitions.any { exit ->
exit.transition == transition && exit.displayId == DEFAULT_DISPLAY
&& exit.taskId == task.taskId
- }).isFalse()
+ }).isTrue()
}
@Test
@@ -405,7 +406,7 @@ class DesktopFullImmersiveTransitionHandlerTest : ShellTestCase() {
immersive = false
)
- immersiveHandler.exitImmersiveIfApplicable(wct, task.taskId)?.invoke(transition)
+ immersiveHandler.exitImmersiveIfApplicable(wct, task)?.invoke(transition)
assertThat(immersiveHandler.pendingExternalExitTransitions.any { exit ->
exit.transition == transition && exit.displayId == DEFAULT_DISPLAY
@@ -565,6 +566,24 @@ class DesktopFullImmersiveTransitionHandlerTest : ShellTestCase() {
).isTrue()
}
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP)
+ fun exitImmersive_pendingExit_doesNotExitAgain() {
+ val task = createFreeformTask()
+ whenever(mockShellTaskOrganizer.getRunningTaskInfo(task.taskId)).thenReturn(task)
+ val wct = WindowContainerTransaction()
+ desktopRepository.setTaskInFullImmersiveState(
+ displayId = task.displayId,
+ taskId = task.taskId,
+ immersive = true
+ )
+ immersiveHandler.exitImmersiveIfApplicable(wct, task)?.invoke(Binder())
+
+ immersiveHandler.moveTaskToNonImmersive(task)
+
+ verify(mockTransitions, never()).startTransition(any(), any(), any())
+ }
+
private fun createTransitionInfo(
@TransitionType type: Int = TRANSIT_CHANGE,
@TransitionFlags flags: Int = 0,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt
index 07de0716200c..81d59d586dd3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopMixedTransitionHandlerTest.kt
@@ -21,6 +21,7 @@ import android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD
import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM
import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN
import android.app.WindowConfiguration.WindowingMode
+import android.os.Binder
import android.os.Handler
import android.os.IBinder
import android.testing.AndroidTestingRunner
@@ -107,6 +108,8 @@ class DesktopMixedTransitionHandlerTest : ShellTestCase() {
@Test
fun startRemoveTransition_startsCloseTransition() {
val wct = WindowContainerTransaction()
+ whenever(transitions.startTransition(WindowManager.TRANSIT_CLOSE, wct, mixedHandler))
+ .thenReturn(Binder())
mixedHandler.startRemoveTransition(wct)
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt
index 0825b6b0d7be..2a82e6e4f7b8 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeEventLoggerTest.kt
@@ -16,9 +16,12 @@
package com.android.wm.shell.desktopmode
+import android.app.ActivityManager.RunningTaskInfo
+import android.graphics.Rect
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.SetFlagsRule
import com.android.dx.mockito.inline.extended.ExtendedMockito.clearInvocations
+import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
import com.android.dx.mockito.inline.extended.ExtendedMockito.staticMockMarker
import com.android.dx.mockito.inline.extended.ExtendedMockito.verify
import com.android.dx.mockito.inline.extended.ExtendedMockito.verifyZeroInteractions
@@ -27,6 +30,9 @@ import com.android.modules.utils.testing.ExtendedMockitoRule
import com.android.window.flags.Flags
import com.android.wm.shell.EventLogTags
import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.TestRunningTaskInfoBuilder
+import com.android.wm.shell.common.DisplayController
+import com.android.wm.shell.common.DisplayLayout
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.EnterReason
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ExitReason
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.InputMethod
@@ -39,9 +45,13 @@ import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UNSET_M
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UNSET_UNMINIMIZE_REASON
import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.UnminimizeReason
import com.google.common.truth.Truth.assertThat
+import org.junit.Before
import org.junit.Rule
import org.junit.Test
+import org.mockito.ArgumentMatchers.anyInt
import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
/**
* Tests for [DesktopModeEventLogger].
@@ -49,6 +59,8 @@ import org.mockito.kotlin.eq
class DesktopModeEventLoggerTest : ShellTestCase() {
private val desktopModeEventLogger = DesktopModeEventLogger()
+ val displayController = mock<DisplayController>()
+ val displayLayout = mock<DisplayLayout>()
@JvmField
@Rule(order = 0)
@@ -60,6 +72,13 @@ class DesktopModeEventLoggerTest : ShellTestCase() {
@Rule(order = 1)
val setFlagsRule = SetFlagsRule()
+ @Before
+ fun setUp() {
+ doReturn(displayLayout).whenever(displayController).getDisplayLayout(anyInt())
+ doReturn(DISPLAY_WIDTH).whenever(displayLayout).width()
+ doReturn(DISPLAY_HEIGHT).whenever(displayLayout).height()
+ }
+
@Test
fun logSessionEnter_logsEnterReasonWithNewSessionId() {
desktopModeEventLogger.logSessionEnter(EnterReason.KEYBOARD_SHORTCUT_ENTER)
@@ -467,7 +486,8 @@ class DesktopModeEventLoggerTest : ShellTestCase() {
@Test
fun logTaskResizingStarted_noOngoingSession_doesNotLog() {
- desktopModeEventLogger.logTaskResizingStarted(TASK_SIZE_UPDATE)
+ desktopModeEventLogger.logTaskResizingStarted(ResizeTrigger.CORNER,
+ null, createTaskInfo())
verifyZeroInteractions(staticMockMarker(FrameworkStatsLog::class.java))
verifyZeroInteractions(staticMockMarker(EventLogTags::class.java))
@@ -478,13 +498,14 @@ class DesktopModeEventLoggerTest : ShellTestCase() {
fun logTaskResizingStarted_logsTaskSizeUpdatedWithStartResizingStage() {
val sessionId = startDesktopModeSession()
- desktopModeEventLogger.logTaskResizingStarted(TASK_SIZE_UPDATE)
+ desktopModeEventLogger.logTaskResizingStarted(ResizeTrigger.CORNER,
+ null, createTaskInfo(), displayController)
verify {
FrameworkStatsLog.write(
eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED),
/* resize_trigger */
- eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__UNKNOWN_RESIZE_TRIGGER),
+ eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__CORNER_RESIZE_TRIGGER),
/* resizing_stage */
eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__START_RESIZING_STAGE),
/* input_method */
@@ -500,7 +521,7 @@ class DesktopModeEventLoggerTest : ShellTestCase() {
/* task_width */
eq(TASK_SIZE_UPDATE.taskWidth),
/* display_area */
- eq(TASK_SIZE_UPDATE.displayArea),
+ eq(DISPLAY_AREA),
)
}
verifyZeroInteractions(staticMockMarker(FrameworkStatsLog::class.java))
@@ -508,7 +529,8 @@ class DesktopModeEventLoggerTest : ShellTestCase() {
@Test
fun logTaskResizingEnded_noOngoingSession_doesNotLog() {
- desktopModeEventLogger.logTaskResizingEnded(TASK_SIZE_UPDATE)
+ desktopModeEventLogger.logTaskResizingEnded(ResizeTrigger.CORNER,
+ null, createTaskInfo())
verifyZeroInteractions(staticMockMarker(FrameworkStatsLog::class.java))
verifyZeroInteractions(staticMockMarker(EventLogTags::class.java))
@@ -519,13 +541,14 @@ class DesktopModeEventLoggerTest : ShellTestCase() {
fun logTaskResizingEnded_logsTaskSizeUpdatedWithEndResizingStage() {
val sessionId = startDesktopModeSession()
- desktopModeEventLogger.logTaskResizingEnded(TASK_SIZE_UPDATE)
+ desktopModeEventLogger.logTaskResizingEnded(ResizeTrigger.CORNER,
+ null, createTaskInfo(), displayController = displayController)
verify {
FrameworkStatsLog.write(
eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED),
/* resize_trigger */
- eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__UNKNOWN_RESIZE_TRIGGER),
+ eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZE_TRIGGER__CORNER_RESIZE_TRIGGER),
/* resizing_stage */
eq(FrameworkStatsLog.DESKTOP_MODE_TASK_SIZE_UPDATED__RESIZING_STAGE__END_RESIZING_STAGE),
/* input_method */
@@ -541,7 +564,7 @@ class DesktopModeEventLoggerTest : ShellTestCase() {
/* task_width */
eq(TASK_SIZE_UPDATE.taskWidth),
/* display_area */
- eq(TASK_SIZE_UPDATE.displayArea),
+ eq(DISPLAY_AREA),
)
}
verifyZeroInteractions(staticMockMarker(FrameworkStatsLog::class.java))
@@ -585,8 +608,14 @@ class DesktopModeEventLoggerTest : ShellTestCase() {
}
}
+ private fun createTaskInfo(): RunningTaskInfo {
+ return TestRunningTaskInfoBuilder().setTaskId(TASK_ID)
+ .setUid(TASK_UID)
+ .setBounds(Rect(TASK_X, TASK_Y, TASK_WIDTH, TASK_HEIGHT))
+ .build()
+ }
+
private companion object {
- private const val sessionId = 1
private const val TASK_ID = 1
private const val TASK_UID = 1
private const val TASK_X = 0
@@ -594,7 +623,9 @@ class DesktopModeEventLoggerTest : ShellTestCase() {
private const val TASK_HEIGHT = 100
private const val TASK_WIDTH = 100
private const val TASK_COUNT = 1
- private const val DISPLAY_AREA = 1000
+ private const val DISPLAY_WIDTH = 500
+ private const val DISPLAY_HEIGHT = 500
+ private const val DISPLAY_AREA = DISPLAY_HEIGHT * DISPLAY_WIDTH
private val TASK_UPDATE = TaskUpdate(
TASK_ID, TASK_UID, TASK_HEIGHT, TASK_WIDTH, TASK_X, TASK_Y,
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 113990e9d7d2..7c336cdb54f6 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
@@ -39,6 +39,9 @@ import android.content.res.Configuration.ORIENTATION_PORTRAIT
import android.graphics.Point
import android.graphics.PointF
import android.graphics.Rect
+import android.hardware.input.InputManager
+import android.hardware.input.InputManager.KeyGestureEventHandler
+import android.hardware.input.KeyGestureEvent
import android.os.Binder
import android.os.Bundle
import android.os.Handler
@@ -50,6 +53,8 @@ import android.testing.AndroidTestingRunner
import android.view.Display.DEFAULT_DISPLAY
import android.view.DragEvent
import android.view.Gravity
+import android.view.KeyEvent
+import android.view.MotionEvent
import android.view.SurfaceControl
import android.view.WindowInsets
import android.view.WindowManager
@@ -70,14 +75,18 @@ import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_R
import android.window.WindowContainerTransaction.HierarchyOp.HIERARCHY_OP_TYPE_REORDER
import android.window.WindowContainerTransaction.HierarchyOp.LAUNCH_KEY_TASK_ID
import androidx.test.filters.SmallTest
+import com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer
import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.android.dx.mockito.inline.extended.ExtendedMockito.never
import com.android.dx.mockito.inline.extended.StaticMockitoSession
+import com.android.hardware.input.Flags.FLAG_USE_KEY_GESTURE_EVENT_HANDLER
import com.android.internal.jank.InteractionJankMonitor
import com.android.window.flags.Flags
import com.android.window.flags.Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE
+import com.android.window.flags.Flags.FLAG_ENABLE_DISPLAY_FOCUS_IN_SHELL_TRANSITIONS
import com.android.window.flags.Flags.FLAG_ENABLE_FULLY_IMMERSIVE_IN_DESKTOP
+import com.android.window.flags.Flags.FLAG_ENABLE_MOVE_TO_NEXT_DISPLAY_SHORTCUT
import com.android.wm.shell.MockToken
import com.android.wm.shell.R
import com.android.wm.shell.RootTaskDisplayAreaOrganizer
@@ -91,6 +100,7 @@ import com.android.wm.shell.common.LaunchAdjacentController
import com.android.wm.shell.common.MultiInstanceHelper
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SyncTransactionQueue
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger
import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition
import com.android.wm.shell.desktopmode.DesktopTasksController.TaskbarDesktopTaskListener
import com.android.wm.shell.desktopmode.DesktopTestHelpers.Companion.createFreeformTask
@@ -112,6 +122,7 @@ 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 com.android.wm.shell.transition.FocusTransitionObserver
import com.android.wm.shell.transition.OneShotRemoteHandler
import com.android.wm.shell.transition.TestRemoteTransition
import com.android.wm.shell.transition.Transitions
@@ -205,7 +216,11 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Mock private lateinit var taskbarDesktopTaskListener: TaskbarDesktopTaskListener
@Mock private lateinit var freeformTaskTransitionStarter: FreeformTaskTransitionStarter
@Mock private lateinit var mockHandler: Handler
+ @Mock private lateinit var desktopModeEventLogger: DesktopModeEventLogger
@Mock lateinit var persistentRepository: DesktopPersistentRepository
+ @Mock private lateinit var mockInputManager: InputManager
+ @Mock private lateinit var mockFocusTransitionObserver: FocusTransitionObserver
+ @Mock lateinit var motionEvent: MotionEvent
private lateinit var mockitoSession: StaticMockitoSession
private lateinit var controller: DesktopTasksController
@@ -214,6 +229,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
private lateinit var desktopTasksLimiter: DesktopTasksLimiter
private lateinit var recentsTransitionStateListener: RecentsTransitionStateListener
private lateinit var testScope: CoroutineScope
+ private lateinit var keyGestureEventHandler: KeyGestureEventHandler
private val shellExecutor = TestShellExecutor()
@@ -271,6 +287,11 @@ class DesktopTasksControllerTest : ShellTestCase() {
controller.setSplitScreenController(splitScreenController)
controller.freeformTaskTransitionStarter = freeformTaskTransitionStarter
+ doAnswer {
+ keyGestureEventHandler = (it.arguments[0] as KeyGestureEventHandler)
+ null
+ }.whenever(mockInputManager).registerKeyGestureEventHandler(any())
+
shellInit.init()
val captor = ArgumentCaptor.forClass(RecentsTransitionStateListener::class.java)
@@ -278,6 +299,8 @@ class DesktopTasksControllerTest : ShellTestCase() {
recentsTransitionStateListener = captor.value
controller.taskbarDesktopTaskListener = taskbarDesktopTaskListener
+
+ assumeTrue(ENABLE_SHELL_TRANSITIONS)
}
private fun createController(): DesktopTasksController {
@@ -310,6 +333,9 @@ class DesktopTasksControllerTest : ShellTestCase() {
recentTasksController,
mockInteractionJankMonitor,
mockHandler,
+ mockInputManager,
+ mockFocusTransitionObserver,
+ desktopModeEventLogger,
)
}
@@ -338,9 +364,17 @@ class DesktopTasksControllerTest : ShellTestCase() {
val task1 = setUpFreeformTask()
val argumentCaptor = ArgumentCaptor.forClass(Boolean::class.java)
- controller.toggleDesktopTaskSize(task1)
- verify(taskbarDesktopTaskListener).onTaskbarCornerRoundingUpdate(argumentCaptor.capture())
+ controller.toggleDesktopTaskSize(task1, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent)
+ verify(taskbarDesktopTaskListener).onTaskbarCornerRoundingUpdate(argumentCaptor.capture())
+ verify(desktopModeEventLogger, times(1)).logTaskResizingEnded(
+ ResizeTrigger.MAXIMIZE_BUTTON,
+ motionEvent,
+ task1,
+ STABLE_BOUNDS.height(),
+ STABLE_BOUNDS.width(),
+ displayController
+ )
assertThat(argumentCaptor.value).isTrue()
}
@@ -357,9 +391,17 @@ class DesktopTasksControllerTest : ShellTestCase() {
val task1 = setUpFreeformTask(bounds = stableBounds, active = true)
val argumentCaptor = ArgumentCaptor.forClass(Boolean::class.java)
- controller.toggleDesktopTaskSize(task1)
- verify(taskbarDesktopTaskListener).onTaskbarCornerRoundingUpdate(argumentCaptor.capture())
+ controller.toggleDesktopTaskSize(task1, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent)
+ verify(taskbarDesktopTaskListener).onTaskbarCornerRoundingUpdate(argumentCaptor.capture())
+ verify(desktopModeEventLogger, times(1)).logTaskResizingEnded(
+ ResizeTrigger.MAXIMIZE_BUTTON,
+ motionEvent,
+ task1,
+ 0,
+ 0,
+ displayController
+ )
assertThat(argumentCaptor.value).isFalse()
}
@@ -735,7 +777,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
@EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS)
fun handleRequest_newFreeformTaskLaunch_cascadeApplied() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
setUpLandscapeDisplay()
val stableBounds = Rect()
displayLayout.getStableBoundsForDesktopMode(stableBounds)
@@ -754,7 +795,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
@EnableFlags(Flags.FLAG_ENABLE_CASCADING_WINDOWS)
fun handleRequest_freeformTaskAlreadyExistsInDesktopMode_cascadeNotApplied() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
setUpLandscapeDisplay()
val stableBounds = Rect()
displayLayout.getStableBoundsForDesktopMode(stableBounds)
@@ -1467,6 +1507,44 @@ class DesktopTasksControllerTest : ShellTestCase() {
}
@Test
+ @EnableFlags(
+ FLAG_ENABLE_DISPLAY_FOCUS_IN_SHELL_TRANSITIONS,
+ FLAG_ENABLE_MOVE_TO_NEXT_DISPLAY_SHORTCUT,
+ FLAG_USE_KEY_GESTURE_EVENT_HANDLER
+ )
+ fun moveToNextDisplay_withKeyGesture() {
+ // 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)
+ // Setup a focused task on secondary display, which is expected to move to default display
+ val task = setUpFreeformTask(displayId = SECOND_DISPLAY)
+ task.isFocused = true
+ whenever(shellTaskOrganizer.getRunningTasks()).thenReturn(arrayListOf(task))
+ whenever(mockFocusTransitionObserver.hasGlobalFocus(eq(task))).thenReturn(true)
+
+ val event = KeyGestureEvent.Builder()
+ .setKeyGestureType(KeyGestureEvent.KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY)
+ .setDisplayId(SECOND_DISPLAY)
+ .setKeycodes(intArrayOf(KeyEvent.KEYCODE_D))
+ .setModifierState(KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON)
+ .build()
+ val result = keyGestureEventHandler.handleKeyGestureEvent(event, null)
+
+ assertThat(result).isTrue()
+ with(getLatestWct(type = 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()
@@ -1480,8 +1558,9 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun onDesktopWindowClose_noActiveTasks() {
+ val task = setUpFreeformTask(active = false)
val wct = WindowContainerTransaction()
- controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = 1)
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, task)
// Doesn't modify transaction
assertThat(wct.hierarchyOps).isEmpty()
}
@@ -1490,7 +1569,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
fun onDesktopWindowClose_singleActiveTask_noWallpaperActivityToken() {
val task = setUpFreeformTask()
val wct = WindowContainerTransaction()
- controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, task)
// Doesn't modify transaction
assertThat(wct.hierarchyOps).isEmpty()
}
@@ -1502,7 +1581,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
taskRepository.wallpaperActivityToken = wallpaperToken
val wct = WindowContainerTransaction()
- controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, task)
// Adds remove wallpaper operation
wct.assertRemoveAt(index = 0, wallpaperToken)
}
@@ -1515,7 +1594,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
taskRepository.addClosingTask(DEFAULT_DISPLAY, task.taskId)
val wct = WindowContainerTransaction()
- controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, task)
// Doesn't modify transaction
assertThat(wct.hierarchyOps).isEmpty()
}
@@ -1528,7 +1607,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
taskRepository.minimizeTask(DEFAULT_DISPLAY, task.taskId)
val wct = WindowContainerTransaction()
- controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task.taskId)
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, task)
// Doesn't modify transaction
assertThat(wct.hierarchyOps).isEmpty()
}
@@ -1541,7 +1620,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
taskRepository.wallpaperActivityToken = wallpaperToken
val wct = WindowContainerTransaction()
- controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task1.taskId)
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, task1)
// Doesn't modify transaction
assertThat(wct.hierarchyOps).isEmpty()
}
@@ -1555,7 +1634,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
taskRepository.addClosingTask(DEFAULT_DISPLAY, task2.taskId)
val wct = WindowContainerTransaction()
- controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task1.taskId)
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, task1)
// Adds remove wallpaper operation
wct.assertRemoveAt(index = 0, wallpaperToken)
}
@@ -1569,7 +1648,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
taskRepository.minimizeTask(DEFAULT_DISPLAY, task2.taskId)
val wct = WindowContainerTransaction()
- controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, taskId = task1.taskId)
+ controller.onDesktopWindowClose(wct, displayId = DEFAULT_DISPLAY, task1)
// Adds remove wallpaper operation
wct.assertRemoveAt(index = 0, wallpaperToken)
}
@@ -1715,8 +1794,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_fullscreenTask_freeformVisible_returnSwitchToFreeformWCT() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val homeTask = setUpHomeTask()
val freeformTask = setUpFreeformTask()
markTaskVisible(freeformTask)
@@ -1733,8 +1810,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_fullscreenTaskWithTaskOnHome_freeformVisible_returnSwitchToFreeformWCT() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val homeTask = setUpHomeTask()
val freeformTask = setUpFreeformTask()
markTaskVisible(freeformTask)
@@ -1760,8 +1835,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_fullscreenTaskToFreeform_underTaskLimit_dontMinimize() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val freeformTask = setUpFreeformTask()
markTaskVisible(freeformTask)
val fullscreenTask = createFullscreenTask()
@@ -1775,8 +1848,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_fullscreenTaskToFreeform_bringsTasksOverLimit_otherTaskIsMinimized() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val freeformTasks = (1..MAX_TASK_LIMIT).map { _ -> setUpFreeformTask() }
freeformTasks.forEach { markTaskVisible(it) }
val fullscreenTask = createFullscreenTask()
@@ -1791,8 +1862,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_fullscreenTaskWithTaskOnHome_bringsTasksOverLimit_otherTaskIsMinimized() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val freeformTasks = (1..MAX_TASK_LIMIT).map { _ -> setUpFreeformTask() }
freeformTasks.forEach { markTaskVisible(it) }
val fullscreenTask = createFullscreenTask()
@@ -1808,8 +1877,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_fullscreenTaskWithTaskOnHome_beyondLimit_existingAndNewTasksAreMinimized() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val minimizedTask = setUpFreeformTask()
taskRepository.minimizeTask(displayId = DEFAULT_DISPLAY, taskId = minimizedTask.taskId)
val freeformTasks = (1..MAX_TASK_LIMIT).map { _ -> setUpFreeformTask() }
@@ -1830,7 +1897,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_fullscreenTask_noTasks_enforceDesktop_freeformDisplay_returnFreeformWCT() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
whenever(DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(context)).thenReturn(true)
val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM
@@ -1847,7 +1913,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_fullscreenTask_noTasks_enforceDesktop_fullscreenDisplay_returnNull() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
whenever(DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(context)).thenReturn(true)
val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
@@ -1860,8 +1925,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_fullscreenTask_freeformNotVisible_returnNull() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val freeformTask = setUpFreeformTask()
markTaskHidden(freeformTask)
val fullscreenTask = createFullscreenTask()
@@ -1870,16 +1933,12 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_fullscreenTask_noOtherTasks_returnNull() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val fullscreenTask = createFullscreenTask()
assertThat(controller.handleRequest(Binder(), createTransition(fullscreenTask))).isNull()
}
@Test
fun handleRequest_fullscreenTask_freeformTaskOnOtherDisplay_returnNull() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val fullscreenTaskDefaultDisplay = createFullscreenTask(displayId = DEFAULT_DISPLAY)
createFreeformTask(displayId = SECOND_DISPLAY)
@@ -1889,8 +1948,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_freeformTask_freeformVisible_aboveTaskLimit_minimize() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val freeformTasks = (1..MAX_TASK_LIMIT).map { _ -> setUpFreeformTask() }
freeformTasks.forEach { markTaskVisible(it) }
val newFreeformTask = createFreeformTask()
@@ -1903,8 +1960,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_freeformTask_relaunchActiveTask_taskBecomesUndefined() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val freeformTask = setUpFreeformTask()
markTaskHidden(freeformTask)
@@ -1919,7 +1974,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_freeformTask_relaunchTask_enforceDesktop_freeformDisplay_noWinModeChange() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
whenever(DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(context)).thenReturn(true)
val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FREEFORM
@@ -1934,7 +1988,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_freeformTask_relaunchTask_enforceDesktop_fullscreenDisplay_becomesUndefined() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
whenever(DesktopModeStatus.enterDesktopByDefaultOnFreeformDisplay(context)).thenReturn(true)
val tda = rootTaskDisplayAreaOrganizer.getDisplayAreaInfo(DEFAULT_DISPLAY)!!
tda.configuration.windowConfiguration.windowingMode = WINDOWING_MODE_FULLSCREEN
@@ -1951,8 +2004,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
@DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
fun handleRequest_freeformTask_desktopWallpaperDisabled_freeformNotVisible_reorderedToTop() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val freeformTask1 = setUpFreeformTask()
val freeformTask2 = createFreeformTask()
@@ -1968,8 +2019,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
fun handleRequest_freeformTask_desktopWallpaperEnabled_freeformNotVisible_reorderedToTop() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val freeformTask1 = setUpFreeformTask()
val freeformTask2 = createFreeformTask()
@@ -1990,8 +2039,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
@DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
fun handleRequest_freeformTask_desktopWallpaperDisabled_noOtherTasks_reorderedToTop() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val task = createFreeformTask()
val result = controller.handleRequest(Binder(), createTransition(task))
@@ -2003,8 +2050,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
fun handleRequest_freeformTask_desktopWallpaperEnabled_noOtherTasks_reorderedToTop() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val task = createFreeformTask()
val result = controller.handleRequest(Binder(), createTransition(task))
@@ -2019,8 +2064,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
@DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
fun handleRequest_freeformTask_dskWallpaperDisabled_freeformOnOtherDisplayOnly_reorderedToTop() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val taskDefaultDisplay = createFreeformTask(displayId = DEFAULT_DISPLAY)
// Second display task
createFreeformTask(displayId = SECOND_DISPLAY)
@@ -2035,8 +2078,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY)
fun handleRequest_freeformTask_dskWallpaperEnabled_freeformOnOtherDisplayOnly_reorderedToTop() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val taskDefaultDisplay = createFreeformTask(displayId = DEFAULT_DISPLAY)
// Second display task
createFreeformTask(displayId = SECOND_DISPLAY)
@@ -2053,7 +2094,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_freeformTask_alreadyInDesktop_noOverrideDensity_noConfigDensityChange() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
whenever(DesktopModeStatus.useDesktopOverrideDensity()).thenReturn(false)
val freeformTask1 = setUpFreeformTask()
@@ -2067,7 +2107,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_freeformTask_alreadyInDesktop_overrideDensity_hasConfigDensityChange() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
whenever(DesktopModeStatus.useDesktopOverrideDensity()).thenReturn(true)
val freeformTask1 = setUpFreeformTask()
@@ -2081,7 +2120,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_freeformTask_keyguardLocked_returnNull() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
val freeformTask = createFreeformTask(displayId = DEFAULT_DISPLAY)
@@ -2092,8 +2130,6 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_notOpenOrToFrontTransition_returnNull() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val task =
TestRunningTaskInfoBuilder()
.setActivityType(ACTIVITY_TYPE_STANDARD)
@@ -2106,21 +2142,17 @@ class DesktopTasksControllerTest : ShellTestCase() {
@Test
fun handleRequest_noTriggerTask_returnNull() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
assertThat(controller.handleRequest(Binder(), createTransition(task = null))).isNull()
}
@Test
fun handleRequest_triggerTaskNotStandard_returnNull() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
val task = TestRunningTaskInfoBuilder().setActivityType(ACTIVITY_TYPE_HOME).build()
assertThat(controller.handleRequest(Binder(), createTransition(task))).isNull()
}
@Test
fun handleRequest_triggerTaskNotFullscreenOrFreeform_returnNull() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
-
val task =
TestRunningTaskInfoBuilder()
.setActivityType(ACTIVITY_TYPE_STANDARD)
@@ -2802,7 +2834,8 @@ class DesktopTasksControllerTest : ShellTestCase() {
PointF(200f, -200f), /* inputCoordinate */
Rect(100, -100, 500, 1000), /* currentDragBounds */
Rect(0, 50, 2000, 2000), /* validDragArea */
- Rect() /* dragStartBounds */ )
+ Rect() /* dragStartBounds */,
+ motionEvent)
val rectAfterEnd = Rect(100, 50, 500, 1150)
verify(transitions)
.startTransition(
@@ -2837,7 +2870,8 @@ class DesktopTasksControllerTest : ShellTestCase() {
PointF(200f, 300f), /* inputCoordinate */
currentDragBounds, /* currentDragBounds */
Rect(0, 50, 2000, 2000) /* validDragArea */,
- Rect() /* dragStartBounds */)
+ Rect() /* dragStartBounds */,
+ motionEvent)
verify(transitions)
@@ -3084,10 +3118,19 @@ class DesktopTasksControllerTest : ShellTestCase() {
val bounds = Rect(0, 0, 100, 100)
val task = setUpFreeformTask(DEFAULT_DISPLAY, bounds)
- controller.toggleDesktopTaskSize(task)
+ controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent)
+
// Assert bounds set to stable bounds
val wct = getLatestToggleResizeDesktopTaskWct()
assertThat(findBoundsChange(wct, task)).isEqualTo(STABLE_BOUNDS)
+ verify(desktopModeEventLogger, times(1)).logTaskResizingEnded(
+ ResizeTrigger.MAXIMIZE_BUTTON,
+ motionEvent,
+ task,
+ STABLE_BOUNDS.height(),
+ STABLE_BOUNDS.width(),
+ displayController
+ )
}
@Test
@@ -3106,15 +3149,22 @@ class DesktopTasksControllerTest : ShellTestCase() {
STABLE_BOUNDS.left, STABLE_BOUNDS.top, STABLE_BOUNDS.right / 2, STABLE_BOUNDS.bottom
)
- controller.snapToHalfScreen(task, mockSurface, currentDragBounds, SnapPosition.LEFT)
+ controller.snapToHalfScreen(task, mockSurface, currentDragBounds, SnapPosition.LEFT, ResizeTrigger.SNAP_LEFT_MENU, motionEvent)
// Assert bounds set to stable bounds
val wct = getLatestToggleResizeDesktopTaskWct(currentDragBounds)
assertThat(findBoundsChange(wct, task)).isEqualTo(expectedBounds)
+ verify(desktopModeEventLogger, times(1)).logTaskResizingEnded(
+ ResizeTrigger.SNAP_LEFT_MENU,
+ motionEvent,
+ task,
+ expectedBounds.height(),
+ expectedBounds.width(),
+ displayController
+ )
}
@Test
fun snapToHalfScreen_snapBoundsWhenAlreadySnapped_animatesSurfaceWithoutWCT() {
- assumeTrue(ENABLE_SHELL_TRANSITIONS)
// Set up task to already be in snapped-left bounds
val bounds = Rect(
STABLE_BOUNDS.left, STABLE_BOUNDS.top, STABLE_BOUNDS.right / 2, STABLE_BOUNDS.bottom
@@ -3129,7 +3179,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
// Attempt to snap left again
val currentDragBounds = Rect(bounds).apply { offset(-100, 0) }
- controller.snapToHalfScreen(task, mockSurface, currentDragBounds, SnapPosition.LEFT)
+ controller.snapToHalfScreen(task, mockSurface, currentDragBounds, SnapPosition.LEFT, ResizeTrigger.SNAP_LEFT_MENU, motionEvent)
// Assert that task is NOT updated via WCT
verify(toggleResizeDesktopTaskTransitionHandler, never()).startTransition(any(), any())
@@ -3142,6 +3192,14 @@ class DesktopTasksControllerTest : ShellTestCase() {
eq(bounds),
eq(true)
)
+ verify(desktopModeEventLogger, times(1)).logTaskResizingEnded(
+ ResizeTrigger.SNAP_LEFT_MENU,
+ motionEvent,
+ task,
+ bounds.height(),
+ bounds.width(),
+ displayController
+ )
}
@Test
@@ -3152,12 +3210,22 @@ class DesktopTasksControllerTest : ShellTestCase() {
}
val preDragBounds = Rect(100, 100, 400, 500)
val currentDragBounds = Rect(0, 100, 300, 500)
+ val expectedBounds =
+ Rect(STABLE_BOUNDS.left, STABLE_BOUNDS.top, STABLE_BOUNDS.right / 2, STABLE_BOUNDS.bottom)
controller.handleSnapResizingTask(
- task, SnapPosition.LEFT, mockSurface, currentDragBounds, preDragBounds)
+ task, SnapPosition.LEFT, mockSurface, currentDragBounds, preDragBounds, motionEvent
+ )
val wct = getLatestToggleResizeDesktopTaskWct(currentDragBounds)
assertThat(findBoundsChange(wct, task)).isEqualTo(
- Rect(STABLE_BOUNDS.left, STABLE_BOUNDS.top, STABLE_BOUNDS.right / 2, STABLE_BOUNDS.bottom))
+ expectedBounds
+ )
+ verify(desktopModeEventLogger, times(1)).logTaskResizingStarted(
+ ResizeTrigger.DRAG_LEFT,
+ motionEvent,
+ task,
+ displayController
+ )
}
@Test
@@ -3170,7 +3238,7 @@ class DesktopTasksControllerTest : ShellTestCase() {
val currentDragBounds = Rect(0, 100, 300, 500)
controller.handleSnapResizingTask(
- task, SnapPosition.LEFT, mockSurface, currentDragBounds, preDragBounds)
+ task, SnapPosition.LEFT, mockSurface, currentDragBounds, preDragBounds, motionEvent)
verify(mReturnToDragStartAnimator).start(
eq(task.taskId),
eq(mockSurface),
@@ -3178,6 +3246,13 @@ class DesktopTasksControllerTest : ShellTestCase() {
eq(preDragBounds),
eq(false)
)
+ verify(desktopModeEventLogger, never()).logTaskResizingStarted(
+ any(),
+ any(),
+ any(),
+ any(),
+ any()
+ )
}
@Test
@@ -3196,10 +3271,19 @@ class DesktopTasksControllerTest : ShellTestCase() {
// Bounds should be 1000 x 500, vertically centered in the 1000 x 1000 stable bounds
val expectedBounds = Rect(STABLE_BOUNDS.left, 250, STABLE_BOUNDS.right, 750)
- controller.toggleDesktopTaskSize(task)
+ controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent)
+
// Assert bounds set to stable bounds
val wct = getLatestToggleResizeDesktopTaskWct()
assertThat(findBoundsChange(wct, task)).isEqualTo(expectedBounds)
+ verify(desktopModeEventLogger, times(1)).logTaskResizingEnded(
+ ResizeTrigger.MAXIMIZE_BUTTON,
+ motionEvent,
+ task,
+ expectedBounds.height(),
+ expectedBounds.width(),
+ displayController
+ )
}
@Test
@@ -3207,8 +3291,12 @@ class DesktopTasksControllerTest : ShellTestCase() {
val bounds = Rect(0, 0, 100, 100)
val task = setUpFreeformTask(DEFAULT_DISPLAY, bounds)
- controller.toggleDesktopTaskSize(task)
+ controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent)
assertThat(taskRepository.removeBoundsBeforeMaximize(task.taskId)).isEqualTo(bounds)
+ verify(desktopModeEventLogger, never()).logTaskResizingEnded(
+ any(), any(), any(), any(),
+ any(), any(), any()
+ )
}
@Test
@@ -3217,15 +3305,23 @@ class DesktopTasksControllerTest : ShellTestCase() {
val task = setUpFreeformTask(DEFAULT_DISPLAY, boundsBeforeMaximize)
// Maximize
- controller.toggleDesktopTaskSize(task)
+ controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent)
task.configuration.windowConfiguration.bounds.set(STABLE_BOUNDS)
// Restore
- controller.toggleDesktopTaskSize(task)
+ controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent)
// Assert bounds set to last bounds before maximize
val wct = getLatestToggleResizeDesktopTaskWct()
assertThat(findBoundsChange(wct, task)).isEqualTo(boundsBeforeMaximize)
+ verify(desktopModeEventLogger, times(1)).logTaskResizingEnded(
+ ResizeTrigger.MAXIMIZE_BUTTON,
+ motionEvent,
+ task,
+ boundsBeforeMaximize.height(),
+ boundsBeforeMaximize.width(),
+ displayController
+ )
}
@Test
@@ -3236,16 +3332,24 @@ class DesktopTasksControllerTest : ShellTestCase() {
}
// Maximize
- controller.toggleDesktopTaskSize(task)
+ controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent)
task.configuration.windowConfiguration.bounds.set(STABLE_BOUNDS.left,
boundsBeforeMaximize.top, STABLE_BOUNDS.right, boundsBeforeMaximize.bottom)
// Restore
- controller.toggleDesktopTaskSize(task)
+ controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent)
// Assert bounds set to last bounds before maximize
val wct = getLatestToggleResizeDesktopTaskWct()
assertThat(findBoundsChange(wct, task)).isEqualTo(boundsBeforeMaximize)
+ verify(desktopModeEventLogger, times(1)).logTaskResizingEnded(
+ ResizeTrigger.MAXIMIZE_BUTTON,
+ motionEvent,
+ task,
+ boundsBeforeMaximize.height(),
+ boundsBeforeMaximize.width(),
+ displayController
+ )
}
@Test
@@ -3256,16 +3360,24 @@ class DesktopTasksControllerTest : ShellTestCase() {
}
// Maximize
- controller.toggleDesktopTaskSize(task)
+ controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent)
task.configuration.windowConfiguration.bounds.set(boundsBeforeMaximize.left,
STABLE_BOUNDS.top, boundsBeforeMaximize.right, STABLE_BOUNDS.bottom)
// Restore
- controller.toggleDesktopTaskSize(task)
+ controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent)
// Assert bounds set to last bounds before maximize
val wct = getLatestToggleResizeDesktopTaskWct()
assertThat(findBoundsChange(wct, task)).isEqualTo(boundsBeforeMaximize)
+ verify(desktopModeEventLogger, times(1)).logTaskResizingEnded(
+ ResizeTrigger.MAXIMIZE_BUTTON,
+ motionEvent,
+ task,
+ boundsBeforeMaximize.height(),
+ boundsBeforeMaximize.width(),
+ displayController
+ )
}
@Test
@@ -3274,14 +3386,22 @@ class DesktopTasksControllerTest : ShellTestCase() {
val task = setUpFreeformTask(DEFAULT_DISPLAY, boundsBeforeMaximize)
// Maximize
- controller.toggleDesktopTaskSize(task)
+ controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent)
task.configuration.windowConfiguration.bounds.set(STABLE_BOUNDS)
// Restore
- controller.toggleDesktopTaskSize(task)
+ controller.toggleDesktopTaskSize(task, ResizeTrigger.MAXIMIZE_BUTTON, motionEvent)
// Assert last bounds before maximize removed after use
assertThat(taskRepository.removeBoundsBeforeMaximize(task.taskId)).isNull()
+ verify(desktopModeEventLogger, times(1)).logTaskResizingEnded(
+ ResizeTrigger.MAXIMIZE_BUTTON,
+ motionEvent,
+ task,
+ boundsBeforeMaximize.height(),
+ boundsBeforeMaximize.width(),
+ displayController
+ )
}
@@ -3680,14 +3800,11 @@ class DesktopTasksControllerTest : ShellTestCase() {
handlerClass: Class<out TransitionHandler>? = null
): WindowContainerTransaction {
val arg = ArgumentCaptor.forClass(WindowContainerTransaction::class.java)
- if (ENABLE_SHELL_TRANSITIONS) {
- if (handlerClass == null) {
- verify(transitions).startTransition(eq(type), arg.capture(), isNull())
- } else {
- verify(transitions).startTransition(eq(type), arg.capture(), isA(handlerClass))
- }
+
+ if (handlerClass == null) {
+ verify(transitions).startTransition(eq(type), arg.capture(), isNull())
} else {
- verify(shellTaskOrganizer).applyTransaction(arg.capture())
+ verify(transitions).startTransition(eq(type), arg.capture(), isA(handlerClass))
}
return arg.value
}
@@ -3697,43 +3814,27 @@ class DesktopTasksControllerTest : ShellTestCase() {
): WindowContainerTransaction {
val arg: ArgumentCaptor<WindowContainerTransaction> =
ArgumentCaptor.forClass(WindowContainerTransaction::class.java)
- if (ENABLE_SHELL_TRANSITIONS) {
- verify(toggleResizeDesktopTaskTransitionHandler, atLeastOnce())
+ verify(toggleResizeDesktopTaskTransitionHandler, atLeastOnce())
.startTransition(capture(arg), eq(currentBounds))
- } else {
- verify(shellTaskOrganizer).applyTransaction(capture(arg))
- }
return arg.value
}
private fun getLatestEnterDesktopWct(): WindowContainerTransaction {
val arg = ArgumentCaptor.forClass(WindowContainerTransaction::class.java)
- if (ENABLE_SHELL_TRANSITIONS) {
- verify(enterDesktopTransitionHandler).moveToDesktop(arg.capture(), any())
- } else {
- verify(shellTaskOrganizer).applyTransaction(arg.capture())
- }
+ verify(enterDesktopTransitionHandler).moveToDesktop(arg.capture(), any())
return arg.value
}
private fun getLatestDragToDesktopWct(): WindowContainerTransaction {
val arg: ArgumentCaptor<WindowContainerTransaction> =
ArgumentCaptor.forClass(WindowContainerTransaction::class.java)
- if (ENABLE_SHELL_TRANSITIONS) {
- verify(dragToDesktopTransitionHandler).finishDragToDesktopTransition(capture(arg))
- } else {
- verify(shellTaskOrganizer).applyTransaction(capture(arg))
- }
+ verify(dragToDesktopTransitionHandler).finishDragToDesktopTransition(capture(arg))
return arg.value
}
private fun getLatestExitDesktopWct(): WindowContainerTransaction {
val arg = ArgumentCaptor.forClass(WindowContainerTransaction::class.java)
- if (ENABLE_SHELL_TRANSITIONS) {
- verify(exitDesktopTransitionHandler).startTransition(any(), arg.capture(), any(), any())
- } else {
- verify(shellTaskOrganizer).applyTransaction(arg.capture())
- }
+ verify(exitDesktopTransitionHandler).startTransition(any(), arg.capture(), any(), any())
return arg.value
}
@@ -3741,27 +3842,15 @@ class DesktopTasksControllerTest : ShellTestCase() {
wct.changes[task.token.asBinder()]?.configuration?.windowConfiguration?.bounds
private fun verifyWCTNotExecuted() {
- if (ENABLE_SHELL_TRANSITIONS) {
- verify(transitions, never()).startTransition(anyInt(), any(), isNull())
- } else {
- verify(shellTaskOrganizer, never()).applyTransaction(any())
- }
+ verify(transitions, never()).startTransition(anyInt(), any(), isNull())
}
private fun verifyExitDesktopWCTNotExecuted() {
- if (ENABLE_SHELL_TRANSITIONS) {
- verify(exitDesktopTransitionHandler, never()).startTransition(any(), any(), any(), any())
- } else {
- verify(shellTaskOrganizer, never()).applyTransaction(any())
- }
+ verify(exitDesktopTransitionHandler, never()).startTransition(any(), any(), any(), any())
}
private fun verifyEnterDesktopWCTNotExecuted() {
- if (ENABLE_SHELL_TRANSITIONS) {
- verify(enterDesktopTransitionHandler, never()).moveToDesktop(any(), any())
- } else {
- verify(shellTaskOrganizer, never()).applyTransaction(any())
- }
+ verify(enterDesktopTransitionHandler, never()).moveToDesktop(any(), any())
}
private fun createTransition(
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
index 0bd3e083671e..79e16fea272d 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DragToDesktopTransitionHandlerTest.kt
@@ -607,7 +607,7 @@ class DragToDesktopTransitionHandlerTest : ShellTestCase() {
)
)
.thenReturn(token)
- handler.startDragToDesktopTransition(task, dragAnimator)
+ handler.startDragToDesktopTransition(task.taskId, dragAnimator)
return token
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepositoryTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepositoryTest.kt
index 9b9703fdf6dc..8495580f42a5 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepositoryTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/persistence/DesktopPersistentRepositoryTest.kt
@@ -115,8 +115,8 @@ class DesktopPersistentRepositoryTest : ShellTestCase() {
freeformTasksInZOrder = freeformTasksInZOrder)
val actualDesktop = datastoreRepository.readDesktop(DEFAULT_USER_ID, DEFAULT_DESKTOP_ID)
- assertThat(actualDesktop.tasksByTaskIdMap).hasSize(2)
- assertThat(actualDesktop.getZOrderedTasks(0)).isEqualTo(2)
+ assertThat(actualDesktop?.tasksByTaskIdMap).hasSize(2)
+ assertThat(actualDesktop?.getZOrderedTasks(0)).isEqualTo(2)
}
}
@@ -138,7 +138,7 @@ class DesktopPersistentRepositoryTest : ShellTestCase() {
freeformTasksInZOrder = freeformTasksInZOrder)
val actualDesktop = datastoreRepository.readDesktop(DEFAULT_USER_ID, DEFAULT_DESKTOP_ID)
- assertThat(actualDesktop.tasksByTaskIdMap[task.taskId]?.desktopTaskState)
+ assertThat(actualDesktop?.tasksByTaskIdMap?.get(task.taskId)?.desktopTaskState)
.isEqualTo(DesktopTaskState.MINIMIZED)
}
}
@@ -161,8 +161,8 @@ class DesktopPersistentRepositoryTest : ShellTestCase() {
freeformTasksInZOrder = freeformTasksInZOrder)
val actualDesktop = datastoreRepository.readDesktop(DEFAULT_USER_ID, DEFAULT_DESKTOP_ID)
- assertThat(actualDesktop.tasksByTaskIdMap).isEmpty()
- assertThat(actualDesktop.zOrderedTasksList).isEmpty()
+ assertThat(actualDesktop?.tasksByTaskIdMap).isEmpty()
+ assertThat(actualDesktop?.zOrderedTasksList).isEmpty()
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index a6e33e5e7c29..a252a9db7095 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -320,7 +320,7 @@ public class StageCoordinatorTests extends ShellTestCase {
assertEquals(mStageCoordinator.mLastActiveStage, STAGE_TYPE_MAIN);
- mStageCoordinator.onFinishedWakingUp();
+ mStageCoordinator.onStartedWakingUp();
verify(mTaskOrganizer).startNewTransition(eq(TRANSIT_SPLIT_DISMISS), notNull());
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
index 189684dc391a..7144a1e038f9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
@@ -114,7 +114,6 @@ public final class StageTaskListenerTests extends ShellTestCase {
public void testRootTaskAppeared() {
assertThat(mStageTaskListener.mRootTaskInfo.taskId).isEqualTo(mRootTask.taskId);
verify(mCallbacks).onRootTaskAppeared();
- verify(mCallbacks, never()).onStageHasChildrenChanged(mStageTaskListener);
verify(mCallbacks, never()).onStageVisibilityChanged(mStageTaskListener);
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
index 175fbd2396e3..1839b8a367fe 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt
@@ -87,6 +87,8 @@ import com.android.wm.shell.common.MultiInstanceHelper
import com.android.wm.shell.common.ShellExecutor
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.desktopmode.DesktopActivityOrientationChangeHandler
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger
import com.android.wm.shell.desktopmode.DesktopRepository
import com.android.wm.shell.desktopmode.DesktopTasksController
import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition
@@ -194,7 +196,11 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
@Mock private lateinit var mockAppHandleEducationController: AppHandleEducationController
@Mock private lateinit var mockFocusTransitionObserver: FocusTransitionObserver
@Mock private lateinit var mockCaptionHandleRepository: WindowDecorCaptionHandleRepository
+ @Mock private lateinit var motionEvent: MotionEvent
+ @Mock lateinit var displayController: DisplayController
+ @Mock lateinit var displayLayout: DisplayLayout
private lateinit var spyContext: TestableContext
+ private lateinit var desktopModeEventLogger: DesktopModeEventLogger
private val transactionFactory = Supplier<SurfaceControl.Transaction> {
SurfaceControl.Transaction()
@@ -224,6 +230,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
shellInit = ShellInit(mockShellExecutor)
windowDecorByTaskIdSpy.clear()
spyContext.addMockSystemService(InputManager::class.java, mockInputManager)
+ desktopModeEventLogger = mock<DesktopModeEventLogger>()
desktopModeWindowDecorViewModel = DesktopModeWindowDecorViewModel(
spyContext,
mockShellExecutor,
@@ -256,7 +263,8 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
mockCaptionHandleRepository,
Optional.of(mockActivityOrientationChangeHandler),
mockTaskPositionerFactory,
- mockFocusTransitionObserver
+ mockFocusTransitionObserver,
+ desktopModeEventLogger
)
desktopModeWindowDecorViewModel.setSplitScreenController(mockSplitScreenController)
whenever(mockDisplayController.getDisplayLayout(any())).thenReturn(mockDisplayLayout)
@@ -299,6 +307,10 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
argumentCaptor<DesktopModeKeyguardChangeListener>()
verify(mockShellController).addKeyguardChangeListener(keyguardChangedCaptor.capture())
desktopModeOnKeyguardChangedListener = keyguardChangedCaptor.firstValue
+ whenever(displayController.getDisplayLayout(anyInt())).thenReturn(displayLayout)
+ whenever(displayLayout.getStableBounds(any())).thenAnswer { i ->
+ (i.arguments.first() as Rect).set(STABLE_BOUNDS)
+ }
}
@After
@@ -612,7 +624,11 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
maxOrRestoreListenerCaptor.value.invoke()
- verify(mockDesktopTasksController).toggleDesktopTaskSize(decor.mTaskInfo)
+ verify(mockDesktopTasksController).toggleDesktopTaskSize(
+ decor.mTaskInfo,
+ ResizeTrigger.MAXIMIZE_MENU,
+ null
+ )
}
@Test
@@ -647,7 +663,9 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
eq(decor.mTaskInfo),
taskSurfaceCaptor.capture(),
eq(currentBounds),
- eq(SnapPosition.LEFT)
+ eq(SnapPosition.LEFT),
+ eq(ResizeTrigger.SNAP_LEFT_MENU),
+ eq(null)
)
assertEquals(taskSurfaceCaptor.firstValue, decor.mTaskSurface)
}
@@ -685,7 +703,9 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
eq(decor.mTaskInfo),
taskSurfaceCaptor.capture(),
eq(currentBounds),
- eq(SnapPosition.LEFT)
+ eq(SnapPosition.LEFT),
+ eq(ResizeTrigger.SNAP_LEFT_MENU),
+ eq(null)
)
assertEquals(decor.mTaskSurface, taskSurfaceCaptor.firstValue)
}
@@ -704,7 +724,9 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
onLeftSnapClickListenerCaptor.value.invoke()
verify(mockDesktopTasksController, never())
- .snapToHalfScreen(eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.LEFT))
+ .snapToHalfScreen(eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.LEFT),
+ eq(ResizeTrigger.MAXIMIZE_BUTTON),
+ eq(null))
verify(mockToast).show()
}
@@ -725,7 +747,9 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
eq(decor.mTaskInfo),
taskSurfaceCaptor.capture(),
eq(currentBounds),
- eq(SnapPosition.RIGHT)
+ eq(SnapPosition.RIGHT),
+ eq(ResizeTrigger.SNAP_RIGHT_MENU),
+ eq(null)
)
assertEquals(decor.mTaskSurface, taskSurfaceCaptor.firstValue)
}
@@ -763,7 +787,9 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
eq(decor.mTaskInfo),
taskSurfaceCaptor.capture(),
eq(currentBounds),
- eq(SnapPosition.RIGHT)
+ eq(SnapPosition.RIGHT),
+ eq(ResizeTrigger.SNAP_RIGHT_MENU),
+ eq(null)
)
assertEquals(decor.mTaskSurface, taskSurfaceCaptor.firstValue)
}
@@ -782,7 +808,9 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
onRightSnapClickListenerCaptor.value.invoke()
verify(mockDesktopTasksController, never())
- .snapToHalfScreen(eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.RIGHT))
+ .snapToHalfScreen(eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.RIGHT),
+ eq(ResizeTrigger.MAXIMIZE_BUTTON),
+ eq(null))
verify(mockToast).show()
}
@@ -1247,7 +1275,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
onClickListenerCaptor.value.onClick(view)
verify(mockDesktopTasksController)
- .toggleDesktopTaskSize(decor.mTaskInfo)
+ .toggleDesktopTaskSize(decor.mTaskInfo, ResizeTrigger.MAXIMIZE_BUTTON, null)
}
private fun createOpenTaskDecoration(
@@ -1337,7 +1365,7 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
whenever(
mockDesktopModeWindowDecorFactory.create(
any(), any(), any(), any(), any(), any(), eq(task), any(), any(), any(), any(),
- any(), any(), any(), any(), any(), any(), any())
+ any(), any(), any(), any(), any(), any(), any(), any())
).thenReturn(decoration)
decoration.mTaskInfo = task
whenever(decoration.user).thenReturn(mockUserHandle)
@@ -1378,5 +1406,6 @@ class DesktopModeWindowDecorViewModelTests : ShellTestCase() {
private const val TAG = "DesktopModeWindowDecorViewModelTests"
private val STABLE_INSETS = Rect(0, 100, 0, 0)
private val INITIAL_BOUNDS = Rect(0, 0, 100, 100)
+ private val STABLE_BOUNDS = Rect(0, 0, 1000, 1000)
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index 320887212f54..0afb6c10b549 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -106,6 +106,7 @@ import com.android.wm.shell.common.MultiInstanceHelper;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.desktopmode.CaptionState;
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger;
import com.android.wm.shell.desktopmode.DesktopRepository;
import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
@@ -210,6 +211,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
private MultiInstanceHelper mMockMultiInstanceHelper;
@Mock
private WindowDecorCaptionHandleRepository mMockCaptionHandleRepository;
+ @Mock
+ private DesktopModeEventLogger mDesktopModeEventLogger;
@Captor
private ArgumentCaptor<Function1<Boolean, Unit>> mOnMaxMenuHoverChangeListener;
@Captor
@@ -1400,7 +1403,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
mMockTransactionSupplier, WindowContainerTransaction::new, SurfaceControl::new,
new WindowManagerWrapper(mMockWindowManager), mMockSurfaceControlViewHostFactory,
maximizeMenuFactory, mMockHandleMenuFactory,
- mMockMultiInstanceHelper, mMockCaptionHandleRepository);
+ mMockMultiInstanceHelper, mMockCaptionHandleRepository, mDesktopModeEventLogger);
windowDecor.setCaptionListeners(mMockTouchEventListener, mMockTouchEventListener,
mMockTouchEventListener, mMockTouchEventListener);
windowDecor.setExclusionRegionListener(mMockExclusionRegionListener);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index fb17ae93030d..cb7fadee9822 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -83,6 +83,7 @@ import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.desktopmode.DesktopModeEventLogger;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.tests.R;
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewContainer;
@@ -138,6 +139,8 @@ public class WindowDecorationTests extends ShellTestCase {
private SurfaceSyncGroup mMockSurfaceSyncGroup;
@Mock
private SurfaceControl mMockTaskSurface;
+ @Mock
+ private DesktopModeEventLogger mDesktopModeEventLogger;
private final List<SurfaceControl.Transaction> mMockSurfaceControlTransactions =
new ArrayList<>();
@@ -1014,7 +1017,7 @@ public class WindowDecorationTests extends ShellTestCase {
new MockObjectSupplier<>(mMockSurfaceControlTransactions,
() -> mock(SurfaceControl.Transaction.class)),
() -> mMockWindowContainerTransaction, () -> mMockTaskSurface,
- mMockSurfaceControlViewHostFactory);
+ mMockSurfaceControlViewHostFactory, mDesktopModeEventLogger);
}
private class MockObjectSupplier<T> implements Supplier<T> {
@@ -1054,11 +1057,12 @@ public class WindowDecorationTests extends ShellTestCase {
Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
Supplier<SurfaceControl> surfaceControlSupplier,
- SurfaceControlViewHostFactory surfaceControlViewHostFactory) {
+ SurfaceControlViewHostFactory surfaceControlViewHostFactory,
+ DesktopModeEventLogger desktopModeEventLogger) {
super(context, userContext, displayController, taskOrganizer, taskInfo, taskSurface,
surfaceControlBuilderSupplier, surfaceControlTransactionSupplier,
windowContainerTransactionSupplier, surfaceControlSupplier,
- surfaceControlViewHostFactory);
+ surfaceControlViewHostFactory, desktopModeEventLogger);
}
@Override
diff --git a/libs/hwui/tests/common/scenes/WindowBlurKawase.cpp b/libs/hwui/tests/common/scenes/WindowBlurKawase.cpp
new file mode 100644
index 000000000000..5905b32e7589
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/WindowBlurKawase.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <SkBitmap.h>
+#include <SkBlendMode.h>
+#include <SkCanvas.h>
+#include <SkPaint.h>
+#include <SkRefCnt.h>
+#include <SkRuntimeEffect.h>
+#include <SkSurface.h>
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
+#include <math.h>
+
+#include "SkImageFilters.h"
+#include "TestSceneBase.h"
+#include "include/gpu/GpuTypes.h" // from Skia
+#include "tests/common/BitmapAllocationTestUtils.h"
+#include "utils/Color.h"
+
+class WindowBlurKawase;
+
+static TestScene::Registrar _WindowBlurKawase(TestScene::Info{
+ "windowblurkawase", "Draws window Kawase blur",
+ TestScene::simpleCreateScene<WindowBlurKawase>});
+
+/**
+ * Simulates the multi-pass Kawase blur algorithm in
+ * frameworks/native/libs/renderengine/skia/filters/WindowBlurKawaseFilter.cpp
+ */
+class WindowBlurKawase : public TestScene {
+private:
+ // Keep in sync with
+ // frameworks/native/libs/renderengine/skia/filters/KawaseBlurFilter.h
+ static constexpr uint32_t kMaxPasses = 4;
+ // Keep in sync with frameworks/native/libs/renderengine/skia/filters/BlurFilter.h
+ static constexpr float kInputScale = 0.25f;
+
+ static constexpr uint32_t kLoopLength = 500;
+ static constexpr uint32_t kMaxBlurRadius = 300;
+ sk_sp<SkRuntimeEffect> mBlurEffect;
+
+ sp<RenderNode> card;
+ sp<RenderNode> contentNode;
+
+public:
+ explicit WindowBlurKawase() {
+ SkString blurString(
+ "uniform shader child;"
+ "uniform float in_blurOffset;"
+
+ "half4 main(float2 xy) {"
+ "half4 c = child.eval(xy);"
+ "c += child.eval(xy + float2(+in_blurOffset, +in_blurOffset));"
+ "c += child.eval(xy + float2(+in_blurOffset, -in_blurOffset));"
+ "c += child.eval(xy + float2(-in_blurOffset, -in_blurOffset));"
+ "c += child.eval(xy + float2(-in_blurOffset, +in_blurOffset));"
+ "return half4(c.rgb * 0.2, 1.0);"
+ "}");
+
+ auto [blurEffect, error] = SkRuntimeEffect::MakeForShader(blurString);
+ if (!blurEffect) {
+ LOG_ALWAYS_FATAL("RuntimeShader error: %s", error.c_str());
+ }
+ mBlurEffect = std::move(blurEffect);
+ }
+
+ void createContent(int width, int height, Canvas& canvas) override {
+ contentNode = TestUtils::createNode(
+ 0, 0, width, height, [width, height](RenderProperties& props, Canvas& canvas) {
+ canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
+ Paint paint;
+ paint.setColor(Color::Red_500);
+ canvas.drawRect(0, 0, width / 2, height / 2, paint);
+ paint.setColor(Color::Blue_500);
+ canvas.drawRect(width / 2, height / 2, width, height, paint);
+ });
+
+ card = TestUtils::createNode(
+ 0, 0, width, height,
+ [this](RenderProperties& props, Canvas& canvas) { blurFrame(canvas, 0); });
+ canvas.drawRenderNode(card.get());
+ }
+
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % kLoopLength;
+ float blurRadius =
+ (sin((float)curFrame / kLoopLength * M_PI * 2) + 1) * 0.5 * kMaxBlurRadius;
+ TestUtils::recordNode(
+ *card, [this, blurRadius](Canvas& canvas) { blurFrame(canvas, blurRadius); });
+ }
+
+ void blurFrame(Canvas& canvas, float blurRadius) {
+ if (blurRadius == 0) {
+ canvas.drawRenderNode(contentNode.get());
+ return;
+ }
+
+ int width = canvas.width();
+ int height = canvas.height();
+ float tmpRadius = (float)blurRadius / 2.0f;
+ uint32_t numberOfPasses = std::min(kMaxPasses, (uint32_t)ceil(tmpRadius));
+ float radiusByPasses = tmpRadius / (float)numberOfPasses;
+
+ SkRuntimeShaderBuilder blurBuilder(mBlurEffect);
+
+ sp<RenderNode> node = contentNode;
+ for (int i = 0; i < numberOfPasses; i++) {
+ blurBuilder.uniform("in_blurOffset") = radiusByPasses * kInputScale * (i + 1);
+ sk_sp<SkImageFilter> blurFilter =
+ SkImageFilters::RuntimeShader(blurBuilder, radiusByPasses, "child", nullptr);
+ // Also downsample the image in the first pass.
+ float canvasScale = i == 0 ? kInputScale : 1;
+
+ // Apply the blur effect as an image filter.
+ node = TestUtils::createNode(
+ 0, 0, width * kInputScale, height * kInputScale,
+ [node, blurFilter, canvasScale](RenderProperties& props, Canvas& canvas) {
+ props.mutateLayerProperties().setImageFilter(blurFilter.get());
+ canvas.scale(canvasScale, canvasScale);
+ canvas.drawRenderNode(node.get());
+ });
+ }
+
+ // Finally upsample the image to its original size.
+ canvas.scale(1 / kInputScale, 1 / kInputScale);
+ canvas.drawRenderNode(node.get());
+ }
+};
diff --git a/libs/hwui/tests/common/scenes/WindowBlurSkia.cpp b/libs/hwui/tests/common/scenes/WindowBlurSkia.cpp
new file mode 100644
index 000000000000..36e6d8fbb6ed
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/WindowBlurSkia.cpp
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <SkBitmap.h>
+#include <SkBlendMode.h>
+#include <SkCanvas.h>
+#include <SkPaint.h>
+#include <SkRefCnt.h>
+#include <SkRuntimeEffect.h>
+#include <SkSurface.h>
+#include <include/gpu/ganesh/SkSurfaceGanesh.h>
+#include <math.h>
+
+#include "SkImageFilters.h"
+#include "TestSceneBase.h"
+#include "include/gpu/GpuTypes.h" // from Skia
+#include "tests/common/BitmapAllocationTestUtils.h"
+#include "utils/Color.h"
+
+class WindowBlurSkia;
+
+static TestScene::Registrar _WindowBlurSkia(TestScene::Info{
+ "windowblurskia", "Draws window Skia blur", TestScene::simpleCreateScene<WindowBlurSkia>});
+
+/**
+ * Simulates the Skia window blur in
+ * frameworks/native/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
+ */
+class WindowBlurSkia : public TestScene {
+private:
+ // Keep in sync with frameworks/native/libs/renderengine/skia/filters/BlurFilter.h
+ static constexpr float kInputScale = 0.25f;
+
+ static constexpr uint32_t kLoopLength = 500;
+ static constexpr uint32_t kMaxBlurRadius = 300;
+
+ sp<RenderNode> card;
+ sp<RenderNode> contentNode;
+
+public:
+ void createContent(int width, int height, Canvas& canvas) override {
+ contentNode = TestUtils::createNode(
+ 0, 0, width, height, [width, height](RenderProperties& props, Canvas& canvas) {
+ canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
+ Paint paint;
+ paint.setColor(Color::Red_500);
+ canvas.drawRect(0, 0, width / 2, height / 2, paint);
+ paint.setColor(Color::Blue_500);
+ canvas.drawRect(width / 2, height / 2, width, height, paint);
+ });
+
+ card = TestUtils::createNode(
+ 0, 0, width, height,
+ [this](RenderProperties& props, Canvas& canvas) { blurFrame(canvas, 0); });
+ canvas.drawRenderNode(card.get());
+ }
+
+ void doFrame(int frameNr) override {
+ int curFrame = frameNr % kLoopLength;
+ float blurRadius =
+ (sin((float)curFrame / kLoopLength * M_PI * 2) + 1) * 0.5 * kMaxBlurRadius;
+ TestUtils::recordNode(
+ *card, [this, blurRadius](Canvas& canvas) { blurFrame(canvas, blurRadius); });
+ }
+
+ void blurFrame(Canvas& canvas, float blurRadius) {
+ if (blurRadius == 0) {
+ canvas.drawRenderNode(contentNode.get());
+ return;
+ }
+
+ int width = canvas.width();
+ int height = canvas.height();
+
+ // Downsample and blur the image with the Skia blur filter.
+ sp<RenderNode> node = contentNode;
+ sk_sp<SkImageFilter> blurFilter =
+ SkImageFilters::Blur(blurRadius, blurRadius, SkTileMode::kClamp, nullptr, nullptr);
+ node = TestUtils::createNode(
+ 0, 0, width * kInputScale, height * kInputScale,
+ [node, blurFilter](RenderProperties& props, Canvas& canvas) {
+ props.mutateLayerProperties().setImageFilter(blurFilter.get());
+ canvas.scale(kInputScale, kInputScale);
+ canvas.drawRenderNode(node.get());
+ });
+
+ // Upsample the image to its original size.
+ canvas.scale(1 / kInputScale, 1 / kInputScale);
+ canvas.drawRenderNode(node.get());
+ }
+};
diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp
index 23097f634464..c7a7ed2a885e 100644
--- a/libs/hwui/utils/Color.cpp
+++ b/libs/hwui/utils/Color.cpp
@@ -17,7 +17,6 @@
#include "Color.h"
#include <Properties.h>
-#include <aidl/android/hardware/graphics/common/Dataspace.h>
#include <android/hardware_buffer.h>
#include <android/native_window.h>
#include <ui/ColorSpace.h>
@@ -222,8 +221,7 @@ android_dataspace ColorSpaceToADataSpace(SkColorSpace* colorSpace, SkColorType c
if (nearlyEqual(fn, SkNamedTransferFn::kRec2020)) {
return HAL_DATASPACE_BT2020;
} else if (nearlyEqual(fn, SkNamedTransferFn::kSRGB)) {
- return static_cast<android_dataspace>(
- ::aidl::android::hardware::graphics::common::Dataspace::DISPLAY_BT2020);
+ return static_cast<android_dataspace>(HAL_DATASPACE_DISPLAY_BT2020);
}
}
diff --git a/media/java/android/media/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
index afa0a3271906..65e83b9bf204 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerDetector.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
@@ -323,10 +323,15 @@ public final class SoundTriggerDetector {
int status;
try {
- status = mSoundTriggerSession.startRecognition(mSoundModel,
- mRecognitionCallback, new RecognitionConfig(captureTriggerAudio,
- allowMultipleTriggers, null, null, audioCapabilities),
- runInBatterySaver);
+ status = mSoundTriggerSession.startRecognition(
+ mSoundModel,
+ mRecognitionCallback,
+ new RecognitionConfig.Builder()
+ .setCaptureRequested(captureTriggerAudio)
+ .setAllowMultipleTriggers(allowMultipleTriggers)
+ .setAudioCapabilities(audioCapabilities)
+ .build(),
+ runInBatterySaver);
} catch (RemoteException e) {
return false;
}
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml
index 2e3ee32e2efb..e3f8fbb88a65 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout-v31/settingslib_main_switch_bar.xml
@@ -20,6 +20,8 @@
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?android:attr/listPreferredItemHeight"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingTop="@dimen/settingslib_switchbar_margin"
android:paddingBottom="@dimen/settingslib_switchbar_margin"
android:orientation="vertical">
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout-v33/settingslib_main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout-v33/settingslib_main_switch_bar.xml
index 3e0e18488f36..255b2c92e709 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/layout-v33/settingslib_main_switch_bar.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout-v33/settingslib_main_switch_bar.xml
@@ -20,6 +20,8 @@
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?android:attr/listPreferredItemHeight"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingTop="@dimen/settingslib_switchbar_margin"
android:paddingBottom="@dimen/settingslib_switchbar_margin"
android:orientation="vertical">
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout-v35/settingslib_expressive_main_switch_layout.xml b/packages/SettingsLib/MainSwitchPreference/res/layout-v35/settingslib_expressive_main_switch_layout.xml
new file mode 100644
index 000000000000..94c6924a02f2
--- /dev/null
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout-v35/settingslib_expressive_main_switch_layout.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2024 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.
+ -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:importantForAccessibility="no">
+
+ <com.android.settingslib.widget.MainSwitchBar
+ android:id="@+id/settingslib_main_switch_bar"
+ android:visibility="gone"
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent" />
+
+</FrameLayout>
+
+
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout/settingslib_main_switch_bar.xml b/packages/SettingsLib/MainSwitchPreference/res/layout/settingslib_main_switch_bar.xml
index 7c0eaeaca3de..bf34db93298b 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/layout/settingslib_main_switch_bar.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout/settingslib_main_switch_bar.xml
@@ -18,7 +18,11 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
- android:layout_width="match_parent">
+ android:layout_width="match_parent"
+ android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingRight="?android:attr/listPreferredItemPaddingRight"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
<TextView
android:id="@+id/switch_text"
diff --git a/packages/SettingsLib/MainSwitchPreference/res/layout/settingslib_main_switch_layout.xml b/packages/SettingsLib/MainSwitchPreference/res/layout/settingslib_main_switch_layout.xml
index fa908a4ed6c8..bef6e352d854 100644
--- a/packages/SettingsLib/MainSwitchPreference/res/layout/settingslib_main_switch_layout.xml
+++ b/packages/SettingsLib/MainSwitchPreference/res/layout/settingslib_main_switch_layout.xml
@@ -18,10 +18,6 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingRight="?android:attr/listPreferredItemPaddingRight"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:importantForAccessibility="no">
<com.android.settingslib.widget.MainSwitchBar
diff --git a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java
index 3394874797e3..83858d9c9c54 100644
--- a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java
+++ b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java
@@ -81,7 +81,11 @@ public class MainSwitchPreference extends TwoStatePreference
}
private void init(Context context, AttributeSet attrs) {
- setLayoutResource(R.layout.settingslib_main_switch_layout);
+ boolean isExpressive = SettingsThemeHelper.isExpressiveTheme(context);
+ int resId = isExpressive
+ ? R.layout.settingslib_expressive_main_switch_layout
+ : R.layout.settingslib_main_switch_layout;
+ setLayoutResource(resId);
mSwitchChangeListeners.add(this);
if (attrs != null) {
final TypedArray a = context.obtainStyledAttributes(attrs,
diff --git a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceTypes.kt b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceTypes.kt
index ad996c7c8f86..b64f5dc49b4b 100644
--- a/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceTypes.kt
+++ b/packages/SettingsLib/Metadata/src/com/android/settingslib/metadata/PreferenceTypes.kt
@@ -38,3 +38,11 @@ constructor(
@StringRes override val title: Int = 0,
@StringRes override val summary: Int = 0,
) : TwoStatePreference
+
+/** A preference that provides a two-state toggleable option that can be used as a main switch. */
+open class MainSwitchPreference
+@JvmOverloads
+constructor(
+ override val key: String,
+ @StringRes override val title: Int = 0,
+) : TwoStatePreference \ No newline at end of file
diff --git a/packages/SettingsLib/Preference/Android.bp b/packages/SettingsLib/Preference/Android.bp
index bff95ceb137e..fb06be908733 100644
--- a/packages/SettingsLib/Preference/Android.bp
+++ b/packages/SettingsLib/Preference/Android.bp
@@ -32,6 +32,7 @@ android_library {
static_libs: [
"SettingsLibDataStore",
"SettingsLibMetadata",
+ "SettingsLibMainSwitchPreference",
"androidx.annotation_annotation",
"androidx.preference_preference",
"guava",
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindingFactory.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindingFactory.kt
index 4c2e1ba683f6..43f2cb6e2134 100644
--- a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindingFactory.kt
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindingFactory.kt
@@ -16,6 +16,7 @@
package com.android.settingslib.preference
+import com.android.settingslib.metadata.MainSwitchPreference
import com.android.settingslib.metadata.PreferenceGroup
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.SwitchPreference
@@ -36,6 +37,7 @@ object DefaultPreferenceBindingFactory : PreferenceBindingFactory {
is SwitchPreference -> SwitchPreferenceBinding.INSTANCE
is PreferenceGroup -> PreferenceGroupBinding.INSTANCE
is PreferenceScreenCreator -> PreferenceScreenBinding.INSTANCE
+ is MainSwitchPreference -> MainSwitchPreferenceBinding.INSTANCE
else -> DefaultPreferenceBinding
}
}
diff --git a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt
index ede970e42e72..d40a6f6c55f4 100644
--- a/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt
+++ b/packages/SettingsLib/Preference/src/com/android/settingslib/preference/PreferenceBindings.kt
@@ -21,11 +21,13 @@ import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat
+import androidx.preference.TwoStatePreference
import com.android.settingslib.metadata.EXTRA_BINDING_SCREEN_KEY
import com.android.settingslib.metadata.PersistentPreference
import com.android.settingslib.metadata.PreferenceMetadata
import com.android.settingslib.metadata.PreferenceScreenMetadata
import com.android.settingslib.metadata.PreferenceTitleProvider
+import com.android.settingslib.widget.MainSwitchPreference
/** Binding of preference group associated with [PreferenceCategory]. */
interface PreferenceScreenBinding : PreferenceBinding {
@@ -64,23 +66,37 @@ interface PreferenceGroupBinding : PreferenceBinding {
}
}
-/** A boolean value type preference associated with [SwitchPreferenceCompat]. */
-interface SwitchPreferenceBinding : PreferenceBinding {
-
- override fun createWidget(context: Context): Preference = SwitchPreferenceCompat(context)
+/** A boolean value type preference associated with the abstract [TwoStatePreference]. */
+interface TwoStatePreferenceBinding : PreferenceBinding {
override fun bind(preference: Preference, metadata: PreferenceMetadata) {
super.bind(preference, metadata)
(metadata as? PersistentPreference<*>)
?.storage(preference.context)
?.getValue(metadata.key, Boolean::class.javaObjectType)
- ?.let { (preference as SwitchPreferenceCompat).isChecked = it }
+ ?.let { (preference as TwoStatePreference).isChecked = it }
}
+}
+
+/** A boolean value type preference associated with [SwitchPreferenceCompat]. */
+interface SwitchPreferenceBinding : TwoStatePreferenceBinding {
+
+ override fun createWidget(context: Context): Preference = SwitchPreferenceCompat(context)
companion object {
@JvmStatic val INSTANCE = object : SwitchPreferenceBinding {}
}
}
+/** A boolean value type preference associated with [MainSwitchPreference]. */
+interface MainSwitchPreferenceBinding : TwoStatePreferenceBinding {
+
+ override fun createWidget(context: Context): Preference = MainSwitchPreference(context)
+
+ companion object {
+ @JvmStatic val INSTANCE = object : MainSwitchPreferenceBinding {}
+ }
+}
+
/** Default [PreferenceBinding] for [Preference]. */
object DefaultPreferenceBinding : PreferenceBinding
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java
index 4f315a2a2486..63661f698f4e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InputRouteManager.java
@@ -74,7 +74,23 @@ public final class InputRouteManager {
new AudioDeviceCallback() {
@Override
public void onAudioDevicesAdded(@NonNull AudioDeviceInfo[] addedDevices) {
- applyDefaultSelectedTypeToAllPresets();
+ // Activate the last hot plugged valid input device, to match the output device
+ // behavior.
+ @AudioDeviceType int deviceTypeToActivate = mSelectedInputDeviceType;
+ for (AudioDeviceInfo info : addedDevices) {
+ if (InputMediaDevice.isSupportedInputDevice(info.getType())) {
+ deviceTypeToActivate = info.getType();
+ }
+ }
+
+ // Only activate if we find a different valid input device. e.g. if none of the
+ // addedDevices is supported input device, we don't need to activate anything.
+ if (mSelectedInputDeviceType != deviceTypeToActivate) {
+ mSelectedInputDeviceType = deviceTypeToActivate;
+ AudioDeviceAttributes deviceAttributes =
+ createInputDeviceAttributes(mSelectedInputDeviceType);
+ setPreferredDeviceForAllPresets(deviceAttributes);
+ }
}
@Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioRepository.kt b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioRepository.kt
index d3c345deebad..f5e6caf0d9b9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioRepository.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/volume/data/repository/AudioRepository.kt
@@ -25,6 +25,7 @@ import android.media.AudioManager.OnCommunicationDeviceChangedListener
import android.media.IVolumeController
import android.provider.Settings
import android.util.Log
+import android.view.KeyEvent
import androidx.concurrent.futures.DirectExecutor
import com.android.internal.util.ConcurrentUtils
import com.android.settingslib.volume.data.model.VolumeControllerEvent
@@ -104,6 +105,8 @@ interface AudioRepository {
@AudioDeviceCategory suspend fun getBluetoothAudioDeviceCategory(bluetoothAddress: String): Int
suspend fun notifyVolumeControllerVisible(isVisible: Boolean)
+
+ fun dispatchMediaKeyEvent(event: KeyEvent)
}
class AudioRepositoryImpl(
@@ -265,6 +268,10 @@ class AudioRepositoryImpl(
}
}
+ override fun dispatchMediaKeyEvent(event: KeyEvent) {
+ audioManager.dispatchMediaKeyEvent(event)
+ }
+
private fun getMinVolume(stream: AudioStream): Int =
try {
audioManager.getStreamMinVolume(stream.value)
@@ -320,15 +327,9 @@ private class ProducingVolumeController : IVolumeController.Stub() {
mutableEvents.tryEmit(VolumeControllerEvent.SetA11yMode(mode))
}
- override fun displayCsdWarning(
- csdWarning: Int,
- displayDurationMs: Int,
- ) {
+ override fun displayCsdWarning(csdWarning: Int, displayDurationMs: Int) {
mutableEvents.tryEmit(
- VolumeControllerEvent.DisplayCsdWarning(
- csdWarning,
- displayDurationMs,
- )
+ VolumeControllerEvent.DisplayCsdWarning(csdWarning, displayDurationMs)
)
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java
index 782cee23fb42..d808a25ebc04 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InputRouteManagerTest.java
@@ -24,6 +24,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -138,6 +139,18 @@ public class InputRouteManagerTest {
/* address= */ "");
}
+ private AudioDeviceAttributes getUsbHeadsetDeviceAttributes() {
+ return new AudioDeviceAttributes(
+ AudioDeviceAttributes.ROLE_INPUT,
+ AudioDeviceInfo.TYPE_USB_HEADSET,
+ /* address= */ "");
+ }
+
+ private AudioDeviceAttributes getHdmiDeviceAttributes() {
+ return new AudioDeviceAttributes(
+ AudioDeviceAttributes.ROLE_INPUT, AudioDeviceInfo.TYPE_HDMI, /* address= */ "");
+ }
+
private void onPreferredDevicesForCapturePresetChanged(InputRouteManager inputRouteManager) {
final List<AudioDeviceAttributes> audioDeviceAttributesList =
new ArrayList<AudioDeviceAttributes>();
@@ -303,21 +316,47 @@ public class InputRouteManagerTest {
}
@Test
- public void onAudioDevicesAdded_shouldApplyDefaultSelectedDeviceToAllPresets() {
+ public void onAudioDevicesAdded_shouldActivateAddedDevice() {
final AudioManager audioManager = mock(AudioManager.class);
- AudioDeviceAttributes wiredHeadsetDeviceAttributes = getWiredHeadsetDeviceAttributes();
- when(audioManager.getDevicesForAttributes(INPUT_ATTRIBUTES))
- .thenReturn(Collections.singletonList(wiredHeadsetDeviceAttributes));
-
InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager);
AudioDeviceInfo[] devices = {mockWiredHeadsetInfo()};
inputRouteManager.mAudioDeviceCallback.onAudioDevicesAdded(devices);
- // Called twice, one after initiation, the other after onAudioDevicesAdded call.
- verify(audioManager, atLeast(2)).getDevicesForAttributes(INPUT_ATTRIBUTES);
+ // The only added wired headset will be activated.
for (@MediaRecorder.Source int preset : PRESETS) {
- verify(audioManager, atLeast(2))
- .setPreferredDeviceForCapturePreset(preset, wiredHeadsetDeviceAttributes);
+ verify(audioManager, atLeast(1))
+ .setPreferredDeviceForCapturePreset(preset, getWiredHeadsetDeviceAttributes());
+ }
+ }
+
+ @Test
+ public void onAudioDevicesAdded_shouldActivateLastAddedDevice() {
+ final AudioManager audioManager = mock(AudioManager.class);
+ InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager);
+ AudioDeviceInfo[] devices = {mockWiredHeadsetInfo(), mockUsbHeadsetInfo()};
+ inputRouteManager.mAudioDeviceCallback.onAudioDevicesAdded(devices);
+
+ // When adding multiple valid input devices, the last added device (usb headset in this
+ // case) will be activated.
+ for (@MediaRecorder.Source int preset : PRESETS) {
+ verify(audioManager, never())
+ .setPreferredDeviceForCapturePreset(preset, getWiredHeadsetDeviceAttributes());
+ verify(audioManager, atLeast(1))
+ .setPreferredDeviceForCapturePreset(preset, getUsbHeadsetDeviceAttributes());
+ }
+ }
+
+ @Test
+ public void onAudioDevicesAdded_doNotActivateInvalidAddedDevice() {
+ final AudioManager audioManager = mock(AudioManager.class);
+ InputRouteManager inputRouteManager = new InputRouteManager(mContext, audioManager);
+ AudioDeviceInfo[] devices = {mockHdmiInfo()};
+ inputRouteManager.mAudioDeviceCallback.onAudioDevicesAdded(devices);
+
+ // Do not activate since HDMI is not a valid input device.
+ for (@MediaRecorder.Source int preset : PRESETS) {
+ verify(audioManager, never())
+ .setPreferredDeviceForCapturePreset(preset, getHdmiDeviceAttributes());
}
}
diff --git a/packages/SettingsProvider/Android.bp b/packages/SettingsProvider/Android.bp
index 65b22758946d..00ae05ceabd4 100644
--- a/packages/SettingsProvider/Android.bp
+++ b/packages/SettingsProvider/Android.bp
@@ -76,6 +76,7 @@ android_test {
"truth",
"Nene",
"Harrier",
+ "bedstead-enterprise",
],
libs: [
"android.test.base.stubs.system",
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java
index e86e72712b48..9cce43160b52 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsProviderMultiUsersTest.java
@@ -20,6 +20,9 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_ENABLED;
import static android.provider.Settings.Secure.SYNC_PARENT_SOUNDS;
import static android.provider.Settings.System.RINGTONE;
+import static com.android.bedstead.enterprise.EnterpriseDeviceStateExtensionsKt.workProfile;
+import static com.android.bedstead.multiuser.MultiUserDeviceStateExtensionsKt.secondaryUser;
+
import static com.google.common.truth.Truth.assertThat;
import android.content.pm.PackageManager;
@@ -82,7 +85,7 @@ public class SettingsProviderMultiUsersTest {
@RequireFeature(PackageManager.FEATURE_MANAGED_USERS)
@EnsureHasWorkProfile
public void testSettings_workProfile() throws Exception {
- UserReference profile = sDeviceState.workProfile();
+ UserReference profile = workProfile(sDeviceState);
// Settings.Global settings are shared between different users
assertSettingsShared(SPACE_GLOBAL, mPrimaryUser.id(), profile.id());
@@ -96,7 +99,7 @@ public class SettingsProviderMultiUsersTest {
@RequireRunOnInitialUser
@EnsureHasSecondaryUser
public void testSettings_secondaryUser() throws Exception {
- UserReference secondaryUser = sDeviceState.secondaryUser();
+ UserReference secondaryUser = secondaryUser(sDeviceState);
// Settings.Global settings are shared between different users
assertSettingsShared(SPACE_GLOBAL, mPrimaryUser.id(), secondaryUser.id());
@@ -223,7 +226,7 @@ public class SettingsProviderMultiUsersTest {
@RequireRunOnInitialUser
@EnsureHasSecondaryUser
public void testSettings_stopAndRestartSecondaryUser() throws Exception {
- UserReference secondaryUser = sDeviceState.secondaryUser();
+ UserReference secondaryUser = secondaryUser(sDeviceState);
assertSettingsDifferent(SPACE_SECURE, mPrimaryUser.id(), secondaryUser.id());
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 3c560fdcadb6..5f90b39808f8 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -276,8 +276,6 @@ filegroup {
filegroup {
name: "SystemUI-tests-broken-robofiles-compile",
srcs: [
- "tests/src/**/*DeviceOnlyTest.java",
- "tests/src/**/*DeviceOnlyTest.kt",
"tests/src/**/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt",
"tests/src/**/systemui/accessibility/data/repository/AccessibilityQsShortcutsRepositoryImplForDeviceTest.kt",
"tests/src/**/systemui/biometrics/AuthDialogPanelInteractionDetectorTest.kt",
@@ -293,7 +291,6 @@ filegroup {
"tests/src/**/systemui/keyguard/ResourceTrimmerTest.kt",
"tests/src/**/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt",
"tests/src/**/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt",
- "tests/src/**/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt",
"tests/src/**/systemui/media/controls/ui/controller/MediaHierarchyManagerTest.kt",
"tests/src/**/systemui/mediaprojection/taskswitcher/MediaProjectionTaskSwitcherCoreStartableTest.kt",
"tests/src/**/systemui/media/taptotransfer/receiver/FakeMediaTttChipControllerReceiver.kt",
@@ -303,14 +300,12 @@ filegroup {
"tests/src/**/systemui/screenshot/ActionIntentCreatorTest.kt",
"tests/src/**/systemui/screenshot/DefaultScreenshotActionsProviderTest.kt",
"tests/src/**/systemui/screenshot/TakeScreenshotServiceTest.kt",
- "tests/src/**/systemui/statusbar/commandline/CommandRegistryTest.kt",
"tests/src/**/systemui/statusbar/notification/collection/TargetSdkResolverTest.kt",
"tests/src/**/systemui/statusbar/notification/icon/IconManagerTest.kt",
"tests/src/**/systemui/statusbar/notification/row/BigPictureIconManagerTest.kt",
"tests/src/**/systemui/statusbar/notification/row/NotificationSettingsControllerTest.kt",
"tests/src/**/systemui/statusbar/notification/stack/ui/view/NotificationStatsLoggerTest.kt",
"tests/src/**/systemui/statusbar/pipeline/satellite/data/prod/DeviceBasedSatelliteRepositoryImplTest.kt",
- "tests/src/**/systemui/statusbar/policy/BatteryStateNotifierTest.kt",
"tests/src/**/systemui/statusbar/policy/FlashlightControllerImplTest.kt",
"tests/src/**/systemui/statusbar/policy/SensitiveNotificationProtectionControllerFlagDisabledTest.kt",
"tests/src/**/systemui/stylus/StylusUsiPowerStartableTest.kt",
@@ -449,27 +444,20 @@ filegroup {
"tests/src/**/systemui/media/dialog/MediaSwitchingControllerTest.java",
"tests/src/**/systemui/navigationbar/views/NavigationBarTest.java",
"tests/src/**/systemui/power/PowerNotificationWarningsTest.java",
- "tests/src/**/systemui/power/PowerUITest.java",
"tests/src/**/systemui/qs/QSFooterViewControllerTest.java",
"tests/src/**/systemui/qs/QSImplTest.java",
- "tests/src/**/systemui/qs/QSSecurityFooterTest.java",
- "tests/src/**/systemui/qs/tileimpl/QSTileImplTest.java",
"tests/src/**/systemui/qs/tiles/QuickAccessWalletTileTest.java",
"tests/src/**/systemui/shade/carrier/ShadeCarrierGroupControllerTest.java",
- "tests/src/**/systemui/shared/plugins/PluginActionManagerTest.java",
- "tests/src/**/systemui/statusbar/CommandQueueTest.java",
- "tests/src/**/systemui/statusbar/connectivity/CallbackHandlerTest.java",
"tests/src/**/systemui/statusbar/connectivity/NetworkControllerBaseTest.java",
+ "tests/src/**/systemui/statusbar/connectivity/NetworkControllerDataTest.java",
+ "tests/src/**/systemui/statusbar/connectivity/NetworkControllerEthernetTest.java",
+ "tests/src/**/systemui/statusbar/connectivity/NetworkControllerSignalTest.java",
+ "tests/src/**/systemui/statusbar/connectivity/NetworkControllerWifiTest.java",
"tests/src/**/systemui/statusbar/KeyguardIndicationControllerTest.java",
"tests/src/**/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java",
"tests/src/**/systemui/statusbar/phone/ScrimControllerTest.java",
"tests/src/**/systemui/statusbar/policy/RotationLockControllerImplTest.java",
- "tests/src/**/systemui/statusbar/policy/SecurityControllerTest.java",
"tests/src/**/systemui/toast/ToastUITest.java",
- "tests/src/**/systemui/statusbar/connectivity/NetworkControllerDataTest.java",
- "tests/src/**/systemui/statusbar/connectivity/NetworkControllerEthernetTest.java",
- "tests/src/**/systemui/statusbar/connectivity/NetworkControllerSignalTest.java",
- "tests/src/**/systemui/statusbar/connectivity/NetworkControllerWifiTest.java",
],
visibility: ["//visibility:private"],
}
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 426b24dfe070..1c29db128a8c 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1148,6 +1148,13 @@ flag {
}
flag {
+ name: "media_controls_button_media3_placement"
+ namespace: "systemui"
+ description: "Use media3 API for action button placement preferences"
+ bug: "360196209"
+}
+
+flag {
name: "media_controls_drawables_reuse"
namespace: "systemui"
description: "Re-use created media drawables for media controls"
@@ -1552,8 +1559,28 @@ flag {
}
flag {
+ name: "hide_ringer_button_in_single_volume_mode"
+ namespace: "systemui"
+ description: "When the device is in single volume mode, hide the ringer button because it doesn't work"
+ bug: "374870615"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "qs_tile_detailed_view"
namespace: "systemui"
description: "Enables the tile detailed view UI."
bug: "374173773"
}
+
+flag {
+ name: "ensure_enr_views_visibility"
+ namespace: "systemui"
+ description: "Ensures public and private visibilities"
+ bug: "361552380"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index 8b0daf6e75b2..476cced6a03d 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -159,6 +159,7 @@ import androidx.compose.ui.unit.times
import androidx.compose.ui.util.fastAll
import androidx.compose.ui.viewinterop.AndroidView
import androidx.compose.ui.viewinterop.NoOpUpdate
+import androidx.compose.ui.zIndex
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.window.layout.WindowMetricsCalculator
import com.android.compose.animation.Easings.Emphasized
@@ -796,6 +797,7 @@ private fun BoxScope.CommunalHubLazyGrid(
}
if (viewModel.isEditMode && dragDropState != null) {
+ val isItemDragging = dragDropState.draggingItemKey == item.key
val outlineAlpha by
animateFloatAsState(
targetValue = if (selected) 1f else 0f,
@@ -812,13 +814,13 @@ private fun BoxScope.CommunalHubLazyGrid(
enabled = selected,
alpha = { outlineAlpha },
modifier =
- Modifier.requiredSize(dpSize).thenIf(
- dragDropState.draggingItemKey != item.key
- ) {
- Modifier.animateItem(
- placementSpec = spring(stiffness = Spring.StiffnessMediumLow)
- )
- },
+ Modifier.requiredSize(dpSize)
+ .thenIf(!isItemDragging) {
+ Modifier.animateItem(
+ placementSpec = spring(stiffness = Spring.StiffnessMediumLow)
+ )
+ }
+ .thenIf(isItemDragging) { Modifier.zIndex(1f) },
onResize = { resizeInfo -> contentListState.resize(index, resizeInfo) },
minHeightPx = widgetSizeInfo.minHeightPx,
maxHeightPx = widgetSizeInfo.maxHeightPx,
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
index 9f99c372e2a8..8469007eddb6 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/DraggableHandler.kt
@@ -710,6 +710,9 @@ internal class NestedScrollHandlerImpl(
canStart
},
+ // We need to maintain scroll priority even if the scene transition can no longer
+ // consume the scroll gesture to allow us to return to the previous scene.
+ canStopOnScroll = { _, _ -> false },
canStopOnPreFling = { true },
onStart = { offsetAvailable ->
val pointersInfo = pointersInfo()
@@ -740,7 +743,12 @@ internal class NestedScrollHandlerImpl(
.onStop(velocity = velocityAvailable, canChangeContent = canChangeScene)
.invoke()
} finally {
- dragController = null
+ // onStop might still be running when a new gesture begins.
+ // To prevent conflicts, we should only remove the drag controller if it's the
+ // same one that was active initially.
+ if (dragController == controller) {
+ dragController = null
+ }
}
},
onCancel = {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
index 6a5b7e103dbb..c790ff03aef1 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
@@ -241,6 +241,10 @@ private fun placeholderContentSize(
return targetValueInScene
}
+ fun TransitionState.Transition.otherContent(): ContentKey {
+ return if (fromContent == content) toContent else fromContent
+ }
+
// If the element content was already composed in the other overlay/scene, we use that
// target size assuming it doesn't change between scenes.
// TODO(b/317026105): Provide a way to give a hint size/content for cases where this is
@@ -249,8 +253,10 @@ private fun placeholderContentSize(
when (val state = movableElementState(elementKey, transitionStates)) {
null -> return IntSize.Zero
is TransitionState.Idle -> movableElementContentWhenIdle(layoutImpl, elementKey, state)
- is TransitionState.Transition ->
- if (state.fromContent == content) state.toContent else state.fromContent
+ is TransitionState.Transition.ReplaceOverlay -> {
+ state.otherContent().takeIf { it in element.stateByContent } ?: state.currentScene
+ }
+ is TransitionState.Transition -> state.otherContent()
}
val targetValueInOtherContent = element.stateByContent[otherContent]?.targetSize
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
index 3bd59df16f12..7d29a68e3a8d 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/content/state/TransitionState.kt
@@ -311,6 +311,22 @@ sealed interface TransitionState {
return fromContent == content || toContent == content
}
+ /**
+ * Return [progress] if [content] is equal to [toContent], `1f - progress` if [content] is
+ * equal to [fromContent], and throw otherwise.
+ */
+ fun progressTo(content: ContentKey): Float {
+ return when (content) {
+ toContent -> progress
+ fromContent -> 1f - progress
+ else ->
+ throw IllegalArgumentException(
+ "content ($content) should be either toContent ($toContent) or " +
+ "fromContent ($fromContent)"
+ )
+ }
+ }
+
/** Run this transition and return once it is finished. */
abstract suspend fun run()
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt
index 636c55799ff2..57d236be40ce 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/nestedscroll/PriorityNestedScrollConnection.kt
@@ -46,6 +46,8 @@ import kotlinx.coroutines.coroutineScope
* events in post-scroll mode.
* @param canStartPostFling lambda that returns true if the connection can start consuming scroll
* events in post-fling mode.
+ * @param canStopOnScroll lambda that returns true if the connection can stop consuming scroll
+ * events in scroll mode.
* @param canStopOnPreFling lambda that returns true if the connection can stop consuming scroll
* events in pre-fling (i.e. as soon as the user lifts their fingers).
* @param onStart lambda that is called when the connection starts consuming scroll events.
@@ -64,6 +66,9 @@ class PriorityNestedScrollConnection(
private val canStartPostScroll:
(offsetAvailable: Float, offsetBeforeStart: Float, source: NestedScrollSource) -> Boolean,
private val canStartPostFling: (velocityAvailable: Float) -> Boolean,
+ private val canStopOnScroll: (available: Float, consumed: Float) -> Boolean = { _, consumed ->
+ consumed == 0f
+ },
private val canStopOnPreFling: () -> Boolean,
private val onStart: (offsetAvailable: Float) -> Unit,
private val onScroll: (offsetAvailable: Float, source: NestedScrollSource) -> Float,
@@ -166,10 +171,6 @@ class PriorityNestedScrollConnection(
}
}
- private fun shouldStop(consumed: Float): Boolean {
- return consumed == 0f
- }
-
private fun start(
availableOffset: Float,
source: NestedScrollSource,
@@ -196,7 +197,7 @@ class PriorityNestedScrollConnection(
// Step 2: We have the priority and can consume the scroll events.
val consumedByScroll = onScroll(offsetAvailable, source)
- if (shouldStop(consumedByScroll)) {
+ if (canStopOnScroll(offsetAvailable, consumedByScroll)) {
// Step 3a: We have lost priority and we no longer need to intercept scroll events.
cancel()
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
index 339445e3483a..f24d93f0d79d 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/DraggableHandlerTest.kt
@@ -849,6 +849,34 @@ class DraggableHandlerTest {
}
@Test
+ fun duringATransition_aNewScrollGesture_shouldTakeControl() = runGestureTest {
+ val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
+ // First gesture
+ nestedScroll.scroll(available = downOffset(fractionOfScreen = 0.1f))
+ assertTransition(currentScene = SceneA)
+ nestedScroll.preFling(available = Velocity.Zero)
+ assertTransition(currentScene = SceneA)
+
+ // Second gesture, it starts during onStop() animation
+ nestedScroll.scroll(downOffset(0.1f))
+ assertTransition(currentScene = SceneA)
+
+ // Allows onStop() to complete or cancel
+ advanceUntilIdle()
+
+ // Second gesture continues
+ nestedScroll.scroll(downOffset(0.1f))
+ assertTransition(currentScene = SceneA)
+
+ // Second gesture ends
+ nestedScroll.preFling(available = Velocity.Zero)
+ assertTransition(currentScene = SceneA)
+
+ advanceUntilIdle()
+ assertIdle(currentScene = SceneA)
+ }
+
+ @Test
fun onPreFling_velocityLowerThanThreshold_remainSameScene() = runGestureTest {
val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeWithPreview)
nestedScroll.scroll(available = downOffset(fractionOfScreen = 0.1f))
@@ -1295,6 +1323,26 @@ class DraggableHandlerTest {
}
@Test
+ fun scrollKeepPriorityEvenIfWeCanNoLongerScrollOnThatDirection() = runGestureTest {
+ // Overscrolling on scene B does nothing.
+ layoutState.transitions = transitions { overscrollDisabled(SceneB, Orientation.Vertical) }
+ val nestedScroll = nestedScrollConnection(nestedScrollBehavior = EdgeAlways)
+
+ // Overscroll is disabled, it will scroll up to 100%
+ nestedScroll.scroll(available = upOffset(fractionOfScreen = 2f))
+ assertTransition(fromScene = SceneA, toScene = SceneB, progress = 1f)
+
+ // We need to maintain scroll priority even if the scene transition can no longer consume
+ // the scroll gesture.
+ nestedScroll.scroll(available = upOffset(fractionOfScreen = 0.1f))
+ assertTransition(fromScene = SceneA, toScene = SceneB, progress = 1f)
+
+ // A scroll gesture in the opposite direction allows us to return to the previous scene.
+ nestedScroll.scroll(available = downOffset(fractionOfScreen = 0.5f))
+ assertTransition(fromScene = SceneA, toScene = SceneB, progress = 0.5f)
+ }
+
+ @Test
fun overscroll_releaseBetween0And100Percent_up() = runGestureTest {
// Make scene B overscrollable.
layoutState.transitions = transitions {
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
index e57702c045c6..09b59394724d 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/MovableElementTest.kt
@@ -43,12 +43,17 @@ import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick
import androidx.compose.ui.unit.dp
import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.compose.animation.scene.TestOverlays.OverlayA
+import com.android.compose.animation.scene.TestOverlays.OverlayB
import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.animation.scene.TestScenes.SceneB
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.subjects.assertThat
import com.android.compose.test.assertSizeIsEqualTo
+import com.android.compose.test.setContentAndCreateMainScope
+import com.android.compose.test.transition
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.launch
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -341,4 +346,62 @@ class MovableElementTest {
rule.onNodeWithTag("bottomEnd").assertPositionInRootIsEqualTo(200.dp, 200.dp)
rule.onNodeWithTag("matchParentSize").assertSizeIsEqualTo(200.dp, 200.dp)
}
+
+ @Test
+ fun useCurrentSceneSizeForPlaceholderWhenReplacingOverlay() {
+ val foo =
+ MovableElementKey(
+ "foo",
+
+ // Always compose foo in SceneA.
+ contentPicker =
+ object : StaticElementContentPicker {
+ override val contents: Set<ContentKey> = setOf(SceneA, OverlayB)
+
+ override fun contentDuringTransition(
+ element: ElementKey,
+ transition: TransitionState.Transition,
+ fromContentZIndex: Float,
+ toContentZIndex: Float,
+ ): ContentKey {
+ return SceneA
+ }
+ },
+ )
+ val fooSize = 50.dp
+ val fooParentInOverlayTag = "fooParentTagInOverlay"
+
+ @Composable
+ fun SceneScope.Foo(modifier: Modifier = Modifier) {
+ // Foo wraps its content, so there is no way for STL to know its size in advance.
+ MovableElement(foo, modifier) { content { Box(Modifier.size(fooSize)) } }
+ }
+
+ val state =
+ rule.runOnUiThread {
+ MutableSceneTransitionLayoutState(
+ initialScene = SceneA,
+ initialOverlays = setOf(OverlayA),
+ )
+ }
+
+ val scope =
+ rule.setContentAndCreateMainScope {
+ SceneTransitionLayout(state) {
+ scene(SceneA) { Box(Modifier.fillMaxSize()) { Foo() } }
+ overlay(OverlayA) { /* empty */ }
+ overlay(OverlayB) { Box(Modifier.testTag(fooParentInOverlayTag)) { Foo() } }
+ }
+ }
+
+ // Start an overlay replace transition.
+ scope.launch {
+ state.startTransition(transition(from = OverlayA, to = OverlayB, progress = { 0.5f }))
+ }
+
+ // The parent of foo should have a correct size in OverlayB even if Foo was never composed
+ // there by using the size information from SceneA.
+ rule.waitForIdle()
+ rule.onNodeWithTag(fooParentInOverlayTag).assertSizeIsEqualTo(fooSize)
+ }
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
index f5bb5ba032c2..a2b263b9f9ed 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
@@ -43,6 +43,7 @@ import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.consumeAsFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runTest
+import org.junit.Assert.assertThrows
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -768,4 +769,12 @@ class SceneTransitionLayoutStateTest {
assertThat(state.transitionState).isIdle()
assertThat(state.transitionState).hasCurrentScene(SceneC)
}
+
+ @Test
+ fun transition_progressTo() {
+ val transition = transition(from = SceneA, to = SceneB, progress = { 0.2f })
+ assertThat(transition.progressTo(SceneB)).isEqualTo(0.2f)
+ assertThat(transition.progressTo(SceneA)).isEqualTo(1f - 0.2f)
+ assertThrows(IllegalArgumentException::class.java) { transition.progressTo(SceneC) }
+ }
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
index 3001505d0e02..2bc9b3826548 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SwipeToSceneTest.kt
@@ -938,6 +938,71 @@ class SwipeToSceneTest {
}
@Test
+ fun scrollKeepPriorityEvenIfWeCanNoLongerScrollOnThatDirection() {
+ val swipeDistance = 100.dp
+ val state =
+ rule.runOnUiThread {
+ MutableSceneTransitionLayoutState(
+ SceneA,
+ transitions {
+ from(SceneA, to = SceneB) { distance = FixedDistance(swipeDistance) }
+ from(SceneB, to = SceneC) { distance = FixedDistance(swipeDistance) }
+ overscrollDisabled(SceneB, Orientation.Vertical)
+ },
+ )
+ }
+ val layoutSize = 200.dp
+ var touchSlop = 0f
+ rule.setContent {
+ touchSlop = LocalViewConfiguration.current.touchSlop
+ SceneTransitionLayout(state, Modifier.size(layoutSize)) {
+ scene(SceneA, userActions = mapOf(Swipe.Down to SceneB, Swipe.Right to SceneC)) {
+ Box(
+ Modifier.fillMaxSize()
+ // A scrollable that does not consume the scroll gesture
+ .scrollable(rememberScrollableState { 0f }, Orientation.Vertical)
+ )
+ }
+ scene(SceneB, userActions = mapOf(Swipe.Right to SceneC)) {
+ Box(Modifier.element(TestElements.Foo).fillMaxSize())
+ }
+ scene(SceneC) { Box(Modifier.fillMaxSize()) }
+ }
+ }
+
+ fun assertTransition(from: SceneKey, to: SceneKey, progress: Float) {
+ val transition = assertThat(state.transitionState).isSceneTransition()
+ assertThat(transition).hasFromScene(from)
+ assertThat(transition).hasToScene(to)
+ assertThat(transition.progress).isEqualTo(progress)
+ }
+
+ // Vertical scroll 100%
+ rule.onRoot().performTouchInput {
+ val middle = (layoutSize / 2).toPx()
+ down(Offset(middle, middle))
+ moveBy(Offset(0f, y = touchSlop + swipeDistance.toPx()), delayMillis = 1_000)
+ }
+ assertTransition(from = SceneA, to = SceneB, progress = 1f)
+
+ // Continue vertical scroll, should be ignored (overscrollDisabled)
+ rule.onRoot().performTouchInput { moveBy(Offset(0f, y = touchSlop), delayMillis = 1_000) }
+ assertTransition(from = SceneA, to = SceneB, progress = 1f)
+
+ // Horizontal scroll, should be ignored
+ rule.onRoot().performTouchInput {
+ moveBy(Offset(x = touchSlop + swipeDistance.toPx(), 0f), delayMillis = 1_000)
+ }
+ assertTransition(from = SceneA, to = SceneB, progress = 1f)
+
+ // Vertical scroll, in the opposite direction
+ rule.onRoot().performTouchInput {
+ moveBy(Offset(0f, -swipeDistance.toPx()), delayMillis = 1_000)
+ }
+ assertTransition(from = SceneA, to = SceneB, progress = 0f)
+ }
+
+ @Test
fun sceneWithoutSwipesDoesNotConsumeGestures() {
val buttonTag = "button"
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestReplaceOverlayTransition.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestReplaceOverlayTransition.kt
new file mode 100644
index 000000000000..c342f488212a
--- /dev/null
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestReplaceOverlayTransition.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2024 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.compose.test
+
+import androidx.compose.foundation.gestures.Orientation
+import com.android.compose.animation.scene.ContentKey
+import com.android.compose.animation.scene.OverlayKey
+import com.android.compose.animation.scene.SceneTransitionLayoutImpl
+import com.android.compose.animation.scene.content.state.TransitionState
+import com.android.compose.animation.scene.content.state.TransitionState.Transition
+import kotlinx.coroutines.CompletableDeferred
+
+/** A [Transition.ShowOrHideOverlay] for tests that will be finished once [finish] is called. */
+abstract class TestReplaceOverlayTransition(
+ fromOverlay: OverlayKey,
+ toOverlay: OverlayKey,
+ replacedTransition: Transition?,
+) :
+ Transition.ReplaceOverlay(
+ fromOverlay = fromOverlay,
+ toOverlay = toOverlay,
+ replacedTransition = replacedTransition,
+ ) {
+ private val finishCompletable = CompletableDeferred<Unit>()
+
+ override suspend fun run() {
+ finishCompletable.await()
+ }
+
+ /** Finish this transition. */
+ fun finish() {
+ finishCompletable.complete(Unit)
+ }
+}
+
+/** A utility to easily create a [TestReplaceOverlayTransition] in tests. */
+fun transition(
+ from: OverlayKey,
+ to: OverlayKey,
+ effectivelyShownOverlay: () -> OverlayKey = { to },
+ progress: () -> Float = { 0f },
+ progressVelocity: () -> Float = { 0f },
+ previewProgress: () -> Float = { 0f },
+ previewProgressVelocity: () -> Float = { 0f },
+ isInPreviewStage: () -> Boolean = { false },
+ interruptionProgress: () -> Float = { 0f },
+ isInitiatedByUserInput: Boolean = false,
+ isUserInputOngoing: Boolean = false,
+ isUpOrLeft: Boolean = false,
+ bouncingContent: ContentKey? = null,
+ orientation: Orientation = Orientation.Horizontal,
+ onFreezeAndAnimate: ((TestReplaceOverlayTransition) -> Unit)? = null,
+ replacedTransition: Transition? = null,
+): TestReplaceOverlayTransition {
+ return object :
+ TestReplaceOverlayTransition(from, to, replacedTransition),
+ TransitionState.HasOverscrollProperties {
+ override val effectivelyShownOverlay: OverlayKey
+ get() = effectivelyShownOverlay()
+
+ override val progress: Float
+ get() = progress()
+
+ override val progressVelocity: Float
+ get() = progressVelocity()
+
+ override val previewProgress: Float
+ get() = previewProgress()
+
+ override val previewProgressVelocity: Float
+ get() = previewProgressVelocity()
+
+ override val isInPreviewStage: Boolean
+ get() = isInPreviewStage()
+
+ override val isInitiatedByUserInput: Boolean = isInitiatedByUserInput
+ override val isUserInputOngoing: Boolean = isUserInputOngoing
+ override val isUpOrLeft: Boolean = isUpOrLeft
+ override val bouncingContent: ContentKey? = bouncingContent
+ override val orientation: Orientation = orientation
+ override val absoluteDistance = 0f
+
+ override fun freezeAndAnimateToCurrentState() {
+ if (onFreezeAndAnimate != null) {
+ onFreezeAndAnimate(this)
+ } else {
+ finish()
+ }
+ }
+
+ override fun interruptionProgress(layoutImpl: SceneTransitionLayoutImpl): Float {
+ return interruptionProgress()
+ }
+ }
+}
diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
index 900971bc3927..2a858238c156 100644
--- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
+++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt
@@ -39,7 +39,7 @@ class DefaultClockProvider(
val resources: Resources,
private val hasStepClockAnimation: Boolean = false,
private val migratedClocks: Boolean = false,
- private val clockReactiveVariants: Boolean = false,
+ private val isClockReactiveVariantsEnabled: Boolean = false,
) : ClockProvider {
private var messageBuffers: ClockMessageBuffers? = null
@@ -54,7 +54,7 @@ class DefaultClockProvider(
throw IllegalArgumentException("${settings.clockId} is unsupported by $TAG")
}
- return if (clockReactiveVariants) {
+ return if (isClockReactiveVariantsEnabled) {
val buffer =
messageBuffers?.infraMessageBuffer ?: LogcatOnlyMessageBuffer(LogLevel.INFO)
val assets = AssetLoader(ctx, ctx, "clocks/", buffer)
@@ -84,7 +84,7 @@ class DefaultClockProvider(
// TODO(b/352049256): Update placeholder to actual resource
resources.getDrawable(R.drawable.clock_default_thumbnail, null),
isReactiveToTone = true,
- isReactiveToTouch = clockReactiveVariants,
+ isReactiveToTouch = isClockReactiveVariantsEnabled,
axes = listOf(), // TODO: Ater some picker definition
)
}
@@ -103,7 +103,6 @@ class DefaultClockProvider(
timespec = DigitalTimespec.FIRST_DIGIT,
style =
FontTextStyle(
- fontFamily = "google_sans_flex.ttf",
lineHeight = 147.25f,
fontVariation =
"'wght' 603, 'wdth' 100, 'opsz' 144, 'ROND' 100",
@@ -112,7 +111,6 @@ class DefaultClockProvider(
FontTextStyle(
fontVariation =
"'wght' 74, 'wdth' 43, 'opsz' 144, 'ROND' 100",
- fontFamily = "google_sans_flex.ttf",
fillColorLight = "#FFFFFFFF",
outlineColor = "#00000000",
renderType = RenderType.CHANGE_WEIGHT,
@@ -131,7 +129,6 @@ class DefaultClockProvider(
timespec = DigitalTimespec.SECOND_DIGIT,
style =
FontTextStyle(
- fontFamily = "google_sans_flex.ttf",
lineHeight = 147.25f,
fontVariation =
"'wght' 603, 'wdth' 100, 'opsz' 144, 'ROND' 100",
@@ -140,7 +137,6 @@ class DefaultClockProvider(
FontTextStyle(
fontVariation =
"'wght' 74, 'wdth' 43, 'opsz' 144, 'ROND' 100",
- fontFamily = "google_sans_flex.ttf",
fillColorLight = "#FFFFFFFF",
outlineColor = "#00000000",
renderType = RenderType.CHANGE_WEIGHT,
@@ -159,7 +155,6 @@ class DefaultClockProvider(
timespec = DigitalTimespec.FIRST_DIGIT,
style =
FontTextStyle(
- fontFamily = "google_sans_flex.ttf",
lineHeight = 147.25f,
fontVariation =
"'wght' 603, 'wdth' 100, 'opsz' 144, 'ROND' 100",
@@ -168,7 +163,6 @@ class DefaultClockProvider(
FontTextStyle(
fontVariation =
"'wght' 74, 'wdth' 43, 'opsz' 144, 'ROND' 100",
- fontFamily = "google_sans_flex.ttf",
fillColorLight = "#FFFFFFFF",
outlineColor = "#00000000",
renderType = RenderType.CHANGE_WEIGHT,
@@ -187,7 +181,6 @@ class DefaultClockProvider(
timespec = DigitalTimespec.SECOND_DIGIT,
style =
FontTextStyle(
- fontFamily = "google_sans_flex.ttf",
lineHeight = 147.25f,
fontVariation =
"'wght' 603, 'wdth' 100, 'opsz' 144, 'ROND' 100",
@@ -196,7 +189,6 @@ class DefaultClockProvider(
FontTextStyle(
fontVariation =
"'wght' 74, 'wdth' 43, 'opsz' 144, 'ROND' 100",
- fontFamily = "google_sans_flex.ttf",
fillColorLight = "#FFFFFFFF",
outlineColor = "#00000000",
renderType = RenderType.CHANGE_WEIGHT,
@@ -221,13 +213,11 @@ class DefaultClockProvider(
timespec = DigitalTimespec.TIME_FULL_FORMAT,
style =
FontTextStyle(
- fontFamily = "google_sans_flex.ttf",
fontVariation = "'wght' 600, 'wdth' 100, 'opsz' 144, 'ROND' 100",
fontSizeScale = 0.98f,
),
aodStyle =
FontTextStyle(
- fontFamily = "google_sans_flex.ttf",
fontVariation = "'wght' 133, 'wdth' 43, 'opsz' 144, 'ROND' 100",
fillColorLight = "#FFFFFFFF",
outlineColor = "#00000000",
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
index af3ddfca14b6..29ee87466f1a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
@@ -17,6 +17,9 @@
package com.android.systemui.bouncer.ui.viewmodel
import android.content.pm.UserInfo
+import android.platform.test.annotations.EnableFlags
+import android.view.KeyEvent
+import androidx.compose.ui.input.key.KeyEventType
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.SceneKey
@@ -27,6 +30,7 @@ import com.android.systemui.authentication.shared.model.AuthenticationMethodMode
import com.android.systemui.bouncer.domain.interactor.bouncerInteractor
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
+import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.inputmethod.data.model.InputMethodModel
import com.android.systemui.inputmethod.data.repository.fakeInputMethodRepository
import com.android.systemui.inputmethod.domain.interactor.inputMethodInteractor
@@ -67,11 +71,12 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
private val inputMethodInteractor by lazy { kosmos.inputMethodInteractor }
private val isInputEnabled = MutableStateFlow(true)
- private val underTest =
+ private val underTest by lazy {
kosmos.passwordBouncerViewModelFactory.create(
isInputEnabled = isInputEnabled,
onIntentionalUserInput = {},
)
+ }
@Before
fun setUp() {
@@ -345,6 +350,37 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
assertThat(textInputFocusRequested).isFalse()
}
+ @EnableFlags(com.android.systemui.Flags.FLAG_COMPOSE_BOUNCER)
+ @Test
+ fun consumeConfirmKeyEvents_toPreventItFromPropagating() =
+ testScope.runTest { verifyConfirmKeyEventsBehavior(keyUpEventConsumed = true) }
+
+ @EnableFlags(com.android.systemui.Flags.FLAG_COMPOSE_BOUNCER)
+ @EnableSceneContainer
+ @Test
+ fun noops_whenSceneContainerIsAlsoEnabled() =
+ testScope.runTest { verifyConfirmKeyEventsBehavior(keyUpEventConsumed = false) }
+
+ private fun verifyConfirmKeyEventsBehavior(keyUpEventConsumed: Boolean) {
+ assertThat(underTest.onKeyEvent(KeyEventType.KeyDown, KeyEvent.KEYCODE_DPAD_CENTER))
+ .isFalse()
+ assertThat(underTest.onKeyEvent(KeyEventType.KeyUp, KeyEvent.KEYCODE_DPAD_CENTER))
+ .isEqualTo(keyUpEventConsumed)
+
+ assertThat(underTest.onKeyEvent(KeyEventType.KeyDown, KeyEvent.KEYCODE_ENTER)).isFalse()
+ assertThat(underTest.onKeyEvent(KeyEventType.KeyUp, KeyEvent.KEYCODE_ENTER))
+ .isEqualTo(keyUpEventConsumed)
+
+ assertThat(underTest.onKeyEvent(KeyEventType.KeyDown, KeyEvent.KEYCODE_NUMPAD_ENTER))
+ .isFalse()
+ assertThat(underTest.onKeyEvent(KeyEventType.KeyUp, KeyEvent.KEYCODE_NUMPAD_ENTER))
+ .isEqualTo(keyUpEventConsumed)
+
+ // space is ignored.
+ assertThat(underTest.onKeyEvent(KeyEventType.KeyUp, KeyEvent.KEYCODE_SPACE)).isFalse()
+ assertThat(underTest.onKeyEvent(KeyEventType.KeyDown, KeyEvent.KEYCODE_SPACE)).isFalse()
+ }
+
private fun TestScope.switchToScene(toScene: SceneKey) {
val currentScene by collectLastValue(sceneInteractor.currentScene)
val bouncerHidden = currentScene == Scenes.Bouncer && toScene != Scenes.Bouncer
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekbarHapticPluginTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekbarHapticPluginTest.kt
index 855b6d0b95d7..587d3d98fbec 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekbarHapticPluginTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SeekbarHapticPluginTest.kt
@@ -20,6 +20,7 @@ import android.widget.SeekBar
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.haptics.msdl.msdlPlayer
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.statusbar.VibratorHelper
@@ -141,11 +142,7 @@ class SeekbarHapticPluginTest : SysuiTestCase() {
}
private fun createPlugin() {
- plugin =
- SeekbarHapticPlugin(
- vibratorHelper,
- kosmos.fakeSystemClock,
- )
+ plugin = SeekbarHapticPlugin(vibratorHelper, kosmos.msdlPlayer, kosmos.fakeSystemClock)
}
companion object {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt
index 28f88fe1d84e..3467382df4da 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProviderTest.kt
@@ -16,16 +16,26 @@
package com.android.systemui.haptics.slider
+import android.os.VibrationAttributes
import android.os.VibrationEffect
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.haptics.fakeVibratorHelper
+import com.android.systemui.haptics.msdl.fakeMSDLPlayer
+import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
import com.android.systemui.util.time.fakeSystemClock
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.android.msdl.domain.InteractionProperties
+import com.google.common.truth.Truth.assertThat
import kotlin.math.max
import kotlin.test.assertEquals
import kotlin.test.assertTrue
+import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -35,6 +45,7 @@ import org.junit.runner.RunWith
class SliderHapticFeedbackProviderTest : SysuiTestCase() {
private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
private val config = SliderHapticFeedbackConfig()
@@ -44,7 +55,14 @@ class SliderHapticFeedbackProviderTest : SysuiTestCase() {
private val dragTextureThresholdMillis =
lowTickDuration * config.numberOfLowTicks + config.deltaMillisForDragInterval
private val vibratorHelper = kosmos.fakeVibratorHelper
+ private val msdlPlayer = kosmos.fakeMSDLPlayer
private lateinit var sliderHapticFeedbackProvider: SliderHapticFeedbackProvider
+ private val pipeliningAttributes =
+ VibrationAttributes.Builder()
+ .setUsage(VibrationAttributes.USAGE_TOUCH)
+ .setFlags(VibrationAttributes.FLAG_PIPELINED_EFFECT)
+ .build()
+ private lateinit var dynamicProperties: InteractionProperties.DynamicVibrationScale
@Before
fun setup() {
@@ -54,13 +72,20 @@ class SliderHapticFeedbackProviderTest : SysuiTestCase() {
sliderHapticFeedbackProvider =
SliderHapticFeedbackProvider(
vibratorHelper,
+ msdlPlayer,
dragVelocityProvider,
config,
kosmos.fakeSystemClock,
)
+ dynamicProperties =
+ InteractionProperties.DynamicVibrationScale(
+ sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale),
+ pipeliningAttributes,
+ )
}
@Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtLowerBookend_playsClick() =
with(kosmos) {
val vibration =
@@ -77,6 +102,18 @@ class SliderHapticFeedbackProviderTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtLowerBookend_playsDragThresholdLimitToken() =
+ testScope.runTest {
+ sliderHapticFeedbackProvider.onLowerBookend()
+
+ assertThat(msdlPlayer.latestTokenPlayed)
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(dynamicProperties)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtLowerBookend_twoTimes_playsClickOnlyOnce() =
with(kosmos) {
val vibration =
@@ -94,6 +131,20 @@ class SliderHapticFeedbackProviderTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtLowerBookend_twoTimes_playsDragThresholdLimitTokenOnlyOnce() =
+ testScope.runTest {
+ sliderHapticFeedbackProvider.onLowerBookend()
+ sliderHapticFeedbackProvider.onLowerBookend()
+
+ assertThat(msdlPlayer.latestTokenPlayed)
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(dynamicProperties)
+ assertThat(msdlPlayer.getHistory().size).isEqualTo(1)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtUpperBookend_playsClick() =
with(kosmos) {
val vibration =
@@ -110,6 +161,18 @@ class SliderHapticFeedbackProviderTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtUpperBookend_playsDragThresholdLimitToken() =
+ testScope.runTest {
+ sliderHapticFeedbackProvider.onUpperBookend()
+
+ assertThat(msdlPlayer.latestTokenPlayed)
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(dynamicProperties)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtUpperBookend_twoTimes_playsClickOnlyOnce() =
with(kosmos) {
val vibration =
@@ -127,6 +190,20 @@ class SliderHapticFeedbackProviderTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtUpperBookend_twoTimes_playsDragThresholdLimitTokenOnlyOnce() =
+ testScope.runTest {
+ sliderHapticFeedbackProvider.onUpperBookend()
+ sliderHapticFeedbackProvider.onUpperBookend()
+
+ assertThat(msdlPlayer.latestTokenPlayed)
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(dynamicProperties)
+ assertThat(msdlPlayer.getHistory().size).isEqualTo(1)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtProgress_onQuickSuccession_playsLowTicksOnce() =
with(kosmos) {
// GIVEN max velocity and slider progress
@@ -150,6 +227,31 @@ class SliderHapticFeedbackProviderTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtProgress_onQuickSuccession_playsContinuousDragTokenOnce() =
+ with(kosmos) {
+ // GIVEN max velocity and slider progress
+ val progress = 1f
+ val expectedScale =
+ sliderHapticFeedbackProvider.scaleOnDragTexture(config.maxVelocityToScale, progress)
+ val expectedProperties =
+ InteractionProperties.DynamicVibrationScale(expectedScale, pipeliningAttributes)
+
+ // GIVEN system running for 1s
+ fakeSystemClock.advanceTime(1000)
+
+ // WHEN two calls to play occur immediately
+ sliderHapticFeedbackProvider.onProgress(progress)
+ sliderHapticFeedbackProvider.onProgress(progress)
+
+ // THEN the correct token plays once
+ assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.DRAG_INDICATOR_CONTINUOUS)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(expectedProperties)
+ assertThat(msdlPlayer.getHistory().size).isEqualTo(1)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtProgress_beforeNextDragThreshold_playsLowTicksOnce() =
with(kosmos) {
// GIVEN max velocity and a slider progress at half progress
@@ -175,6 +277,41 @@ class SliderHapticFeedbackProviderTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtProgress_beforeNextDragThreshold_playsContinousDragTokenOnce() =
+ with(kosmos) {
+ // GIVEN max velocity and a slider progress at half progress
+ val firstProgress = 0.5f
+
+ // Given a second slider progress event smaller than the progress threshold
+ val secondProgress =
+ firstProgress + max(0f, config.deltaProgressForDragThreshold - 0.01f)
+
+ // GIVEN system running for 1s
+ fakeSystemClock.advanceTime(1000)
+
+ // WHEN two calls to play occur with the required threshold separation (time and
+ // progress)
+ sliderHapticFeedbackProvider.onProgress(firstProgress)
+ fakeSystemClock.advanceTime(dragTextureThresholdMillis.toLong())
+ sliderHapticFeedbackProvider.onProgress(secondProgress)
+
+ // THEN Only the first event plays the expected token and propertiesv
+ val expectedProperties =
+ InteractionProperties.DynamicVibrationScale(
+ sliderHapticFeedbackProvider.scaleOnDragTexture(
+ config.maxVelocityToScale,
+ firstProgress,
+ ),
+ pipeliningAttributes,
+ )
+ assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.DRAG_INDICATOR_CONTINUOUS)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(expectedProperties)
+ assertThat(msdlPlayer.getHistory().size).isEqualTo(1)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtProgress_afterNextDragThreshold_playsLowTicksTwice() =
with(kosmos) {
// GIVEN max velocity and a slider progress at half progress
@@ -200,6 +337,51 @@ class SliderHapticFeedbackProviderTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtProgress_afterNextDragThreshold_playsContinuousDragTokenTwice() =
+ with(kosmos) {
+ // GIVEN max velocity and a slider progress at half progress
+ val firstProgress = 0.5f
+
+ // Given a second slider progress event beyond progress threshold
+ val secondProgress = firstProgress + config.deltaProgressForDragThreshold + 0.01f
+
+ // GIVEN system running for 1s
+ fakeSystemClock.advanceTime(1000)
+
+ // WHEN two calls to play occur with the required threshold separation (time and
+ // progress)
+ sliderHapticFeedbackProvider.onProgress(firstProgress)
+ fakeSystemClock.advanceTime(dragTextureThresholdMillis.toLong())
+ sliderHapticFeedbackProvider.onProgress(secondProgress)
+
+ // THEN the correct token plays twice with the correct properties
+ val firstProperties =
+ InteractionProperties.DynamicVibrationScale(
+ sliderHapticFeedbackProvider.scaleOnDragTexture(
+ config.maxVelocityToScale,
+ firstProgress,
+ ),
+ pipeliningAttributes,
+ )
+ val secondProperties =
+ InteractionProperties.DynamicVibrationScale(
+ sliderHapticFeedbackProvider.scaleOnDragTexture(
+ config.maxVelocityToScale,
+ secondProgress,
+ ),
+ pipeliningAttributes,
+ )
+
+ assertThat(msdlPlayer.getHistory().size).isEqualTo(2)
+ assertThat(msdlPlayer.tokensPlayed[0]).isEqualTo(MSDLToken.DRAG_INDICATOR_CONTINUOUS)
+ assertThat(msdlPlayer.propertiesPlayed[0]).isEqualTo(firstProperties)
+ assertThat(msdlPlayer.tokensPlayed[1]).isEqualTo(MSDLToken.DRAG_INDICATOR_CONTINUOUS)
+ assertThat(msdlPlayer.propertiesPlayed[1]).isEqualTo(secondProperties)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtLowerBookend_afterPlayingAtProgress_playsTwice() =
with(kosmos) {
// GIVEN max velocity and slider progress
@@ -233,6 +415,36 @@ class SliderHapticFeedbackProviderTest : SysuiTestCase() {
}
@Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtLowerBookend_afterPlayingAtProgress_playsTokensTwice() =
+ with(kosmos) {
+ // GIVEN max velocity and slider progress
+ val progress = 1f
+ val expectedProperties =
+ InteractionProperties.DynamicVibrationScale(
+ sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale),
+ pipeliningAttributes,
+ )
+
+ // GIVEN a vibration at the lower bookend followed by a request to vibrate at progress
+ sliderHapticFeedbackProvider.onLowerBookend()
+ sliderHapticFeedbackProvider.onProgress(progress)
+
+ // WHEN a vibration is to trigger again at the lower bookend
+ sliderHapticFeedbackProvider.onLowerBookend()
+
+ // THEN there are two bookend token vibrations
+ assertThat(msdlPlayer.getHistory().size).isEqualTo(2)
+ assertThat(msdlPlayer.tokensPlayed[0])
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.propertiesPlayed[0]).isEqualTo(expectedProperties)
+ assertThat(msdlPlayer.tokensPlayed[1])
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.propertiesPlayed[1]).isEqualTo(expectedProperties)
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
fun playHapticAtUpperBookend_afterPlayingAtProgress_playsTwice() =
with(kosmos) {
// GIVEN max velocity and slider progress
@@ -265,6 +477,36 @@ class SliderHapticFeedbackProviderTest : SysuiTestCase() {
)
}
+ @Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun playHapticAtUpperBookend_afterPlayingAtProgress_playsTokensTwice() =
+ with(kosmos) {
+ // GIVEN max velocity and slider progress
+ val progress = 1f
+ val expectedProperties =
+ InteractionProperties.DynamicVibrationScale(
+ sliderHapticFeedbackProvider.scaleOnEdgeCollision(config.maxVelocityToScale),
+ pipeliningAttributes,
+ )
+
+ // GIVEN a vibration at the upper bookend followed by a request to vibrate at progress
+ sliderHapticFeedbackProvider.onUpperBookend()
+ sliderHapticFeedbackProvider.onProgress(progress)
+
+ // WHEN a vibration is to trigger again at the upper bookend
+ sliderHapticFeedbackProvider.onUpperBookend()
+
+ // THEN there are two bookend vibrations
+ assertThat(msdlPlayer.getHistory().size).isEqualTo(2)
+ assertThat(msdlPlayer.tokensPlayed[0])
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.propertiesPlayed[0]).isEqualTo(expectedProperties)
+ assertThat(msdlPlayer.tokensPlayed[1])
+ .isEqualTo(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT)
+ assertThat(msdlPlayer.propertiesPlayed[1]).isEqualTo(expectedProperties)
+ }
+
+ @Test
fun dragTextureLastProgress_afterDragTextureHaptics_keepsLastDragTextureProgress() =
with(kosmos) {
// GIVEN max velocity and a slider progress at half progress
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
index 93754fd7e778..77f19795eaf7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
@@ -314,16 +314,6 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun isActiveDreamLockscreenHosted() =
- testScope.runTest {
- underTest.setIsActiveDreamLockscreenHosted(true)
- assertThat(underTest.isActiveDreamLockscreenHosted.value).isEqualTo(true)
-
- underTest.setIsActiveDreamLockscreenHosted(false)
- assertThat(underTest.isActiveDreamLockscreenHosted.value).isEqualTo(false)
- }
-
- @Test
fun isUdfpsSupported() =
testScope.runTest {
whenever(keyguardUpdateMonitor.isUdfpsSupported).thenReturn(true)
@@ -336,26 +326,14 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
@Test
fun isKeyguardGoingAway() =
testScope.runTest {
- whenever(keyguardStateController.isKeyguardGoingAway).thenReturn(false)
- var latest: Boolean? = null
- val job = underTest.isKeyguardGoingAway.onEach { latest = it }.launchIn(this)
- runCurrent()
- assertThat(latest).isFalse()
-
- val captor = argumentCaptor<KeyguardStateController.Callback>()
- verify(keyguardStateController, atLeastOnce()).addCallback(captor.capture())
+ val isGoingAway by collectLastValue(underTest.isKeyguardGoingAway)
+ assertThat(isGoingAway).isFalse()
- whenever(keyguardStateController.isKeyguardGoingAway).thenReturn(true)
- captor.value.onKeyguardGoingAwayChanged()
- runCurrent()
- assertThat(latest).isTrue()
-
- whenever(keyguardStateController.isKeyguardGoingAway).thenReturn(false)
- captor.value.onKeyguardGoingAwayChanged()
- runCurrent()
- assertThat(latest).isFalse()
+ underTest.isKeyguardGoingAway.value = true
+ assertThat(isGoingAway).isTrue()
- job.cancel()
+ underTest.isKeyguardGoingAway.value = false
+ assertThat(isGoingAway).isFalse()
}
@Test
@@ -423,17 +401,17 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
runCurrent()
listener.onDozeTransition(
DozeMachine.State.DOZE_REQUEST_PULSE,
- DozeMachine.State.DOZE_PULSING
+ DozeMachine.State.DOZE_PULSING,
)
runCurrent()
listener.onDozeTransition(
DozeMachine.State.DOZE_SUSPEND_TRIGGERS,
- DozeMachine.State.DOZE_PULSE_DONE
+ DozeMachine.State.DOZE_PULSE_DONE,
)
runCurrent()
listener.onDozeTransition(
DozeMachine.State.DOZE_AOD_PAUSING,
- DozeMachine.State.DOZE_AOD_PAUSED
+ DozeMachine.State.DOZE_AOD_PAUSED,
)
runCurrent()
@@ -443,22 +421,22 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
// Initial value will be UNINITIALIZED
DozeTransitionModel(
DozeStateModel.UNINITIALIZED,
- DozeStateModel.UNINITIALIZED
+ DozeStateModel.UNINITIALIZED,
),
DozeTransitionModel(DozeStateModel.INITIALIZED, DozeStateModel.DOZE),
DozeTransitionModel(DozeStateModel.DOZE, DozeStateModel.DOZE_AOD),
DozeTransitionModel(DozeStateModel.DOZE_AOD_DOCKED, DozeStateModel.FINISH),
DozeTransitionModel(
DozeStateModel.DOZE_REQUEST_PULSE,
- DozeStateModel.DOZE_PULSING
+ DozeStateModel.DOZE_PULSING,
),
DozeTransitionModel(
DozeStateModel.DOZE_SUSPEND_TRIGGERS,
- DozeStateModel.DOZE_PULSE_DONE
+ DozeStateModel.DOZE_PULSE_DONE,
),
DozeTransitionModel(
DozeStateModel.DOZE_AOD_PAUSING,
- DozeStateModel.DOZE_AOD_PAUSED
+ DozeStateModel.DOZE_AOD_PAUSED,
),
)
)
@@ -510,12 +488,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
// consuming it should handle that properly.
assertThat(values).isEqualTo(listOf(null))
- listOf(
- Point(500, 500),
- Point(0, 0),
- null,
- Point(250, 250),
- )
+ listOf(Point(500, 500), Point(0, 0), null, Point(250, 250))
.onEach {
facePropertyRepository.setSensorLocation(it)
runCurrent()
@@ -551,7 +524,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
.onEach { biometricSourceType ->
underTest.setBiometricUnlockState(
BiometricUnlockMode.NONE,
- BiometricUnlockSource.Companion.fromBiometricSourceType(biometricSourceType)
+ BiometricUnlockSource.Companion.fromBiometricSourceType(biometricSourceType),
)
runCurrent()
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt
index 3b6e5d09a37c..df44425d4b49 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt
@@ -90,6 +90,7 @@ class FromDozingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiT
private lateinit var powerInteractor: PowerInteractor
private lateinit var transitionRepository: FakeKeyguardTransitionRepository
+ private lateinit var keyguardInteractor: KeyguardInteractor
companion object {
@JvmStatic
@@ -106,6 +107,7 @@ class FromDozingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiT
@Before
fun setup() {
powerInteractor = kosmos.powerInteractor
+ keyguardInteractor = kosmos.keyguardInteractor
transitionRepository = kosmos.fakeKeyguardTransitionRepositorySpy
underTest = kosmos.fromDozingTransitionInteractor
@@ -137,6 +139,20 @@ class FromDozingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiT
}
@Test
+ @DisableFlags(FLAG_KEYGUARD_WM_STATE_REFACTOR)
+ fun testTransitionToGone_onWakeup_whenGoingAway() =
+ testScope.runTest {
+ keyguardInteractor.setIsKeyguardGoingAway(true)
+ runCurrent()
+
+ powerInteractor.setAwakeForTest()
+ advanceTimeBy(60L)
+
+ assertThat(transitionRepository)
+ .startedTransition(from = KeyguardState.DOZING, to = KeyguardState.GONE)
+ }
+
+ @Test
@EnableFlags(FLAG_KEYGUARD_WM_STATE_REFACTOR)
@DisableFlags(FLAG_COMMUNAL_SCENE_KTF_REFACTOR)
fun testTransitionToLockscreen_onWake_canDream_glanceableHubAvailable() =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorTest.kt
index 48621047016b..e60d971c7289 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorTest.kt
@@ -173,17 +173,6 @@ class KeyguardClockInteractorTest : SysuiTestCase() {
@Test
@EnableSceneContainer
- fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_isActiveDreamLockscreenHosted_true() =
- testScope.runTest {
- val value by collectLastValue(underTest.clockShouldBeCentered)
- kosmos.shadeRepository.setShadeLayoutWide(true)
- kosmos.activeNotificationListRepository.setActiveNotifs(1)
- kosmos.keyguardRepository.setIsActiveDreamLockscreenHosted(true)
- assertThat(value).isTrue()
- }
-
- @Test
- @EnableSceneContainer
fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_hasPulsingNotifications_false() =
testScope.runTest {
val value by collectLastValue(underTest.clockShouldBeCentered)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractorTest.kt
index 945e44afa455..fbdab7d40c9b 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractorTest.kt
@@ -32,6 +32,7 @@ import com.android.systemui.power.domain.interactor.PowerInteractorFactory
import com.android.systemui.shade.ShadeController
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
+import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
@@ -53,6 +54,7 @@ import org.mockito.kotlin.isNull
@RunWith(AndroidJUnit4::class)
class KeyguardKeyEventInteractorTest : SysuiTestCase() {
@JvmField @Rule var mockitoRule = MockitoJUnit.rule()
+ private val kosmos = testKosmos()
private val actionDownVolumeDownKeyEvent =
KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_VOLUME_DOWN)
@@ -85,6 +87,7 @@ class KeyguardKeyEventInteractorTest : SysuiTestCase() {
mediaSessionLegacyHelperWrapper,
backActionInteractor,
powerInteractor,
+ kosmos.keyguardMediaKeyInteractor,
)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardMediaKeyInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardMediaKeyInteractorTest.kt
new file mode 100644
index 000000000000..b82e1542903b
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardMediaKeyInteractorTest.kt
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2024 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.keyguard.domain.interactor
+
+import android.platform.test.annotations.EnableFlags
+import android.view.KeyEvent
+import android.view.KeyEvent.ACTION_DOWN
+import android.view.KeyEvent.ACTION_UP
+import android.view.KeyEvent.KEYCODE_MEDIA_PAUSE
+import android.view.KeyEvent.KEYCODE_MEDIA_PLAY
+import android.view.KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_COMPOSE_BOUNCER
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.lifecycle.activateIn
+import com.android.systemui.telephony.data.repository.fakeTelephonyRepository
+import com.android.systemui.testKosmos
+import com.android.systemui.volume.data.repository.fakeAudioRepository
+import com.google.common.truth.Correspondence.transforming
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.Test
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@EnableFlags(FLAG_COMPOSE_BOUNCER)
+class KeyguardMediaKeyInteractorTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+
+ private val underTest = kosmos.keyguardMediaKeyInteractor
+
+ @Before
+ fun setup() {
+ underTest.activateIn(testScope)
+ }
+
+ @Test
+ fun test_onKeyEvent_playPauseKeyEvents_areSkipped_whenACallIsActive() =
+ testScope.runTest {
+ kosmos.fakeTelephonyRepository.setIsInCall(true)
+
+ assertEventConsumed(KeyEvent(ACTION_DOWN, KEYCODE_MEDIA_PLAY))
+ assertEventConsumed(KeyEvent(ACTION_DOWN, KEYCODE_MEDIA_PAUSE))
+ assertEventConsumed(KeyEvent(ACTION_DOWN, KEYCODE_MEDIA_PLAY_PAUSE))
+
+ assertThat(kosmos.fakeAudioRepository.dispatchedKeyEvents).isEmpty()
+ }
+
+ @Test
+ fun test_onKeyEvent_playPauseKeyEvents_areNotSkipped_whenACallIsNotActive() =
+ testScope.runTest {
+ kosmos.fakeTelephonyRepository.setIsInCall(false)
+
+ assertEventNotConsumed(KeyEvent(ACTION_DOWN, KEYCODE_MEDIA_PAUSE))
+ assertEventConsumed(KeyEvent(ACTION_UP, KEYCODE_MEDIA_PAUSE))
+ assertEventNotConsumed(KeyEvent(ACTION_DOWN, KEYCODE_MEDIA_PLAY))
+ assertEventConsumed(KeyEvent(ACTION_UP, KEYCODE_MEDIA_PLAY))
+ assertEventNotConsumed(KeyEvent(ACTION_DOWN, KEYCODE_MEDIA_PLAY_PAUSE))
+ assertEventConsumed(KeyEvent(ACTION_UP, KEYCODE_MEDIA_PLAY_PAUSE))
+
+ assertThat(kosmos.fakeAudioRepository.dispatchedKeyEvents)
+ .comparingElementsUsing<KeyEvent, Pair<Int, Int>>(
+ transforming({ Pair(it!!.action, it.keyCode) }, "action and keycode")
+ )
+ .containsExactly(
+ Pair(ACTION_UP, KEYCODE_MEDIA_PAUSE),
+ Pair(ACTION_UP, KEYCODE_MEDIA_PLAY),
+ Pair(ACTION_UP, KEYCODE_MEDIA_PLAY_PAUSE),
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun test_onKeyEvent_nonPlayPauseKeyEvents_areNotSkipped_whenACallIsActive() =
+ testScope.runTest {
+ kosmos.fakeTelephonyRepository.setIsInCall(true)
+
+ assertEventConsumed(KeyEvent(ACTION_DOWN, KeyEvent.KEYCODE_MUTE))
+ assertEventConsumed(KeyEvent(ACTION_UP, KeyEvent.KEYCODE_MUTE))
+
+ assertEventConsumed(KeyEvent(ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK))
+ assertEventConsumed(KeyEvent(ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK))
+
+ assertEventConsumed(KeyEvent(ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_STOP))
+ assertEventConsumed(KeyEvent(ACTION_UP, KeyEvent.KEYCODE_MEDIA_STOP))
+
+ assertEventConsumed(KeyEvent(ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT))
+ assertEventConsumed(KeyEvent(ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT))
+
+ assertEventConsumed(KeyEvent(ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PREVIOUS))
+ assertEventConsumed(KeyEvent(ACTION_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS))
+
+ assertEventConsumed(KeyEvent(ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_REWIND))
+ assertEventConsumed(KeyEvent(ACTION_UP, KeyEvent.KEYCODE_MEDIA_REWIND))
+
+ assertEventConsumed(KeyEvent(ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_RECORD))
+ assertEventConsumed(KeyEvent(ACTION_UP, KeyEvent.KEYCODE_MEDIA_RECORD))
+
+ assertEventConsumed(KeyEvent(ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD))
+ assertEventConsumed(KeyEvent(ACTION_UP, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD))
+
+ assertEventConsumed(KeyEvent(ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK))
+ assertEventConsumed(KeyEvent(ACTION_UP, KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK))
+
+ assertThat(kosmos.fakeAudioRepository.dispatchedKeyEvents)
+ .comparingElementsUsing<KeyEvent, Pair<Int, Int>>(
+ transforming({ Pair(it!!.action, it.keyCode) }, "action and keycode")
+ )
+ .containsExactly(
+ Pair(ACTION_DOWN, KeyEvent.KEYCODE_MUTE),
+ Pair(ACTION_UP, KeyEvent.KEYCODE_MUTE),
+ Pair(ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK),
+ Pair(ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK),
+ Pair(ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_STOP),
+ Pair(ACTION_UP, KeyEvent.KEYCODE_MEDIA_STOP),
+ Pair(ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_NEXT),
+ Pair(ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT),
+ Pair(ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PREVIOUS),
+ Pair(ACTION_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS),
+ Pair(ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_REWIND),
+ Pair(ACTION_UP, KeyEvent.KEYCODE_MEDIA_REWIND),
+ Pair(ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_RECORD),
+ Pair(ACTION_UP, KeyEvent.KEYCODE_MEDIA_RECORD),
+ Pair(ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD),
+ Pair(ACTION_UP, KeyEvent.KEYCODE_MEDIA_FAST_FORWARD),
+ Pair(ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK),
+ Pair(ACTION_UP, KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK),
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun volumeKeyEvents_keyEvents_areSkipped() =
+ testScope.runTest {
+ kosmos.fakeTelephonyRepository.setIsInCall(false)
+
+ assertEventNotConsumed(KeyEvent(ACTION_DOWN, KeyEvent.KEYCODE_VOLUME_UP))
+ assertEventNotConsumed(KeyEvent(ACTION_UP, KeyEvent.KEYCODE_VOLUME_UP))
+ assertEventNotConsumed(KeyEvent(ACTION_DOWN, KeyEvent.KEYCODE_VOLUME_DOWN))
+ assertEventNotConsumed(KeyEvent(ACTION_UP, KeyEvent.KEYCODE_VOLUME_DOWN))
+ assertEventNotConsumed(KeyEvent(ACTION_DOWN, KeyEvent.KEYCODE_VOLUME_MUTE))
+ assertEventNotConsumed(KeyEvent(ACTION_UP, KeyEvent.KEYCODE_VOLUME_MUTE))
+ }
+
+ private fun assertEventConsumed(keyEvent: KeyEvent) {
+ assertThat(underTest.processMediaKeyEvent(keyEvent)).isTrue()
+ }
+
+ private fun assertEventNotConsumed(keyEvent: KeyEvent) {
+ assertThat(underTest.processMediaKeyEvent(keyEvent)).isFalse()
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt
index 5bd3645b4cab..99d2da670172 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractorTest.kt
@@ -30,9 +30,11 @@ import com.android.systemui.plugins.statusbar.statusBarStateController
import com.android.systemui.qs.pipeline.domain.interactor.panelInteractor
import com.android.systemui.qs.tiles.base.interactor.QSTileInput
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
+import com.android.systemui.recordissue.IssueRecordingState
import com.android.systemui.recordissue.RecordIssueDialogDelegate
import com.android.systemui.screenrecord.RecordingController
import com.android.systemui.settings.UserContextProvider
+import com.android.systemui.settings.userFileManager
import com.android.systemui.settings.userTracker
import com.android.systemui.statusbar.phone.KeyguardDismissUtil
import com.android.systemui.statusbar.policy.keyguardStateController
@@ -81,10 +83,11 @@ class IssueRecordingUserActionInteractorTest : SysuiTestCase() {
underTest =
IssueRecordingUserActionInteractor(
testDispatcher,
+ IssueRecordingState(userTracker, userFileManager),
KeyguardDismissUtil(
keyguardStateController,
statusBarStateController,
- activityStarter
+ activityStarter,
),
keyguardStateController,
dialogTransitionAnimator,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/IssueRecordingServiceSessionTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/IssueRecordingServiceSessionTest.kt
index a1edfc1dbcd5..a3f81274dfc5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/IssueRecordingServiceSessionTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/recordissue/IssueRecordingServiceSessionTest.kt
@@ -107,7 +107,7 @@ class IssueRecordingServiceSessionTest : SysuiTestCase() {
@Test
fun requestBugreport_afterReceivingShareCommand_withTakeBugreportTrue() {
- issueRecordingState.takeBugreport = true
+ underTest.takeBugReport = true
val uri = mock<Uri>()
underTest.share(0, uri)
@@ -118,7 +118,7 @@ class IssueRecordingServiceSessionTest : SysuiTestCase() {
@Test
fun sharesTracesDirectly_afterReceivingShareCommand_withTakeBugreportFalse() {
- issueRecordingState.takeBugreport = false
+ underTest.takeBugReport = false
val uri = mock<Uri>()
underTest.share(0, uri)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/FakeScreenshotPolicy.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/FakeScreenshotPolicy.kt
deleted file mode 100644
index 28d53c72640f..000000000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/screenshot/FakeScreenshotPolicy.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.screenshot
-
-import com.android.systemui.screenshot.ScreenshotPolicy.DisplayContentInfo
-
-internal class FakeScreenshotPolicy : ScreenshotPolicy {
-
- private val userTypes = mutableMapOf<Int, Boolean>()
- private val contentInfo = mutableMapOf<Int, DisplayContentInfo?>()
-
- fun setManagedProfile(userId: Int, managedUser: Boolean) {
- userTypes[userId] = managedUser
- }
- override suspend fun isManagedProfile(userId: Int): Boolean {
- return userTypes[userId] ?: error("No managedProfile value set for userId $userId")
- }
-
- fun setDisplayContentInfo(userId: Int, contentInfo: DisplayContentInfo) {
- this.contentInfo[userId] = contentInfo
- }
-
- override suspend fun findPrimaryContent(displayId: Int): DisplayContentInfo {
- return contentInfo[displayId] ?: error("No DisplayContentInfo set for displayId $displayId")
- }
-}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
index fb91c78b9041..080f46fd5f48 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
@@ -32,6 +32,7 @@ import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
+import com.google.android.msdl.domain.MSDLPlayer
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
@@ -46,34 +47,26 @@ import org.mockito.Mockito.isNull
import org.mockito.Mockito.never
import org.mockito.Mockito.notNull
import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
@SmallTest
@RunWith(AndroidTestingRunner::class)
class BrightnessSliderControllerTest : SysuiTestCase() {
- @Mock
- private lateinit var brightnessSliderView: BrightnessSliderView
- @Mock
- private lateinit var enforcedAdmin: RestrictedLockUtils.EnforcedAdmin
- @Mock
- private lateinit var mirrorController: BrightnessMirrorController
- @Mock
- private lateinit var mirror: ToggleSlider
- @Mock
- private lateinit var motionEvent: MotionEvent
- @Mock
- private lateinit var listener: ToggleSlider.Listener
- @Mock
- private lateinit var vibratorHelper: VibratorHelper
- @Mock
- private lateinit var activityStarter: ActivityStarter
+ @Mock private lateinit var brightnessSliderView: BrightnessSliderView
+ @Mock private lateinit var enforcedAdmin: RestrictedLockUtils.EnforcedAdmin
+ @Mock private lateinit var mirrorController: BrightnessMirrorController
+ @Mock private lateinit var mirror: ToggleSlider
+ @Mock private lateinit var motionEvent: MotionEvent
+ @Mock private lateinit var listener: ToggleSlider.Listener
+ @Mock private lateinit var vibratorHelper: VibratorHelper
+ @Mock private lateinit var msdlPlayer: MSDLPlayer
+ @Mock private lateinit var activityStarter: ActivityStarter
@Captor
private lateinit var seekBarChangeCaptor: ArgumentCaptor<SeekBar.OnSeekBarChangeListener>
- @Mock
- private lateinit var seekBar: SeekBar
+ @Mock private lateinit var seekBar: SeekBar
private val uiEventLogger = UiEventLoggerFake()
private var mFalsingManager: FalsingManagerFake = FalsingManagerFake()
private val systemClock = FakeSystemClock()
@@ -93,7 +86,7 @@ class BrightnessSliderControllerTest : SysuiTestCase() {
brightnessSliderView,
mFalsingManager,
uiEventLogger,
- SeekbarHapticPlugin(vibratorHelper, systemClock),
+ SeekbarHapticPlugin(vibratorHelper, msdlPlayer, systemClock),
activityStarter,
)
mController.init()
@@ -241,4 +234,4 @@ class BrightnessSliderControllerTest : SysuiTestCase() {
assertThat(uiEventLogger.numLogs()).isEqualTo(1)
assertThat(uiEventLogger.eventId(0)).isEqualTo(event.id)
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt
deleted file mode 100644
index 2ac0ed0efff4..000000000000
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/LockscreenHostedDreamGestureListenerTest.kt
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.shade
-
-import android.os.PowerManager
-import android.view.MotionEvent
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
-import com.android.systemui.classifier.FalsingCollector
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
-import com.android.systemui.plugins.FalsingManager
-import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.power.data.repository.FakePowerRepository
-import com.android.systemui.power.domain.interactor.PowerInteractorFactory
-import com.android.systemui.statusbar.StatusBarState
-import com.android.systemui.util.mockito.whenever
-import com.google.common.truth.Truth
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.TestScope
-import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers
-import org.mockito.Mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-
-@SmallTest
-@OptIn(ExperimentalCoroutinesApi::class)
-@RunWith(AndroidJUnit4::class)
-class LockscreenHostedDreamGestureListenerTest : SysuiTestCase() {
- @Mock private lateinit var falsingManager: FalsingManager
- @Mock private lateinit var falsingCollector: FalsingCollector
- @Mock private lateinit var statusBarStateController: StatusBarStateController
- @Mock private lateinit var shadeLogger: ShadeLogger
- @Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
-
- private val testDispatcher = UnconfinedTestDispatcher()
- private val testScope = TestScope(testDispatcher)
-
- private lateinit var powerRepository: FakePowerRepository
- private lateinit var keyguardRepository: FakeKeyguardRepository
- private lateinit var underTest: LockscreenHostedDreamGestureListener
-
- @Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
-
- powerRepository = FakePowerRepository()
- keyguardRepository = FakeKeyguardRepository()
-
- underTest =
- LockscreenHostedDreamGestureListener(
- falsingManager,
- PowerInteractorFactory.create(
- repository = powerRepository,
- statusBarStateController = statusBarStateController,
- )
- .powerInteractor,
- statusBarStateController,
- primaryBouncerInteractor,
- keyguardRepository,
- shadeLogger,
- )
- whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD)
- whenever(primaryBouncerInteractor.isBouncerShowing()).thenReturn(false)
- }
-
- @Test
- fun testGestureDetector_onSingleTap_whileDreaming() =
- testScope.runTest {
- // GIVEN device dreaming and the dream is hosted in lockscreen
- whenever(statusBarStateController.isDreaming).thenReturn(true)
- keyguardRepository.setIsActiveDreamLockscreenHosted(true)
- testScope.runCurrent()
-
- // GIVEN the falsing manager does NOT think the tap is a false tap
- whenever(falsingManager.isFalseTap(ArgumentMatchers.anyInt())).thenReturn(false)
-
- // WHEN there's a tap
- underTest.onSingleTapUp(upEv)
-
- // THEN wake up device if dreaming
- Truth.assertThat(powerRepository.lastWakeWhy).isNotNull()
- Truth.assertThat(powerRepository.lastWakeReason).isEqualTo(PowerManager.WAKE_REASON_TAP)
- }
-
- @Test
- fun testGestureDetector_onSingleTap_notOnKeyguard() =
- testScope.runTest {
- // GIVEN device dreaming and the dream is hosted in lockscreen
- whenever(statusBarStateController.isDreaming).thenReturn(true)
- keyguardRepository.setIsActiveDreamLockscreenHosted(true)
- testScope.runCurrent()
-
- // GIVEN shade is open
- whenever(statusBarStateController.state).thenReturn(StatusBarState.SHADE)
-
- // GIVEN the falsing manager does NOT think the tap is a false tap
- whenever(falsingManager.isFalseTap(ArgumentMatchers.anyInt())).thenReturn(false)
-
- // WHEN there's a tap
- underTest.onSingleTapUp(upEv)
-
- // THEN the falsing manager never gets a call
- verify(falsingManager, never()).isFalseTap(ArgumentMatchers.anyInt())
- }
-
- @Test
- fun testGestureDetector_onSingleTap_bouncerShown() =
- testScope.runTest {
- // GIVEN device dreaming and the dream is hosted in lockscreen
- whenever(statusBarStateController.isDreaming).thenReturn(true)
- keyguardRepository.setIsActiveDreamLockscreenHosted(true)
- testScope.runCurrent()
-
- // GIVEN bouncer is expanded
- whenever(primaryBouncerInteractor.isBouncerShowing()).thenReturn(true)
-
- // GIVEN the falsing manager does NOT think the tap is a false tap
- whenever(falsingManager.isFalseTap(ArgumentMatchers.anyInt())).thenReturn(false)
-
- // WHEN there's a tap
- underTest.onSingleTapUp(upEv)
-
- // THEN the falsing manager never gets a call
- verify(falsingManager, never()).isFalseTap(ArgumentMatchers.anyInt())
- }
-
- @Test
- fun testGestureDetector_onSingleTap_falsing() =
- testScope.runTest {
- // GIVEN device dreaming and the dream is hosted in lockscreen
- whenever(statusBarStateController.isDreaming).thenReturn(true)
- keyguardRepository.setIsActiveDreamLockscreenHosted(true)
- testScope.runCurrent()
-
- // GIVEN the falsing manager thinks the tap is a false tap
- whenever(falsingManager.isFalseTap(ArgumentMatchers.anyInt())).thenReturn(true)
-
- // WHEN there's a tap
- underTest.onSingleTapUp(upEv)
-
- // THEN the device doesn't wake up
- Truth.assertThat(powerRepository.lastWakeWhy).isNull()
- Truth.assertThat(powerRepository.lastWakeReason).isNull()
- }
-
- @Test
- fun testSingleTap_notDreaming_noFalsingCheck() =
- testScope.runTest {
- // GIVEN device not dreaming with lockscreen hosted dream
- whenever(statusBarStateController.isDreaming).thenReturn(false)
- keyguardRepository.setIsActiveDreamLockscreenHosted(false)
- testScope.runCurrent()
-
- // WHEN there's a tap
- underTest.onSingleTapUp(upEv)
-
- // THEN the falsing manager never gets a call
- verify(falsingManager, never()).isFalseTap(ArgumentMatchers.anyInt())
- }
-}
-
-private val upEv = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/PrivacyDotViewControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/PrivacyDotViewControllerTest.kt
index 663c3418b144..16da3d22f4f7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/PrivacyDotViewControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/PrivacyDotViewControllerTest.kt
@@ -70,14 +70,14 @@ class PrivacyDotViewControllerTest : SysuiTestCase() {
}
private fun createController() =
- PrivacyDotViewController(
+ PrivacyDotViewControllerImpl(
executor,
testScope.backgroundScope,
statusBarStateController,
configurationController,
contentInsetsProvider,
animationScheduler = mock<SystemStatusAnimationScheduler>(),
- shadeInteractor = null
+ shadeInteractor = null,
)
.also { it.setUiExecutor(executor) }
@@ -307,7 +307,7 @@ class PrivacyDotViewControllerTest : SysuiTestCase() {
newTopLeftView,
newTopRightView,
newBottomLeftView,
- newBottomRightView
+ newBottomRightView,
)
assertThat((newBottomRightView.layoutParams as FrameLayout.LayoutParams).gravity)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
index dc9c22f566bf..f1edb417a314 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
@@ -21,6 +21,7 @@ import static android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE;
import static com.android.systemui.log.LogBufferHelperKt.logcatLogBuffer;
import static com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -36,9 +37,11 @@ import static org.mockito.Mockito.when;
import static java.util.Objects.requireNonNull;
+import android.app.Flags;
import android.database.ContentObserver;
import android.os.Handler;
import android.os.RemoteException;
+import android.platform.test.annotations.EnableFlags;
import android.testing.TestableLooper;
import androidx.annotation.NonNull;
@@ -61,6 +64,7 @@ import com.android.systemui.statusbar.notification.collection.inflation.NotifInf
import com.android.systemui.statusbar.notification.collection.inflation.NotifUiAdjustmentProvider;
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection;
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener;
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
@@ -69,6 +73,8 @@ import com.android.systemui.statusbar.notification.collection.provider.SectionSt
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.notification.collection.render.NotifViewBarn;
import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
+import com.android.systemui.statusbar.notification.row.icon.AppIconProvider;
+import com.android.systemui.statusbar.notification.row.icon.NotificationIconStyleProvider;
import com.android.systemui.statusbar.policy.SensitiveNotificationProtectionController;
import com.android.systemui.util.settings.SecureSettings;
@@ -82,10 +88,12 @@ import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.stream.Stream;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -93,6 +101,7 @@ import java.util.Map;
public class PreparationCoordinatorTest extends SysuiTestCase {
private NotifCollectionListener mCollectionListener;
private OnBeforeFinalizeFilterListener mBeforeFilterListener;
+ private OnBeforeTransformGroupsListener mBeforeTransformGroupsListener;
private NotifFilter mUninflatedFilter;
private NotifFilter mInflationErrorFilter;
private NotifInflationErrorManager mErrorManager;
@@ -101,6 +110,8 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
@Captor private ArgumentCaptor<NotifCollectionListener> mCollectionListenerCaptor;
@Captor private ArgumentCaptor<OnBeforeFinalizeFilterListener> mBeforeFilterListenerCaptor;
+ @Captor private ArgumentCaptor<OnBeforeTransformGroupsListener>
+ mBeforeTransformGroupsListenerCaptor;
@Captor private ArgumentCaptor<NotifInflater.Params> mParamsCaptor;
@Mock private NotifSectioner mNotifSectioner;
@@ -108,13 +119,14 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
@Mock private NotifPipeline mNotifPipeline;
@Mock private IStatusBarService mService;
@Mock private BindEventManagerImpl mBindEventManagerImpl;
+ @Mock private AppIconProvider mAppIconProvider;
+ @Mock private NotificationIconStyleProvider mNotificationIconStyleProvider;
@Mock private NotificationLockscreenUserManager mLockscreenUserManager;
@Mock private SensitiveNotificationProtectionController mSensitiveNotifProtectionController;
@Mock private Handler mHandler;
@Mock private SecureSettings mSecureSettings;
@Spy private FakeNotifInflater mNotifInflater = new FakeNotifInflater();
- @Mock
- HighPriorityProvider mHighPriorityProvider;
+ @Mock HighPriorityProvider mHighPriorityProvider;
private SectionStyleProvider mSectionStyleProvider;
@Mock private UserTracker mUserTracker;
@Mock private GroupMembershipManager mGroupMembershipManager;
@@ -126,6 +138,11 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
return new NotificationEntryBuilder().setSection(mNotifSection);
}
+ @NonNull
+ private GroupEntryBuilder getGroupEntryBuilder() {
+ return new GroupEntryBuilder().setSection(mNotifSection);
+ }
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -138,7 +155,7 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
mSectionStyleProvider,
mUserTracker,
mGroupMembershipManager
- );
+ );
mEntry = getNotificationEntryBuilder().setParent(ROOT_ENTRY).build();
mInflationError = new Exception(TEST_MESSAGE);
mErrorManager = new NotifInflationErrorManager();
@@ -153,6 +170,8 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
mAdjustmentProvider,
mService,
mBindEventManagerImpl,
+ mAppIconProvider,
+ mNotificationIconStyleProvider,
TEST_CHILD_BIND_CUTOFF,
TEST_MAX_GROUP_DELAY);
@@ -163,6 +182,15 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
mInflationErrorFilter = filters.get(0);
mUninflatedFilter = filters.get(1);
+ if (android.app.Flags.notificationsRedesignAppIcons()) {
+ verify(mNotifPipeline).addOnBeforeTransformGroupsListener(
+ mBeforeTransformGroupsListenerCaptor.capture());
+ mBeforeTransformGroupsListener = mBeforeTransformGroupsListenerCaptor.getValue();
+ } else {
+ verify(mNotifPipeline, never()).addOnBeforeTransformGroupsListener(
+ mBeforeTransformGroupsListenerCaptor.capture());
+ }
+
verify(mNotifPipeline).addCollectionListener(mCollectionListenerCaptor.capture());
mCollectionListener = mCollectionListenerCaptor.getValue();
@@ -199,6 +227,100 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
}
@Test
+ @EnableFlags(Flags.FLAG_NOTIFICATIONS_REDESIGN_APP_ICONS)
+ public void testPurgesAppIconProviderCache() {
+ // GIVEN a notification list
+ NotificationEntry entry1 = getNotificationEntryBuilder().setPkg("1").build();
+ NotificationEntry entry2 = getNotificationEntryBuilder().setPkg("2").build();
+ NotificationEntry entry2bis = getNotificationEntryBuilder().setPkg("2").build();
+ NotificationEntry entry3 = getNotificationEntryBuilder().setPkg("3").build();
+
+ String groupKey1 = "group1";
+ NotificationEntry summary =
+ getNotificationEntryBuilder()
+ .setPkg(groupKey1)
+ .setGroup(mContext, groupKey1)
+ .setGroupSummary(mContext, true)
+ .build();
+ NotificationEntry child1 = getNotificationEntryBuilder().setGroup(mContext, groupKey1)
+ .setPkg(groupKey1).build();
+ NotificationEntry child2 = getNotificationEntryBuilder().setGroup(mContext, groupKey1)
+ .setPkg(groupKey1).build();
+ GroupEntry groupWithSummaryAndChildren = getGroupEntryBuilder().setKey(groupKey1)
+ .setSummary(summary).addChild(child1).addChild(child2).build();
+
+ String groupKey2 = "group2";
+ NotificationEntry summary2 =
+ getNotificationEntryBuilder()
+ .setPkg(groupKey2)
+ .setGroup(mContext, groupKey2)
+ .setGroupSummary(mContext, true)
+ .build();
+ GroupEntry summaryOnlyGroup = getGroupEntryBuilder().setKey(groupKey2)
+ .setSummary(summary2).build();
+
+ // WHEN onBeforeTransformGroup is called
+ mBeforeTransformGroupsListener.onBeforeTransformGroups(
+ List.of(entry1, entry2, entry2bis, entry3,
+ groupWithSummaryAndChildren, summaryOnlyGroup));
+
+ // THEN purge should be called
+ ArgumentCaptor<Collection<String>> argumentCaptor = ArgumentCaptor.forClass(List.class);
+ verify(mAppIconProvider).purgeCache(argumentCaptor.capture());
+ List<String> actualList = argumentCaptor.getValue().stream().sorted().toList();
+ List<String> expectedList = Stream.of("1", "2", "3", "group1", "group2")
+ .sorted().toList();
+ assertEquals(expectedList, actualList);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_NOTIFICATIONS_REDESIGN_APP_ICONS)
+ public void testPurgesNotificationIconStyleProviderCache() {
+ // GIVEN a notification list
+ NotificationEntry entry1 = getNotificationEntryBuilder().setPkg("1").build();
+ NotificationEntry entry2 = getNotificationEntryBuilder().setPkg("2").build();
+ NotificationEntry entry2bis = getNotificationEntryBuilder().setPkg("2").build();
+ NotificationEntry entry3 = getNotificationEntryBuilder().setPkg("3").build();
+
+ String groupKey1 = "group1";
+ NotificationEntry summary =
+ getNotificationEntryBuilder()
+ .setPkg(groupKey1)
+ .setGroup(mContext, groupKey1)
+ .setGroupSummary(mContext, true)
+ .build();
+ NotificationEntry child1 = getNotificationEntryBuilder().setGroup(mContext, groupKey1)
+ .setPkg(groupKey1).build();
+ NotificationEntry child2 = getNotificationEntryBuilder().setGroup(mContext, groupKey1)
+ .setPkg(groupKey1).build();
+ GroupEntry groupWithSummaryAndChildren = getGroupEntryBuilder().setKey(groupKey1)
+ .setSummary(summary).addChild(child1).addChild(child2).build();
+
+ String groupKey2 = "group2";
+ NotificationEntry summary2 =
+ getNotificationEntryBuilder()
+ .setPkg(groupKey2)
+ .setGroup(mContext, groupKey2)
+ .setGroupSummary(mContext, true)
+ .build();
+ GroupEntry summaryOnlyGroup = getGroupEntryBuilder().setKey(groupKey2)
+ .setSummary(summary2).build();
+
+ // WHEN onBeforeTransformGroup is called
+ mBeforeTransformGroupsListener.onBeforeTransformGroups(
+ List.of(entry1, entry2, entry2bis, entry3,
+ groupWithSummaryAndChildren, summaryOnlyGroup));
+
+ // THEN purge should be called
+ ArgumentCaptor<Collection<String>> argumentCaptor = ArgumentCaptor.forClass(List.class);
+ verify(mNotificationIconStyleProvider).purgeCache(argumentCaptor.capture());
+ List<String> actualList = argumentCaptor.getValue().stream().sorted().toList();
+ List<String> expectedList = Stream.of("1", "2", "3", "group1", "group2")
+ .sorted().toList();
+ assertEquals(expectedList, actualList);
+ }
+
+ @Test
public void testInflatesNewNotification() {
// WHEN there is a new notification
mCollectionListener.onEntryInit(mEntry);
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
index aed9af6df454..406ca0585dd9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java
@@ -33,6 +33,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.keyguard.logging.KeyguardUpdateMonitorLogger;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
@@ -67,6 +68,8 @@ public class KeyguardStateControllerTest extends SysuiTestCase {
@Mock
private Lazy<KeyguardUnlockAnimationController> mKeyguardUnlockAnimationControllerLazy;
@Mock
+ private Lazy<KeyguardInteractor> mKeyguardInteractorLazy;
+ @Mock
private SelectedUserInteractor mSelectedUserInteractor;
@Mock
private KeyguardUpdateMonitorLogger mLogger;
@@ -86,6 +89,7 @@ public class KeyguardStateControllerTest extends SysuiTestCase {
mKeyguardUnlockAnimationControllerLazy,
mLogger,
mDumpManager,
+ mKeyguardInteractorLazy,
mFeatureFlags,
mSelectedUserInteractor);
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractorTest.kt
new file mode 100644
index 000000000000..7d5559933cd8
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractorTest.kt
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2024 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.volume.dialog.ringer.domain
+
+import android.media.AudioManager.RINGER_MODE_NORMAL
+import android.media.AudioManager.RINGER_MODE_SILENT
+import android.media.AudioManager.RINGER_MODE_VIBRATE
+import android.media.AudioManager.STREAM_RING
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.settingslib.volume.shared.model.RingerMode
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.plugins.fakeVolumeDialogController
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper
+class VolumeDialogRingerInteractorTest : SysuiTestCase() {
+
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+ private val controller = kosmos.fakeVolumeDialogController
+
+ private lateinit var underTest: VolumeDialogRingerInteractor
+
+ @Before
+ fun setUp() {
+ underTest = kosmos.volumeDialogRingerInteractor
+ controller.setStreamVolume(STREAM_RING, 50)
+ }
+
+ @Test
+ fun setRingerMode_normal() =
+ testScope.runTest {
+ runCurrent()
+ val ringerModel by collectLastValue(underTest.ringerModel)
+
+ underTest.setRingerMode(RingerMode(RINGER_MODE_NORMAL))
+ controller.getState()
+ runCurrent()
+
+ assertThat(ringerModel).isNotNull()
+ assertThat(ringerModel?.currentRingerMode).isEqualTo(RingerMode(RINGER_MODE_NORMAL))
+ }
+
+ @Test
+ fun setRingerMode_silent() =
+ testScope.runTest {
+ runCurrent()
+ val ringerModel by collectLastValue(underTest.ringerModel)
+
+ underTest.setRingerMode(RingerMode(RINGER_MODE_SILENT))
+ controller.getState()
+ runCurrent()
+
+ assertThat(ringerModel).isNotNull()
+ assertThat(ringerModel?.currentRingerMode).isEqualTo(RingerMode(RINGER_MODE_SILENT))
+ }
+
+ @Test
+ fun setRingerMode_vibrate() =
+ testScope.runTest {
+ runCurrent()
+ val ringerModel by collectLastValue(underTest.ringerModel)
+
+ underTest.setRingerMode(RingerMode(RINGER_MODE_VIBRATE))
+ controller.getState()
+ runCurrent()
+
+ assertThat(ringerModel).isNotNull()
+ assertThat(ringerModel?.currentRingerMode).isEqualTo(RingerMode(RINGER_MODE_VIBRATE))
+ }
+}
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index cdf15ca83dd9..c494e8525e0f 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -3745,6 +3745,10 @@
use. The helper shows shortcuts in categories, which can be collapsed or expanded.
[CHAR LIMIT=NONE] -->
<string name="shortcut_helper_content_description_drag_handle">Drag handle</string>
+ <!-- Label on the keyboard settings button in keyboard shortcut helper, that allows user to
+ open keyboard settings while in shortcut helper. The helper is a component that shows the
+ user which keyboard shortcuts they can use. [CHAR LIMIT=NONE] -->
+ <string name="shortcut_helper_keyboard_settings_buttons_label">Keyboard Settings</string>
<!-- Keyboard touchpad tutorial scheduler-->
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 83ab5245bc31..b3ea75d00917 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -2368,7 +2368,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
// Take a guess at initial SIM state, battery status and PLMN until we get an update
- mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, /* level= */ 100, /* plugged= */
+ mBatteryStatus = new BatteryStatus(BATTERY_STATUS_UNKNOWN, /* level= */ -1, /* plugged= */
0, CHARGING_POLICY_DEFAULT, /* maxChargingWattage= */0, /* present= */true);
// Watch for interesting updates
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 8ae11abab473..811b47d57c1d 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -43,7 +43,7 @@ import com.android.systemui.dagger.SysUIComponent;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.process.ProcessWrapper;
import com.android.systemui.res.R;
-import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.phone.ConfigurationForwarder;
import com.android.systemui.util.NotificationChannels;
import java.lang.reflect.InvocationTargetException;
@@ -454,13 +454,13 @@ public class SystemUIApplication extends Application implements
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
if (mServicesStarted) {
- ConfigurationController configController = mSysUIComponent.getConfigurationController();
+ ConfigurationForwarder configForwarder = mSysUIComponent.getConfigurationForwarder();
if (Trace.isEnabled()) {
Trace.traceBegin(
Trace.TRACE_TAG_APP,
- configController.getClass().getSimpleName() + ".onConfigurationChanged()");
+ configForwarder.getClass().getSimpleName() + ".onConfigurationChanged()");
}
- configController.onConfigurationChanged(newConfig);
+ configForwarder.onConfigurationChanged(newConfig);
Trace.endSection();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/startable/BouncerStartable.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/startable/BouncerStartable.kt
new file mode 100644
index 000000000000..e3cf88c94afd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/startable/BouncerStartable.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2024 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.bouncer.domain.startable
+
+import com.android.app.tracing.coroutines.launchTraced
+import com.android.systemui.CoreStartable
+import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.domain.interactor.KeyguardMediaKeyInteractor
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+
+/** Starts interactors needed for the compose bouncer to work as expected. */
+@SysUISingleton
+class BouncerStartable
+@Inject
+constructor(
+ private val keyguardMediaKeyInteractor: dagger.Lazy<KeyguardMediaKeyInteractor>,
+ @Application private val scope: CoroutineScope,
+) : CoreStartable {
+ override fun start() {
+ if (!ComposeBouncerFlags.isEnabled) return
+
+ scope.launchTraced("KeyguardMediaKeyInteractor#start") {
+ keyguardMediaKeyInteractor.get().activate()
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt b/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt
index 7647cf6081bf..47570a53d663 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/shared/flag/ComposeBouncerFlags.kt
@@ -43,17 +43,25 @@ object ComposeBouncerFlags {
fun isUnexpectedlyInLegacyMode() =
RefactorFlagUtils.isUnexpectedlyInLegacyMode(
isEnabled,
- "SceneContainerFlag || ComposeBouncerFlag"
+ "SceneContainerFlag || ComposeBouncerFlag",
)
/**
+ * Called to ensure code is only run when the flag is disabled. This will throw an exception if
+ * the flag is enabled to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ fun assertInLegacyMode() =
+ RefactorFlagUtils.assertInLegacyMode(isEnabled, "SceneContainerFlag || ComposeBouncerFlag")
+
+ /**
* Returns `true` if only compose bouncer is enabled and scene container framework is not
* enabled.
*/
@Deprecated(
"Avoid using this, this is meant to be used only by the glue code " +
"that includes compose bouncer in legacy keyguard.",
- replaceWith = ReplaceWith("isComposeBouncerOrSceneContainerEnabled()")
+ replaceWith = ReplaceWith("isComposeBouncerOrSceneContainerEnabled()"),
)
fun isOnlyComposeBouncerEnabled(): Boolean {
return !SceneContainerFlag.isEnabled && Flags.composeBouncer()
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt
index 148b9ea61e2c..1bcc1eeb4f12 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt
@@ -17,6 +17,7 @@
package com.android.systemui.bouncer.ui.viewmodel
import android.annotation.StringRes
+import androidx.compose.ui.input.key.KeyEventType
import com.android.systemui.authentication.domain.interactor.AuthenticationResult
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
@@ -122,6 +123,13 @@ sealed class AuthMethodBouncerViewModel(
/** Invoked after a successful authentication. */
protected open fun onSuccessfulAuthentication() = Unit
+ /**
+ * Invoked for any key events on the bouncer.
+ *
+ * @return whether the event was consumed by this method and should not be propagated further.
+ */
+ open fun onKeyEvent(type: KeyEventType, keyCode: Int): Boolean = false
+
/** Perform authentication result haptics */
private fun performAuthenticationHapticFeedback(result: AuthenticationResult) {
if (result == AuthenticationResult.SKIPPED) return
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModel.kt
index 5f973917440c..67d312e17069 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneContentViewModel.kt
@@ -34,6 +34,7 @@ import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.common.shared.model.Text
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.keyguard.domain.interactor.KeyguardMediaKeyInteractor
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.user.ui.viewmodel.UserSwitcherViewModel
import dagger.assisted.AssistedFactory
@@ -63,6 +64,7 @@ constructor(
private val patternViewModelFactory: PatternBouncerViewModel.Factory,
private val passwordViewModelFactory: PasswordBouncerViewModel.Factory,
private val bouncerHapticPlayer: BouncerHapticPlayer,
+ private val keyguardMediaKeyInteractor: KeyguardMediaKeyInteractor,
) : ExclusiveActivatable() {
private val _selectedUserImage = MutableStateFlow<Bitmap?>(null)
val selectedUserImage: StateFlow<Bitmap?> = _selectedUserImage.asStateFlow()
@@ -337,10 +339,9 @@ constructor(
* @return `true` when the [KeyEvent] was consumed as user input on bouncer; `false` otherwise.
*/
fun onKeyEvent(keyEvent: KeyEvent): Boolean {
- return (authMethodViewModel.value as? PinBouncerViewModel)?.onKeyEvent(
- keyEvent.type,
- keyEvent.nativeKeyEvent.keyCode,
- ) ?: false
+ if (keyguardMediaKeyInteractor.processMediaKeyEvent(keyEvent.nativeKeyEvent)) return true
+ return authMethodViewModel.value?.onKeyEvent(keyEvent.type, keyEvent.nativeKeyEvent.keyCode)
+ ?: false
}
data class DialogViewModel(
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt
index 1427d787ea86..b8c6ab3783d5 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt
@@ -16,9 +16,12 @@
package com.android.systemui.bouncer.ui.viewmodel
+import android.view.KeyEvent
import androidx.annotation.VisibleForTesting
+import androidx.compose.ui.input.key.KeyEventType
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
+import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags
import com.android.systemui.inputmethod.domain.interactor.InputMethodInteractor
import com.android.systemui.res.R
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
@@ -150,6 +153,17 @@ constructor(
return _password.value.toCharArray().toList()
}
+ override fun onKeyEvent(type: KeyEventType, keyCode: Int): Boolean {
+ // Ignore SPACE as a confirm key to allow the space character within passwords.
+ val isKeyboardEnterKey =
+ KeyEvent.isConfirmKey(keyCode) &&
+ keyCode != KeyEvent.KEYCODE_SPACE &&
+ type == KeyEventType.KeyUp
+ // consume confirm key events while on the bouncer. This prevents it from propagating
+ // and avoids other parent elements from receiving it.
+ return isKeyboardEnterKey && ComposeBouncerFlags.isOnlyComposeBouncerEnabled()
+ }
+
override fun onSuccessfulAuthentication() {
wasSuccessfullyAuthenticated = true
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
index 0cb4260e4d7f..5c8a9a692baf 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
@@ -251,7 +251,7 @@ constructor(
*
* @return `true` when the [KeyEvent] was consumed as user input on bouncer; `false` otherwise.
*/
- fun onKeyEvent(type: KeyEventType, keyCode: Int): Boolean {
+ override fun onKeyEvent(type: KeyEventType, keyCode: Int): Boolean {
return when (type) {
KeyEventType.KeyUp -> {
if (isConfirmKey(keyCode)) {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index 3fe6669de556..17f1961e662c 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -29,6 +29,7 @@ import com.android.systemui.people.PeopleProvider;
import com.android.systemui.startable.Dependencies;
import com.android.systemui.statusbar.NotificationInsetsModule;
import com.android.systemui.statusbar.QsFrameTranslateModule;
+import com.android.systemui.statusbar.phone.ConfigurationForwarder;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.bubbles.Bubbles;
@@ -125,13 +126,20 @@ public interface SysUIComponent {
BootCompleteCacheImpl provideBootCacheImpl();
/**
- * Creates a ContextComponentHelper.
+ * Creates a ConfigurationController.
*/
@SysUISingleton
@GlobalConfig
ConfigurationController getConfigurationController();
/**
+ * Creates a ConfigurationForwarder.
+ */
+ @SysUISingleton
+ @GlobalConfig
+ ConfigurationForwarder getConfigurationForwarder();
+
+ /**
* Creates a ContextComponentHelper.
*/
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
index 0de919deb943..6fb6236a4ed3 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUICoreStartableModule.kt
@@ -23,6 +23,7 @@ import com.android.systemui.SliceBroadcastRelayHandler
import com.android.systemui.accessibility.Magnification
import com.android.systemui.back.domain.interactor.BackActionInteractor
import com.android.systemui.biometrics.BiometricNotificationService
+import com.android.systemui.bouncer.domain.startable.BouncerStartable
import com.android.systemui.clipboardoverlay.ClipboardListener
import com.android.systemui.controls.dagger.StartControlsStartableModule
import com.android.systemui.dagger.qualifiers.PerUser
@@ -304,6 +305,11 @@ abstract class SystemUICoreStartableModule {
@Binds
@IntoMap
+ @ClassKey(BouncerStartable::class)
+ abstract fun bindBouncerStartable(impl: BouncerStartable): CoreStartable
+
+ @Binds
+ @IntoMap
@ClassKey(KeyguardDismissBinder::class)
abstract fun bindKeyguardDismissBinder(impl: KeyguardDismissBinder): CoreStartable
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 21922ff22afe..12718e8bd119 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -17,6 +17,7 @@
package com.android.systemui.doze;
import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
+import static android.hardware.biometrics.Flags.screenOffUnlockUdfps;
import static com.android.systemui.doze.DozeLog.REASON_SENSOR_QUICK_PICKUP;
import static com.android.systemui.doze.DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS;
@@ -248,8 +249,8 @@ public class DozeSensors {
true /* touchscreen */,
false /* ignoresSetting */,
dozeParameters.longPressUsesProx(),
- false /* immediatelyReRegister */,
- true /* requiresAod */
+ screenOffUnlockUdfps() /* immediatelyReRegister */,
+ !screenOffUnlockUdfps() /* requiresAod */
),
new PluginSensor(
new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY),
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 95cd9eb4ae4b..61832875dc2e 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -165,7 +165,7 @@ object Flags {
val QS_USER_DETAIL_SHORTCUT =
resourceBooleanFlag(
R.bool.flag_lockscreen_qs_user_detail_shortcut,
- "qs_user_detail_shortcut"
+ "qs_user_detail_shortcut",
)
// TODO(b/254512383): Tracking Bug
@@ -365,11 +365,6 @@ object Flags {
val ZJ_285570694_LOCKSCREEN_TRANSITION_FROM_AOD =
releasedFlag("zj_285570694_lockscreen_transition_from_aod")
- // 3000 - dream
- // TODO(b/285059790) : Tracking Bug
- @JvmField
- val LOCKSCREEN_WALLPAPER_DREAM_ENABLED = unreleasedFlag("enable_lockscreen_wallpaper_dream")
-
// TODO(b/283447257): Tracking bug
@JvmField
val BIGPICTURE_NOTIFICATION_LAZY_LOADING =
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekbarHapticPlugin.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekbarHapticPlugin.kt
index 932e5af6244b..cc77f68a801e 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekbarHapticPlugin.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/SeekbarHapticPlugin.kt
@@ -22,6 +22,7 @@ import android.widget.SeekBar
import androidx.annotation.VisibleForTesting
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.util.time.SystemClock
+import com.google.android.msdl.domain.MSDLPlayer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
@@ -39,6 +40,7 @@ class SeekbarHapticPlugin
@JvmOverloads
constructor(
vibratorHelper: VibratorHelper,
+ msdlPlayer: MSDLPlayer,
systemClock: SystemClock,
sliderHapticFeedbackConfig: SliderHapticFeedbackConfig = SliderHapticFeedbackConfig(),
private val sliderTrackerConfig: SeekableSliderTrackerConfig = SeekableSliderTrackerConfig(),
@@ -63,6 +65,7 @@ constructor(
private val sliderHapticFeedbackProvider =
SliderHapticFeedbackProvider(
vibratorHelper,
+ msdlPlayer,
dragVelocityProvider,
sliderHapticFeedbackConfig,
systemClock,
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProvider.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProvider.kt
index 06428b77f759..bc4f531b8b81 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/SliderHapticFeedbackProvider.kt
@@ -22,7 +22,11 @@ import android.view.VelocityTracker
import android.view.animation.AccelerateInterpolator
import androidx.annotation.FloatRange
import androidx.annotation.VisibleForTesting
+import com.android.systemui.Flags
import com.android.systemui.statusbar.VibratorHelper
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.android.msdl.domain.InteractionProperties
+import com.google.android.msdl.domain.MSDLPlayer
import kotlin.math.abs
import kotlin.math.min
import kotlin.math.pow
@@ -38,6 +42,7 @@ import kotlin.math.pow
*/
class SliderHapticFeedbackProvider(
private val vibratorHelper: VibratorHelper,
+ private val msdlPlayer: MSDLPlayer,
private val velocityProvider: SliderDragVelocityProvider,
private val config: SliderHapticFeedbackConfig = SliderHapticFeedbackConfig(),
private val clock: com.android.systemui.util.time.SystemClock,
@@ -67,11 +72,20 @@ class SliderHapticFeedbackProvider(
*/
private fun vibrateOnEdgeCollision(absoluteVelocity: Float) {
val powerScale = scaleOnEdgeCollision(absoluteVelocity)
- val vibration =
- VibrationEffect.startComposition()
- .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, powerScale)
- .compose()
- vibratorHelper.vibrate(vibration, VIBRATION_ATTRIBUTES_PIPELINING)
+ if (Flags.msdlFeedback()) {
+ val properties =
+ InteractionProperties.DynamicVibrationScale(
+ powerScale,
+ VIBRATION_ATTRIBUTES_PIPELINING,
+ )
+ msdlPlayer.playToken(MSDLToken.DRAG_THRESHOLD_INDICATOR_LIMIT, properties)
+ } else {
+ val vibration =
+ VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK, powerScale)
+ .compose()
+ vibratorHelper.vibrate(vibration, VIBRATION_ATTRIBUTES_PIPELINING)
+ }
}
/**
@@ -112,16 +126,26 @@ class SliderHapticFeedbackProvider(
val powerScale = scaleOnDragTexture(absoluteVelocity, normalizedSliderProgress)
- // Trigger the vibration composition
- val composition = VibrationEffect.startComposition()
- repeat(config.numberOfLowTicks) {
- composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, powerScale)
- }
- vibratorHelper.vibrate(composition.compose(), VIBRATION_ATTRIBUTES_PIPELINING)
+ // Deliver haptic feedback
+ performContinuousSliderDragVibration(powerScale)
dragTextureLastTime = currentTime
dragTextureLastProgress = normalizedSliderProgress
}
+ private fun performContinuousSliderDragVibration(scale: Float) {
+ if (Flags.msdlFeedback()) {
+ val properties =
+ InteractionProperties.DynamicVibrationScale(scale, VIBRATION_ATTRIBUTES_PIPELINING)
+ msdlPlayer.playToken(MSDLToken.DRAG_INDICATOR_CONTINUOUS, properties)
+ } else {
+ val composition = VibrationEffect.startComposition()
+ repeat(config.numberOfLowTicks) {
+ composition.addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK, scale)
+ }
+ vibratorHelper.vibrate(composition.compose(), VIBRATION_ATTRIBUTES_PIPELINING)
+ }
+ }
+
/**
* Get the scale of the drag texture vibration.
*
diff --git a/packages/SystemUI/src/com/android/systemui/haptics/slider/compose/ui/SliderHapticsViewModel.kt b/packages/SystemUI/src/com/android/systemui/haptics/slider/compose/ui/SliderHapticsViewModel.kt
index 1dbcb3dfe399..de242597f463 100644
--- a/packages/SystemUI/src/com/android/systemui/haptics/slider/compose/ui/SliderHapticsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/haptics/slider/compose/ui/SliderHapticsViewModel.kt
@@ -33,6 +33,7 @@ import com.android.systemui.haptics.slider.SliderStateTracker
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.util.time.SystemClock
+import com.google.android.msdl.domain.MSDLPlayer
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@@ -50,6 +51,7 @@ constructor(
@Assisted private val sliderHapticFeedbackConfig: SliderHapticFeedbackConfig,
@Assisted private val sliderTrackerConfig: SeekableSliderTrackerConfig,
vibratorHelper: VibratorHelper,
+ msdlPlayer: MSDLPlayer,
systemClock: SystemClock,
) : ExclusiveActivatable() {
@@ -78,6 +80,7 @@ constructor(
private val sliderHapticFeedbackProvider =
SliderHapticFeedbackProvider(
vibratorHelper,
+ msdlPlayer,
dragVelocityProvider,
sliderHapticFeedbackConfig,
systemClock,
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
index 3c8bb09ddc09..5cade686ae09 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutHelper.kt
@@ -16,10 +16,7 @@
package com.android.systemui.keyboard.shortcut.ui.composable
-import android.content.Context
-import android.content.pm.PackageManager.NameNotFoundException
import android.graphics.drawable.Icon
-import android.util.Log
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.Image
@@ -55,12 +52,8 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.OpenInNew
-import androidx.compose.material.icons.filled.Apps
import androidx.compose.material.icons.filled.ExpandMore
-import androidx.compose.material.icons.filled.Keyboard
import androidx.compose.material.icons.filled.Search
-import androidx.compose.material.icons.filled.Tv
-import androidx.compose.material.icons.filled.VerticalSplit
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
@@ -111,16 +104,15 @@ import androidx.compose.ui.util.fastForEachIndexed
import com.android.compose.modifiers.thenIf
import com.android.compose.ui.graphics.painter.rememberDrawablePainter
import com.android.systemui.keyboard.shortcut.shared.model.Shortcut as ShortcutModel
-import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategory
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCommand
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutIcon
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutSubCategory
import com.android.systemui.keyboard.shortcut.ui.model.IconSource
+import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCategoryUi
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutsUiState
import com.android.systemui.res.R
-import com.android.systemui.statusbar.phone.CentralSurfaces
@Composable
fun ShortcutHelper(
@@ -187,7 +179,7 @@ private fun ActiveShortcutHelper(
private fun ShortcutHelperSinglePane(
searchQuery: String,
onSearchQueryChanged: (String) -> Unit,
- categories: List<ShortcutCategory>,
+ categories: List<ShortcutCategoryUi>,
selectedCategoryType: ShortcutCategoryType?,
onCategorySelected: (ShortcutCategoryType?) -> Unit,
onKeyboardSettingsClicked: () -> Unit,
@@ -228,7 +220,7 @@ private fun ShortcutHelperSinglePane(
@Composable
private fun CategoriesPanelSinglePane(
searchQuery: String,
- categories: List<ShortcutCategory>,
+ categories: List<ShortcutCategoryUi>,
selectedCategoryType: ShortcutCategoryType?,
onCategorySelected: (ShortcutCategoryType?) -> Unit,
) {
@@ -267,7 +259,7 @@ private fun CategoriesPanelSinglePane(
@Composable
private fun CategoryItemSinglePane(
searchQuery: String,
- category: ShortcutCategory,
+ category: ShortcutCategoryUi,
isExpanded: Boolean,
onClick: () -> Unit,
shape: Shape,
@@ -278,9 +270,9 @@ private fun CategoryItemSinglePane(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth().heightIn(min = 88.dp).padding(horizontal = 16.dp),
) {
- ShortcutCategoryIcon(modifier = Modifier.size(24.dp), source = category.icon)
+ ShortcutCategoryIcon(modifier = Modifier.size(24.dp), source = category.iconSource)
Spacer(modifier = Modifier.width(16.dp))
- Text(category.label(LocalContext.current))
+ Text(category.label)
Spacer(modifier = Modifier.weight(1f))
RotatingExpandCollapseIcon(isExpanded)
}
@@ -291,23 +283,6 @@ private fun CategoryItemSinglePane(
}
}
-private val ShortcutCategory.icon: IconSource
- @Composable
- get() =
- when (type) {
- ShortcutCategoryType.System -> IconSource(imageVector = Icons.Default.Tv)
- ShortcutCategoryType.MultiTasking ->
- IconSource(imageVector = Icons.Default.VerticalSplit)
- ShortcutCategoryType.InputMethodEditor ->
- IconSource(imageVector = Icons.Default.Keyboard)
- ShortcutCategoryType.AppCategories -> IconSource(imageVector = Icons.Default.Apps)
- is ShortcutCategoryType.CurrentApp -> {
- val context = LocalContext.current
- val iconDrawable = context.packageManager.getApplicationIcon(type.packageName)
- IconSource(painter = rememberDrawablePainter(drawable = iconDrawable))
- }
- }
-
@Composable
fun ShortcutCategoryIcon(
source: IconSource,
@@ -322,37 +297,6 @@ fun ShortcutCategoryIcon(
}
}
-private fun ShortcutCategory.label(context: Context): String =
- when (type) {
- ShortcutCategoryType.System -> context.getString(R.string.shortcut_helper_category_system)
- ShortcutCategoryType.MultiTasking ->
- context.getString(R.string.shortcut_helper_category_multitasking)
- ShortcutCategoryType.InputMethodEditor ->
- context.getString(R.string.shortcut_helper_category_input)
- ShortcutCategoryType.AppCategories ->
- context.getString(R.string.shortcut_helper_category_app_shortcuts)
- is ShortcutCategoryType.CurrentApp -> getApplicationLabelForCurrentApp(type, context)
- }
-
-private fun getApplicationLabelForCurrentApp(
- type: ShortcutCategoryType.CurrentApp,
- context: Context,
-): String {
- val packageManagerForUser = CentralSurfaces.getPackageManagerForUser(context, context.userId)
- return try {
- val currentAppInfo =
- packageManagerForUser.getApplicationInfoAsUser(
- type.packageName,
- /* flags = */ 0,
- context.userId,
- )
- packageManagerForUser.getApplicationLabel(currentAppInfo).toString()
- } catch (e: NameNotFoundException) {
- Log.wtf(ShortcutHelper.TAG, "Couldn't find app info by package name ${type.packageName}")
- context.getString(R.string.shortcut_helper_category_current_app_shortcuts)
- }
-}
-
@Composable
private fun RotatingExpandCollapseIcon(isExpanded: Boolean) {
val expandIconRotationDegrees by
@@ -384,7 +328,7 @@ private fun RotatingExpandCollapseIcon(isExpanded: Boolean) {
}
@Composable
-private fun ShortcutCategoryDetailsSinglePane(searchQuery: String, category: ShortcutCategory) {
+private fun ShortcutCategoryDetailsSinglePane(searchQuery: String, category: ShortcutCategoryUi) {
Column(Modifier.padding(horizontal = 16.dp)) {
category.subCategories.fastForEach { subCategory ->
ShortcutSubCategorySinglePane(searchQuery, subCategory)
@@ -409,7 +353,7 @@ private fun ShortcutHelperTwoPane(
searchQuery: String,
onSearchQueryChanged: (String) -> Unit,
modifier: Modifier = Modifier,
- categories: List<ShortcutCategory>,
+ categories: List<ShortcutCategoryUi>,
selectedCategoryType: ShortcutCategoryType?,
onCategorySelected: (ShortcutCategoryType?) -> Unit,
onKeyboardSettingsClicked: () -> Unit,
@@ -434,7 +378,7 @@ private fun ShortcutHelperTwoPane(
}
@Composable
-private fun EndSidePanel(searchQuery: String, modifier: Modifier, category: ShortcutCategory?) {
+private fun EndSidePanel(searchQuery: String, modifier: Modifier, category: ShortcutCategoryUi?) {
val listState = rememberLazyListState()
LaunchedEffect(key1 = category) { if (category != null) listState.animateScrollToItem(0) }
if (category == null) {
@@ -670,10 +614,10 @@ private fun textWithHighlightedSearchQuery(text: String, searchValue: String) =
private fun StartSidePanel(
onSearchQueryChanged: (String) -> Unit,
modifier: Modifier,
- categories: List<ShortcutCategory>,
+ categories: List<ShortcutCategoryUi>,
onKeyboardSettingsClicked: () -> Unit,
selectedCategory: ShortcutCategoryType?,
- onCategoryClicked: (ShortcutCategory) -> Unit,
+ onCategoryClicked: (ShortcutCategoryUi) -> Unit,
) {
Column(modifier) {
ShortcutsSearchBar(onSearchQueryChanged)
@@ -690,15 +634,15 @@ private fun StartSidePanel(
@Composable
private fun CategoriesPanelTwoPane(
- categories: List<ShortcutCategory>,
+ categories: List<ShortcutCategoryUi>,
selectedCategory: ShortcutCategoryType?,
- onCategoryClicked: (ShortcutCategory) -> Unit,
+ onCategoryClicked: (ShortcutCategoryUi) -> Unit,
) {
Column {
categories.fastForEach {
CategoryItemTwoPane(
- label = it.label(LocalContext.current),
- iconSource = it.icon,
+ label = it.label,
+ iconSource = it.iconSource,
selected = selectedCategory == it.type,
onClick = { onCategoryClicked(it) },
)
@@ -833,7 +777,7 @@ private fun KeyboardSettings(horizontalPadding: Dp, verticalPadding: Dp, onClick
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
- "Keyboard Settings",
+ stringResource(id = R.string.shortcut_helper_keyboard_settings_buttons_label),
color = MaterialTheme.colorScheme.onSurfaceVariant,
fontSize = 16.sp,
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutCategoryUi.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutCategoryUi.kt
new file mode 100644
index 000000000000..f5d478b5855d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutCategoryUi.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 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.keyboard.shortcut.ui.model
+
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategory
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType
+import com.android.systemui.keyboard.shortcut.shared.model.ShortcutSubCategory
+
+data class ShortcutCategoryUi(
+ val label: String,
+ val iconSource: IconSource,
+ val type: ShortcutCategoryType,
+ val subCategories: List<ShortcutSubCategory>,
+) {
+ constructor(
+ label: String,
+ iconSource: IconSource,
+ shortcutCategory: ShortcutCategory,
+ ) : this(label, iconSource, shortcutCategory.type, shortcutCategory.subCategories)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutsUiState.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutsUiState.kt
index d2122b3f173a..8f23261c3ef4 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutsUiState.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutsUiState.kt
@@ -16,14 +16,13 @@
package com.android.systemui.keyboard.shortcut.ui.model
-import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategory
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType
sealed interface ShortcutsUiState {
data class Active(
val searchQuery: String,
- val shortcutCategories: List<ShortcutCategory>,
+ val shortcutCategories: List<ShortcutCategoryUi>,
val defaultSelectedCategory: ShortcutCategoryType?,
) : ShortcutsUiState
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt
index 04aa04d1f2af..20d09ede39e3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModel.kt
@@ -17,6 +17,15 @@
package com.android.systemui.keyboard.shortcut.ui.viewmodel
import android.app.role.RoleManager
+import android.content.pm.PackageManager.NameNotFoundException
+import android.util.Log
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Android
+import androidx.compose.material.icons.filled.Apps
+import androidx.compose.material.icons.filled.Keyboard
+import androidx.compose.material.icons.filled.Tv
+import androidx.compose.material.icons.filled.VerticalSplit
+import com.android.compose.ui.graphics.painter.DrawablePainter
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.keyboard.shortcut.domain.interactor.ShortcutHelperCategoriesInteractor
import com.android.systemui.keyboard.shortcut.domain.interactor.ShortcutHelperStateInteractor
@@ -25,7 +34,10 @@ import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategory
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType.CurrentApp
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutSubCategory
+import com.android.systemui.keyboard.shortcut.ui.model.IconSource
+import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCategoryUi
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutsUiState
+import com.android.systemui.res.R
import com.android.systemui.settings.UserTracker
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -51,6 +63,7 @@ constructor(
) {
private val searchQuery = MutableStateFlow("")
+ private val userContext = userTracker.createCurrentUserContext(userTracker.userContext)
val shouldShow =
categoriesInteractor.shortcutCategories
@@ -68,9 +81,10 @@ constructor(
val categoriesWithLauncherExcluded = excludeLauncherApp(categories)
val filteredCategories =
filterCategoriesBySearchQuery(query, categoriesWithLauncherExcluded)
+ val shortcutCategoriesUi = convertCategoriesModelToUiModel(filteredCategories)
ShortcutsUiState.Active(
searchQuery = query,
- shortcutCategories = filteredCategories,
+ shortcutCategories = shortcutCategoriesUi,
defaultSelectedCategory = getDefaultSelectedCategory(filteredCategories),
)
}
@@ -78,9 +92,73 @@ constructor(
.stateIn(
scope = backgroundScope,
started = SharingStarted.Lazily,
- initialValue = ShortcutsUiState.Inactive
+ initialValue = ShortcutsUiState.Inactive,
)
+ private fun convertCategoriesModelToUiModel(
+ categories: List<ShortcutCategory>
+ ): List<ShortcutCategoryUi> {
+ return categories.map { category ->
+ ShortcutCategoryUi(
+ label = getShortcutCategoryLabel(category.type),
+ iconSource = getShortcutCategoryIcon(category.type),
+ shortcutCategory = category,
+ )
+ }
+ }
+
+ private fun getShortcutCategoryIcon(type: ShortcutCategoryType): IconSource {
+ return when (type) {
+ ShortcutCategoryType.System -> IconSource(imageVector = Icons.Default.Tv)
+ ShortcutCategoryType.MultiTasking ->
+ IconSource(imageVector = Icons.Default.VerticalSplit)
+ ShortcutCategoryType.InputMethodEditor ->
+ IconSource(imageVector = Icons.Default.Keyboard)
+ ShortcutCategoryType.AppCategories -> IconSource(imageVector = Icons.Default.Apps)
+ is CurrentApp -> {
+ try {
+ val iconDrawable =
+ userContext.packageManager.getApplicationIcon(type.packageName)
+ IconSource(painter = DrawablePainter(drawable = iconDrawable))
+ } catch (e: NameNotFoundException) {
+ Log.wtf(
+ "ShortcutHelperViewModel",
+ "Package not found when retrieving icon for ${type.packageName}",
+ )
+ IconSource(imageVector = Icons.Default.Android)
+ }
+ }
+ }
+ }
+
+ private fun getShortcutCategoryLabel(type: ShortcutCategoryType): String =
+ when (type) {
+ ShortcutCategoryType.System ->
+ userContext.getString(R.string.shortcut_helper_category_system)
+ ShortcutCategoryType.MultiTasking ->
+ userContext.getString(R.string.shortcut_helper_category_multitasking)
+ ShortcutCategoryType.InputMethodEditor ->
+ userContext.getString(R.string.shortcut_helper_category_input)
+ ShortcutCategoryType.AppCategories ->
+ userContext.getString(R.string.shortcut_helper_category_app_shortcuts)
+ is CurrentApp -> getApplicationLabelForCurrentApp(type)
+ }
+
+ private fun getApplicationLabelForCurrentApp(type: CurrentApp): String {
+ try {
+ val packageManagerForUser = userContext.packageManager
+ val currentAppInfo =
+ packageManagerForUser.getApplicationInfo(type.packageName, /* flags= */ 0)
+ return packageManagerForUser.getApplicationLabel(currentAppInfo).toString()
+ } catch (e: NameNotFoundException) {
+ Log.wtf(
+ "ShortcutHelperViewModel",
+ "Package Not found when retrieving Label for ${type.packageName}",
+ )
+ return "Current App"
+ }
+ }
+
private suspend fun excludeLauncherApp(
categories: List<ShortcutCategory>
): List<ShortcutCategory> {
@@ -111,7 +189,7 @@ constructor(
private fun filterCategoriesBySearchQuery(
query: String,
- categories: List<ShortcutCategory>
+ categories: List<ShortcutCategory>,
): List<ShortcutCategory> {
val lowerCaseTrimmedQuery = query.trim().lowercase()
if (lowerCaseTrimmedQuery.isEmpty()) {
@@ -132,7 +210,7 @@ constructor(
private fun filterSubCategoriesBySearchQuery(
subCategories: List<ShortcutSubCategory>,
- query: String
+ query: String,
) =
subCategories
.map { subCategory ->
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index fbc76c587be2..60a306b3e245 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -2975,7 +2975,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
@Override
public void run() {
Trace.beginSection("KeyguardViewMediator.mKeyGuardGoingAwayRunnable");
- if (DEBUG) Log.d(TAG, "keyguardGoingAway");
+ Log.d(TAG, "keyguardGoingAwayRunnable");
mKeyguardViewControllerLazy.get().keyguardGoingAway();
int flags = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index 821017418277..9e99a879be41 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -114,7 +114,7 @@ interface KeyguardRepository {
"away' is isInTransitionToState(GONE), but consider using more specific flows " +
"whenever possible."
)
- val isKeyguardGoingAway: Flow<Boolean>
+ val isKeyguardGoingAway: MutableStateFlow<Boolean>
/**
* Whether the keyguard is enabled, per [KeyguardService]. If the keyguard is not enabled, the
@@ -184,9 +184,6 @@ interface KeyguardRepository {
/** Observable for whether the device is dreaming with an overlay, see [DreamOverlayService] */
val isDreamingWithOverlay: Flow<Boolean>
- /** Observable for device dreaming state and the active dream is hosted in lockscreen */
- val isActiveDreamLockscreenHosted: StateFlow<Boolean>
-
/**
* Observable for the amount of doze we are currently in.
*
@@ -308,8 +305,6 @@ interface KeyguardRepository {
fun setIsDozing(isDozing: Boolean)
- fun setIsActiveDreamLockscreenHosted(isLockscreenHosted: Boolean)
-
fun dozeTimeTick()
fun showDismissibleKeyguard()
@@ -637,9 +632,6 @@ constructor(
private val _isQuickSettingsVisible = MutableStateFlow(false)
override val isQuickSettingsVisible: Flow<Boolean> = _isQuickSettingsVisible.asStateFlow()
- private val _isActiveDreamLockscreenHosted = MutableStateFlow(false)
- override val isActiveDreamLockscreenHosted = _isActiveDreamLockscreenHosted.asStateFlow()
-
private val _shortcutAbsoluteTop = MutableStateFlow(0F)
override val shortcutAbsoluteTop = _shortcutAbsoluteTop.asStateFlow()
@@ -655,10 +647,6 @@ constructor(
override fun onUnlockedChanged() {
isKeyguardDismissible.value = keyguardStateController.isUnlocked
}
-
- override fun onKeyguardGoingAwayChanged() {
- isKeyguardGoingAway.value = keyguardStateController.isKeyguardGoingAway
- }
}
keyguardStateController.addCallback(callback)
@@ -698,10 +686,6 @@ constructor(
_isQuickSettingsVisible.value = isVisible
}
- override fun setIsActiveDreamLockscreenHosted(isLockscreenHosted: Boolean) {
- _isActiveDreamLockscreenHosted.value = isLockscreenHosted
- }
-
override fun setClockShouldBeCentered(shouldBeCentered: Boolean) {
_clockShouldBeCentered.value = shouldBeCentered
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
index 8c7fe5f87a3f..0c2d5778079b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
@@ -131,12 +131,13 @@ constructor(
.collect { (_, isCommunalAvailable, isIdleOnCommunal) ->
val isKeyguardOccludedLegacy = keyguardInteractor.isKeyguardOccluded.value
val primaryBouncerShowing = keyguardInteractor.primaryBouncerShowing.value
+ val isKeyguardGoingAway = keyguardInteractor.isKeyguardGoingAway.value
if (!deviceEntryInteractor.isLockscreenEnabled()) {
if (!SceneContainerFlag.isEnabled) {
startTransitionTo(KeyguardState.GONE)
}
- } else if (canDismissLockscreen()) {
+ } else if (canDismissLockscreen() || isKeyguardGoingAway) {
if (!SceneContainerFlag.isEnabled) {
startTransitionTo(KeyguardState.GONE)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
index 5b7eeddfb8e1..d18d6dce2e94 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
@@ -105,21 +105,13 @@ constructor(
combine(
shadeInteractor.isShadeLayoutWide,
activeNotificationsInteractor.areAnyNotificationsPresent,
- keyguardInteractor.isActiveDreamLockscreenHosted,
isOnAod,
headsUpNotificationInteractor.isHeadsUpOrAnimatingAway,
keyguardInteractor.isDozing,
- ) {
- isShadeLayoutWide,
- areAnyNotificationsPresent,
- isActiveDreamLockscreenHosted,
- isOnAod,
- isHeadsUp,
- isDozing ->
+ ) { isShadeLayoutWide, areAnyNotificationsPresent, isOnAod, isHeadsUp, isDozing ->
when {
!isShadeLayoutWide -> true
!areAnyNotificationsPresent -> true
- isActiveDreamLockscreenHosted -> true
// Pulsing notification appears on the right. Move clock left to avoid overlap.
isHeadsUp && isDozing -> false
else -> isOnAod
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 6ecbc6175e40..0d5ad547f15f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -189,9 +189,6 @@ constructor(
/** Whether any dreaming is running, including the doze dream. */
val isDreamingAny: Flow<Boolean> = repository.isDreaming
- /** Whether the system is dreaming and the active dream is hosted in lockscreen */
- val isActiveDreamLockscreenHosted: StateFlow<Boolean> = repository.isActiveDreamLockscreenHosted
-
/** Event for when the camera gesture is detected */
val onCameraLaunchDetected: Flow<CameraLaunchSourceModel> =
repository.onCameraLaunchDetected.filter { it.type != CameraLaunchType.IGNORE }
@@ -244,7 +241,7 @@ constructor(
/** Whether the keyguard is going away. */
@Deprecated("Use KeyguardTransitionInteractor + KeyguardState.GONE")
- val isKeyguardGoingAway: Flow<Boolean> = repository.isKeyguardGoingAway
+ val isKeyguardGoingAway: StateFlow<Boolean> = repository.isKeyguardGoingAway.asStateFlow()
/** Keyguard can be clipped at the top as the shade is dragged */
val topClippingBounds: Flow<Int?> by lazy {
@@ -477,10 +474,6 @@ constructor(
}
}
- fun setIsActiveDreamLockscreenHosted(isLockscreenHosted: Boolean) {
- repository.setIsActiveDreamLockscreenHosted(isLockscreenHosted)
- }
-
/** Sets whether quick settings or quick-quick settings is visible. */
fun setQuickSettingsVisible(isVisible: Boolean) {
repository.setQuickSettingsVisible(isVisible)
@@ -549,6 +542,10 @@ constructor(
repository.setShortcutAbsoluteTop(top)
}
+ fun setIsKeyguardGoingAway(isGoingAway: Boolean) {
+ repository.isKeyguardGoingAway.value = isGoingAway
+ }
+
companion object {
private const val TAG = "KeyguardInteractor"
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractor.kt
index fcf486b5696b..d4d7e75a8b41 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardKeyEventInteractor.kt
@@ -20,6 +20,7 @@ import android.content.Context
import android.media.AudioManager
import android.view.KeyEvent
import com.android.systemui.back.domain.interactor.BackActionInteractor
+import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyevent.domain.interactor.SysUIKeyEventHandler.Companion.handleAction
import com.android.systemui.media.controls.util.MediaSessionLegacyHelperWrapper
@@ -45,6 +46,7 @@ constructor(
private val mediaSessionLegacyHelperWrapper: MediaSessionLegacyHelperWrapper,
private val backActionInteractor: BackActionInteractor,
private val powerInteractor: PowerInteractor,
+ private val keyguardMediaKeyInteractor: KeyguardMediaKeyInteractor,
) {
fun dispatchKeyEvent(event: KeyEvent): Boolean {
@@ -96,8 +98,15 @@ constructor(
}
fun interceptMediaKey(event: KeyEvent): Boolean {
- return statusBarStateController.state == StatusBarState.KEYGUARD &&
- statusBarKeyguardViewManager.interceptMediaKey(event)
+ return when (statusBarStateController.state) {
+ StatusBarState.KEYGUARD ->
+ if (ComposeBouncerFlags.isEnabled) {
+ keyguardMediaKeyInteractor.processMediaKeyEvent(event)
+ } else {
+ statusBarKeyguardViewManager.interceptMediaKey(event)
+ }
+ else -> false
+ }
}
private fun dispatchMenuKeyEvent(): Boolean {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardMediaKeyInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardMediaKeyInteractor.kt
new file mode 100644
index 000000000000..1404ef6a8fab
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardMediaKeyInteractor.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2024 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.keyguard.domain.interactor
+
+import android.media.AudioManager
+import android.view.KeyEvent
+import com.android.settingslib.volume.data.repository.AudioRepository
+import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.lifecycle.ExclusiveActivatable
+import com.android.systemui.telephony.domain.interactor.TelephonyInteractor
+import javax.inject.Inject
+
+/** Handle media key events while on keyguard or bouncer. */
+@SysUISingleton
+class KeyguardMediaKeyInteractor
+@Inject
+constructor(
+ private val telephonyInteractor: TelephonyInteractor,
+ private val audioRepository: AudioRepository,
+) : ExclusiveActivatable() {
+
+ /**
+ * Allows the media keys to work when the keyguard is showing. Forwards the relevant media keys
+ * to [AudioManager].
+ *
+ * @param event The key event
+ * @return whether the event was consumed as a media key.
+ */
+ fun processMediaKeyEvent(event: KeyEvent): Boolean {
+ if (ComposeBouncerFlags.isUnexpectedlyInLegacyMode()) {
+ return false
+ }
+ val keyCode = event.keyCode
+ if (event.action == KeyEvent.ACTION_DOWN) {
+ when (keyCode) {
+ KeyEvent.KEYCODE_MEDIA_PLAY,
+ KeyEvent.KEYCODE_MEDIA_PAUSE,
+ KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> {
+ /* Suppress PLAY/PAUSE toggle when phone is ringing or
+ * in-call to avoid music playback */
+ // suppress key event
+ return telephonyInteractor.isInCall.value
+ }
+
+ KeyEvent.KEYCODE_MUTE,
+ KeyEvent.KEYCODE_HEADSETHOOK,
+ KeyEvent.KEYCODE_MEDIA_STOP,
+ KeyEvent.KEYCODE_MEDIA_NEXT,
+ KeyEvent.KEYCODE_MEDIA_PREVIOUS,
+ KeyEvent.KEYCODE_MEDIA_REWIND,
+ KeyEvent.KEYCODE_MEDIA_RECORD,
+ KeyEvent.KEYCODE_MEDIA_FAST_FORWARD,
+ KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK -> {
+ audioRepository.dispatchMediaKeyEvent(event)
+ return true
+ }
+
+ KeyEvent.KEYCODE_VOLUME_UP,
+ KeyEvent.KEYCODE_VOLUME_DOWN,
+ KeyEvent.KEYCODE_VOLUME_MUTE -> return false
+ }
+ } else if (event.action == KeyEvent.ACTION_UP) {
+ when (keyCode) {
+ KeyEvent.KEYCODE_MUTE,
+ KeyEvent.KEYCODE_HEADSETHOOK,
+ KeyEvent.KEYCODE_MEDIA_PLAY,
+ KeyEvent.KEYCODE_MEDIA_PAUSE,
+ KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE,
+ KeyEvent.KEYCODE_MEDIA_STOP,
+ KeyEvent.KEYCODE_MEDIA_NEXT,
+ KeyEvent.KEYCODE_MEDIA_PREVIOUS,
+ KeyEvent.KEYCODE_MEDIA_REWIND,
+ KeyEvent.KEYCODE_MEDIA_RECORD,
+ KeyEvent.KEYCODE_MEDIA_FAST_FORWARD,
+ KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK -> {
+ audioRepository.dispatchMediaKeyEvent(event)
+ return true
+ }
+ }
+ }
+ return false
+ }
+
+ override suspend fun onActivated(): Nothing {
+ // Collect to keep this flow hot for this interactor.
+ telephonyInteractor.isInCall.collect {}
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt
index cf747c81769a..34173a9f44ea 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt
@@ -29,6 +29,7 @@ import com.android.systemui.power.shared.model.ScreenPowerState
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.LightRevealEffect
+import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
import com.android.systemui.util.kotlin.sample
import dagger.Lazy
import javax.inject.Inject
@@ -96,16 +97,19 @@ constructor(
/** Limit the max alpha for the scrim to allow for some transparency */
val maxAlpha: Flow<Float> =
- transitionInteractor
- .isInTransition(
- edge = Edge.create(Scenes.Gone, KeyguardState.AOD),
- edgeWithoutSceneContainer = Edge.create(KeyguardState.GONE, KeyguardState.AOD),
+ anyOf(
+ transitionInteractor.isInTransition(
+ edge = Edge.create(Scenes.Gone, KeyguardState.AOD),
+ edgeWithoutSceneContainer = Edge.create(KeyguardState.GONE, KeyguardState.AOD),
+ ),
+ transitionInteractor.isInTransition(
+ Edge.create(KeyguardState.OCCLUDED, KeyguardState.AOD)
+ ),
)
.flatMapLatest { isInTransition ->
- // During GONE->AOD transitions, the home screen and wallpaper are still visible
- // until
- // WM is told to hide them, which occurs at the end of the animation. Use an opaque
- // scrim until this transition is complete
+ // During transitions like GONE->AOD, surfaces like the launcher may be visible
+ // until WM is told to hide them, which occurs at the end of the animation. Use an
+ // opaque scrim until this transition is complete.
if (isInTransition) {
flowOf(1f)
} else {
@@ -149,7 +153,6 @@ constructor(
KeyguardState.DOZING -> false
KeyguardState.AOD -> false
KeyguardState.DREAMING -> true
- KeyguardState.DREAMING_LOCKSCREEN_HOSTED -> true
KeyguardState.GLANCEABLE_HUB -> true
KeyguardState.ALTERNATE_BOUNCER -> true
KeyguardState.PRIMARY_BOUNCER -> true
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
index 080ddfd18370..f0e79b8590a0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/KeyguardState.kt
@@ -41,12 +41,6 @@ enum class KeyguardState {
*/
DREAMING,
/**
- * A device state after the device times out, which can be from both LOCKSCREEN or GONE states.
- * It is a special version of DREAMING state but not DOZING. The active dream will be windowless
- * and hosted in the lockscreen.
- */
- DREAMING_LOCKSCREEN_HOSTED,
- /**
* The device has entered a special low-power mode within SystemUI, also called the Always-on
* Display (AOD). A minimal UI is presented to show critical information. If the device is in
* low-power mode without a UI, then it is DOZING.
@@ -125,7 +119,6 @@ enum class KeyguardState {
OFF,
DOZING,
DREAMING,
- DREAMING_LOCKSCREEN_HOSTED,
AOD,
ALTERNATE_BOUNCER,
OCCLUDED,
@@ -142,7 +135,6 @@ enum class KeyguardState {
OFF,
DOZING,
DREAMING,
- DREAMING_LOCKSCREEN_HOSTED,
AOD,
ALTERNATE_BOUNCER,
OCCLUDED,
@@ -166,7 +158,6 @@ enum class KeyguardState {
OFF -> false
DOZING -> false
DREAMING -> false
- DREAMING_LOCKSCREEN_HOSTED -> false
GLANCEABLE_HUB -> true
AOD -> false
ALTERNATE_BOUNCER -> true
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt
index 32757ce82c69..741cc02ffb6b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt
@@ -19,6 +19,7 @@ package com.android.systemui.keyguard.ui.binder
import android.animation.ValueAnimator
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
+import com.android.app.animation.Interpolators.ALPHA_IN
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
@@ -43,14 +44,24 @@ object LightRevealScrimViewBinder {
}
}
launch("$TAG#viewModel.maxAlpha") {
- viewModel.maxAlpha.collect { alpha ->
+ var animator: ValueAnimator? = null
+ viewModel.maxAlpha.collect { (alpha, animate) ->
if (alpha != revealScrim.alpha) {
- ValueAnimator.ofFloat(revealScrim.alpha, alpha).apply {
- duration = 400
- addUpdateListener { animation ->
- revealScrim.alpha = animation.getAnimatedValue() as Float
- }
- start()
+ animator?.cancel()
+ if (!animate) {
+ revealScrim.alpha = alpha
+ } else {
+ animator =
+ ValueAnimator.ofFloat(revealScrim.alpha, alpha).apply {
+ startDelay = 333
+ duration = 733
+ interpolator = ALPHA_IN
+ addUpdateListener { animation ->
+ revealScrim.alpha =
+ animation.getAnimatedValue() as Float
+ }
+ start()
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
index 68244d842046..4c667c1c702d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
@@ -114,7 +114,6 @@ constructor(
keyguardTransitionInteractor.currentKeyguardState.replayCache.last()
) {
KeyguardState.GLANCEABLE_HUB,
- KeyguardState.DREAMING_LOCKSCREEN_HOSTED,
KeyguardState.GONE,
KeyguardState.OCCLUDED,
KeyguardState.OFF,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
index d3bb4f5d7508..f5e0c81ca9a2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryIconViewModel.kt
@@ -95,11 +95,10 @@ constructor(
.shareIn(scope, SharingStarted.WhileSubscribed())
.onStart { emit(initialAlphaFromKeyguardState(transitionInteractor.getCurrentState())) }
private val alphaMultiplierFromShadeExpansion: Flow<Float> =
- combine(
- showingAlternateBouncer,
+ combine(showingAlternateBouncer, shadeExpansion, qsProgress) {
+ showingAltBouncer,
shadeExpansion,
- qsProgress,
- ) { showingAltBouncer, shadeExpansion, qsProgress ->
+ qsProgress ->
val interpolatedQsProgress = (qsProgress * 2).coerceIn(0f, 1f)
if (showingAltBouncer) {
1f
@@ -113,13 +112,9 @@ constructor(
combine(
burnInInteractor.deviceEntryIconXOffset,
burnInInteractor.deviceEntryIconYOffset,
- burnInInteractor.udfpsProgress
+ burnInInteractor.udfpsProgress,
) { fullyDozingBurnInX, fullyDozingBurnInY, fullyDozingBurnInProgress ->
- BurnInOffsets(
- fullyDozingBurnInX,
- fullyDozingBurnInY,
- fullyDozingBurnInProgress,
- )
+ BurnInOffsets(fullyDozingBurnInX, fullyDozingBurnInY, fullyDozingBurnInProgress)
}
private val dozeAmount: Flow<Float> = transitionInteractor.transitionValue(KeyguardState.AOD)
@@ -129,22 +124,15 @@ constructor(
BurnInOffsets(
intEvaluator.evaluate(dozeAmount, 0, burnInOffsets.x),
intEvaluator.evaluate(dozeAmount, 0, burnInOffsets.y),
- floatEvaluator.evaluate(dozeAmount, 0, burnInOffsets.progress)
+ floatEvaluator.evaluate(dozeAmount, 0, burnInOffsets.progress),
)
}
val deviceEntryViewAlpha: Flow<Float> =
- combine(
- transitionAlpha,
- alphaMultiplierFromShadeExpansion,
- ) { alpha, alphaMultiplier ->
+ combine(transitionAlpha, alphaMultiplierFromShadeExpansion) { alpha, alphaMultiplier ->
alpha * alphaMultiplier
}
- .stateIn(
- scope = scope,
- started = SharingStarted.WhileSubscribed(),
- initialValue = 0f,
- )
+ .stateIn(scope = scope, started = SharingStarted.WhileSubscribed(), initialValue = 0f)
private fun initialAlphaFromKeyguardState(keyguardState: KeyguardState): Float {
return when (keyguardState) {
@@ -155,11 +143,10 @@ constructor(
KeyguardState.GLANCEABLE_HUB,
KeyguardState.GONE,
KeyguardState.OCCLUDED,
- KeyguardState.DREAMING_LOCKSCREEN_HOSTED,
- KeyguardState.UNDEFINED, -> 0f
+ KeyguardState.UNDEFINED -> 0f
KeyguardState.AOD,
KeyguardState.ALTERNATE_BOUNCER,
- KeyguardState.LOCKSCREEN, -> 1f
+ KeyguardState.LOCKSCREEN -> 1f
}
}
@@ -171,7 +158,7 @@ constructor(
combine(
transitionInteractor.startedKeyguardTransitionStep.sample(
shadeInteractor.isAnyFullyExpanded,
- ::Pair
+ ::Pair,
),
animatedBurnInOffsets,
nonAnimatedBurnInOffsets,
@@ -228,10 +215,9 @@ constructor(
}
val iconType: Flow<DeviceEntryIconView.IconType> =
- combine(
- deviceEntryUdfpsInteractor.isListeningForUdfps,
- isUnlocked,
- ) { isListeningForUdfps, isUnlocked ->
+ combine(deviceEntryUdfpsInteractor.isListeningForUdfps, isUnlocked) {
+ isListeningForUdfps,
+ isUnlocked ->
if (isListeningForUdfps) {
if (isUnlocked) {
// Don't show any UI until isUnlocked=false. This covers the case
@@ -250,10 +236,7 @@ constructor(
val isVisible: Flow<Boolean> = deviceEntryViewAlpha.map { it > 0f }.distinctUntilChanged()
private val isInteractive: Flow<Boolean> =
- combine(
- iconType,
- isUdfpsSupported,
- ) { deviceEntryStatus, isUdfps ->
+ combine(iconType, isUdfpsSupported) { deviceEntryStatus, isUdfps ->
when (deviceEntryStatus) {
DeviceEntryIconView.IconType.LOCK -> isUdfps
DeviceEntryIconView.IconType.UNLOCK -> true
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt
index af6cd166479a..6d1aefe813c3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt
@@ -21,6 +21,7 @@ import com.android.systemui.statusbar.LightRevealEffect
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
/**
* Models UI state for the light reveal scrim, which is used during screen on and off animations to
@@ -32,7 +33,16 @@ class LightRevealScrimViewModel
constructor(private val interactor: LightRevealScrimInteractor) {
val lightRevealEffect: Flow<LightRevealEffect> = interactor.lightRevealEffect
val revealAmount: Flow<Float> = interactor.revealAmount
- val maxAlpha: Flow<Float> = interactor.maxAlpha
+
+ /** Max alpha for the scrim + whether to animate the change */
+ val maxAlpha: Flow<Pair<Float, Boolean>> =
+ interactor.maxAlpha.map { alpha ->
+ Pair(
+ alpha,
+ // Darken immediately if going to be fully opaque
+ if (alpha == 1f) false else true,
+ )
+ }
fun setWallpaperSupportsAmbientMode(supportsAmbientMode: Boolean) {
interactor.setWallpaperSupportsAmbientMode(supportsAmbientMode)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
index 6db91ac073ba..4071b135dfaf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
@@ -221,7 +221,7 @@ constructor(
{ notificationScrimClippingParams.params.top },
// Only allow scrolling when we are fully expanded. That way, we don't intercept
// swipes in lockscreen (when somehow QS is receiving touches).
- { scrollState.canScrollForward && viewModel.isQsFullyExpanded },
+ { (scrollState.canScrollForward && viewModel.isQsFullyExpanded) || isCustomizing },
)
frame.addView(
composeView,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt
index 71fa0ac30fb7..7b2593952599 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/CommonTile.kt
@@ -77,25 +77,24 @@ fun LargeTileContent(
colors: TileColors,
squishiness: () -> Float,
accessibilityUiState: AccessibilityUiState? = null,
- toggleClickSupported: Boolean = false,
iconShape: Shape = RoundedCornerShape(CommonTileDefaults.InactiveCornerRadius),
- onClick: () -> Unit = {},
- onLongClick: () -> Unit = {},
+ toggleClick: (() -> Unit)? = null,
+ onLongClick: (() -> Unit)? = null,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = tileHorizontalArrangement(),
) {
// Icon
- val longPressLabel = longPressLabel()
+ val longPressLabel = longPressLabel().takeIf { onLongClick != null }
Box(
modifier =
- Modifier.size(CommonTileDefaults.ToggleTargetSize).thenIf(toggleClickSupported) {
+ Modifier.size(CommonTileDefaults.ToggleTargetSize).thenIf(toggleClick != null) {
Modifier.clip(iconShape)
.verticalSquish(squishiness)
.background(colors.iconBackground, { 1f })
.combinedClickable(
- onClick = onClick,
+ onClick = toggleClick!!,
onLongClick = onLongClick,
onLongClickLabel = longPressLabel,
)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt
index d2ec958c17b7..b581c8bf953f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/EditTile.kt
@@ -202,14 +202,17 @@ fun DefaultEditTileGrid(
topBar = { EditModeTopBar(onStopEditing = onStopEditing, onReset = reset) },
) { innerPadding ->
CompositionLocalProvider(LocalOverscrollConfiguration provides null) {
+ val scrollState = rememberScrollState()
+ LaunchedEffect(listState.dragInProgress) {
+ if (listState.dragInProgress) {
+ scrollState.animateScrollTo(0)
+ }
+ }
+
Column(
verticalArrangement =
spacedBy(dimensionResource(id = R.dimen.qs_label_container_margin)),
- modifier =
- modifier
- .fillMaxSize()
- .verticalScroll(rememberScrollState())
- .padding(innerPadding),
+ modifier = modifier.fillMaxSize().verticalScroll(scrollState).padding(innerPadding),
) {
AnimatedContent(
targetState = listState.dragInProgress,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt
index 52d526123430..5f28fe427707 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/Tile.kt
@@ -160,19 +160,18 @@ fun Tile(
)
} else {
val iconShape = TileDefaults.animateIconShape(uiState.state)
+ val secondaryClick: (() -> Unit)? =
+ { tile.onSecondaryClick() }.takeIf { uiState.handlesSecondaryClick }
+ val longClick: (() -> Unit)? =
+ { tile.onLongClick(expandable) }.takeIf { uiState.handlesLongClick }
LargeTileContent(
label = uiState.label,
secondaryLabel = uiState.secondaryLabel,
icon = icon,
colors = colors,
iconShape = iconShape,
- toggleClickSupported = state.handlesSecondaryClick,
- onClick = {
- if (state.handlesSecondaryClick) {
- tile.onSecondaryClick()
- }
- },
- onLongClick = { tile.onLongClick(expandable) },
+ toggleClick = secondaryClick,
+ onLongClick = longClick,
accessibilityUiState = uiState.accessibilityUiState,
squishiness = squishiness,
)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt
index aa420800be7b..56675e49d4e6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/TileUiState.kt
@@ -33,6 +33,7 @@ data class TileUiState(
val label: String,
val secondaryLabel: String,
val state: Int,
+ val handlesLongClick: Boolean,
val handlesSecondaryClick: Boolean,
val icon: Supplier<QSTile.Icon?>,
val accessibilityUiState: AccessibilityUiState,
@@ -86,6 +87,7 @@ fun QSTile.State.toUiState(resources: Resources): TileUiState {
label = label?.toString() ?: "",
secondaryLabel = secondaryLabel?.toString() ?: "",
state = if (disabledByPolicy) Tile.STATE_UNAVAILABLE else state,
+ handlesLongClick = handlesLongClick,
handlesSecondaryClick = handlesSecondaryClick,
icon = icon?.let { Supplier { icon } } ?: iconSupplier ?: Supplier { null },
AccessibilityUiState(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
index fb406d47d7a6..1792ebd5245d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/RecordIssueTile.kt
@@ -152,7 +152,14 @@ constructor(
recordingController.startCountdown(
DELAY_MS,
INTERVAL_MS,
- pendingServiceIntent(getStartIntent(userContextProvider.userContext)),
+ pendingServiceIntent(
+ getStartIntent(
+ userContextProvider.userContext,
+ issueRecordingState.traceConfig,
+ issueRecordingState.recordScreen,
+ issueRecordingState.takeBugreport,
+ )
+ ),
pendingServiceIntent(getStopIntent(userContextProvider.userContext)),
)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt
index 0c8a3750f6fe..fceee5a3379e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/impl/irecording/IssueRecordingUserActionInteractor.kt
@@ -35,6 +35,7 @@ import com.android.systemui.qs.tiles.base.interactor.QSTileUserActionInteractor
import com.android.systemui.qs.tiles.viewmodel.QSTileUserAction
import com.android.systemui.recordissue.IssueRecordingService.Companion.getStartIntent
import com.android.systemui.recordissue.IssueRecordingService.Companion.getStopIntent
+import com.android.systemui.recordissue.IssueRecordingState
import com.android.systemui.recordissue.RecordIssueDialogDelegate
import com.android.systemui.recordissue.RecordIssueModule.Companion.TILE_SPEC
import com.android.systemui.screenrecord.RecordingController
@@ -52,6 +53,7 @@ class IssueRecordingUserActionInteractor
@Inject
constructor(
@Main private val mainCoroutineContext: CoroutineContext,
+ private val state: IssueRecordingState,
private val keyguardDismissUtil: KeyguardDismissUtil,
private val keyguardStateController: KeyguardStateController,
private val dialogTransitionAnimator: DialogTransitionAnimator,
@@ -104,8 +106,15 @@ constructor(
recordingController.startCountdown(
DELAY_MS,
INTERVAL_MS,
- pendingServiceIntent(getStartIntent(userContextProvider.userContext)),
- pendingServiceIntent(getStopIntent(userContextProvider.userContext))
+ pendingServiceIntent(
+ getStartIntent(
+ userContextProvider.userContext,
+ state.traceConfig,
+ state.recordScreen,
+ state.takeBugreport,
+ )
+ ),
+ pendingServiceIntent(getStopIntent(userContextProvider.userContext)),
)
private fun stopIssueRecordingService() =
@@ -117,6 +126,6 @@ constructor(
userContextProvider.userContext,
RecordingService.REQUEST_CODE,
action,
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt
index 3f875bcc288b..ad0ede44a58e 100644
--- a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingService.kt
@@ -38,6 +38,8 @@ import com.android.systemui.screenrecord.RecordingService
import com.android.systemui.screenrecord.RecordingServiceStrings
import com.android.systemui.settings.UserContextProvider
import com.android.systemui.statusbar.phone.KeyguardDismissUtil
+import com.android.traceur.MessageConstants.INTENT_EXTRA_TRACE_TYPE
+import com.android.traceur.TraceConfig
import java.util.concurrent.Executor
import javax.inject.Inject
@@ -110,7 +112,13 @@ constructor(
when (intent?.action) {
ACTION_START -> {
session.start()
- if (!issueRecordingState.recordScreen) {
+ with(session) {
+ traceConfig =
+ intent.getParcelableExtra(INTENT_EXTRA_TRACE_TYPE, TraceConfig::class.java)
+ takeBugReport = intent.getBooleanExtra(EXTRA_BUG_REPORT, false)
+ start()
+ }
+ if (!intent.getBooleanExtra(EXTRA_SCREEN_RECORD, false)) {
// If we don't want to record the screen, the ACTION_SHOW_START_NOTIF action
// will circumvent the RecordingService's screen recording start code.
return super.onStartCommand(Intent(ACTION_SHOW_START_NOTIF), flags, startId)
@@ -136,6 +144,8 @@ constructor(
companion object {
private const val TAG = "IssueRecordingService"
private const val CHANNEL_ID = "issue_record"
+ const val EXTRA_SCREEN_RECORD = "extra_screenRecord"
+ const val EXTRA_BUG_REPORT = "extra_bugReport"
/**
* Get an intent to stop the issue recording service.
@@ -153,8 +163,17 @@ constructor(
*
* @param context Context from the requesting activity
*/
- fun getStartIntent(context: Context): Intent =
- Intent(context, IssueRecordingService::class.java).setAction(ACTION_START)
+ fun getStartIntent(
+ context: Context,
+ traceConfig: TraceConfig,
+ screenRecord: Boolean,
+ bugReport: Boolean,
+ ): Intent =
+ Intent(context, IssueRecordingService::class.java)
+ .setAction(ACTION_START)
+ .putExtra(INTENT_EXTRA_TRACE_TYPE, traceConfig)
+ .putExtra(EXTRA_SCREEN_RECORD, screenRecord)
+ .putExtra(EXTRA_BUG_REPORT, bugReport)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceSession.kt b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceSession.kt
index ad9b4fe164e8..4c01293d1cad 100644
--- a/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceSession.kt
+++ b/packages/SystemUI/src/com/android/systemui/recordissue/IssueRecordingServiceSession.kt
@@ -25,6 +25,7 @@ import android.provider.Settings
import com.android.systemui.animation.DialogTransitionAnimator
import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor
import com.android.systemui.settings.UserContextProvider
+import com.android.traceur.PresetTraceConfigs
import java.util.concurrent.Executor
private const val NOTIFY_SESSION_ENDED_SETTING = "should_notify_trace_session_ended"
@@ -47,15 +48,17 @@ class IssueRecordingServiceSession(
private val notificationManager: NotificationManager,
private val userContextProvider: UserContextProvider,
) {
+ var takeBugReport = false
+ var traceConfig = PresetTraceConfigs.getDefaultConfig()
fun start() {
- bgExecutor.execute { traceurConnection.startTracing(issueRecordingState.traceConfig) }
+ bgExecutor.execute { traceurConnection.startTracing(traceConfig) }
issueRecordingState.isRecording = true
}
fun stop(contentResolver: ContentResolver) {
bgExecutor.execute {
- if (issueRecordingState.traceConfig.longTrace) {
+ if (traceConfig.longTrace) {
Settings.Global.putInt(contentResolver, NOTIFY_SESSION_ENDED_SETTING, DISABLED)
}
traceurConnection.stopTracing()
@@ -71,7 +74,7 @@ class IssueRecordingServiceSession(
UserHandle(userContextProvider.userContext.userId),
)
- if (issueRecordingState.takeBugreport) {
+ if (takeBugReport) {
iActivityManager.requestBugReportWithExtraAttachment(screenRecording)
} else {
traceurConnection.shareTraces(screenRecording)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt
deleted file mode 100644
index f73d2041af95..000000000000
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicy.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.screenshot
-
-import android.annotation.UserIdInt
-import android.content.ComponentName
-import android.graphics.Rect
-import android.os.UserHandle
-import android.view.Display
-
-/**
- * Provides policy decision-making information to screenshot request handling.
- */
-interface ScreenshotPolicy {
-
- /** @return true if the user is a managed profile (a.k.a. work profile) */
- suspend fun isManagedProfile(@UserIdInt userId: Int): Boolean
-
- /**
- * Requests information about the owner of display content which occupies a majority of the
- * screenshot and/or has most recently been interacted with at the time the screenshot was
- * requested.
- *
- * @param displayId the id of the display to inspect
- * @return content info for the primary content on the display
- */
- suspend fun findPrimaryContent(displayId: Int): DisplayContentInfo
-
- data class DisplayContentInfo(
- val component: ComponentName,
- val bounds: Rect,
- val user: UserHandle,
- val taskId: Int,
- )
-
- fun getDefaultDisplayId(): Int = Display.DEFAULT_DISPLAY
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicyImpl.kt b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicyImpl.kt
deleted file mode 100644
index 21a73100da06..000000000000
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotPolicyImpl.kt
+++ /dev/null
@@ -1,189 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.screenshot
-
-import android.annotation.UserIdInt
-import android.app.ActivityTaskManager
-import android.app.ActivityTaskManager.RootTaskInfo
-import android.app.IActivityTaskManager
-import android.app.WindowConfiguration
-import android.app.WindowConfiguration.activityTypeToString
-import android.app.WindowConfiguration.windowingModeToString
-import android.content.ComponentName
-import android.content.Context
-import android.content.Intent
-import android.graphics.Rect
-import android.os.Process
-import android.os.RemoteException
-import android.os.UserHandle
-import android.os.UserManager
-import android.util.Log
-import com.android.internal.annotations.VisibleForTesting
-import com.android.internal.infra.ServiceConnector
-import com.android.systemui.SystemUIService
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.settings.DisplayTracker
-import com.android.systemui.screenshot.ScreenshotPolicy.DisplayContentInfo
-import java.util.Arrays
-import javax.inject.Inject
-import kotlin.coroutines.resume
-import kotlin.coroutines.suspendCoroutine
-import kotlinx.coroutines.CoroutineDispatcher
-import kotlinx.coroutines.withContext
-
-@SysUISingleton
-internal open class ScreenshotPolicyImpl @Inject constructor(
- context: Context,
- private val userMgr: UserManager,
- private val atmService: IActivityTaskManager,
- @Background val bgDispatcher: CoroutineDispatcher,
- private val displayTracker: DisplayTracker
-) : ScreenshotPolicy {
-
- private val proxyConnector: ServiceConnector<IScreenshotProxy> =
- ServiceConnector.Impl(
- context,
- Intent(context, ScreenshotProxyService::class.java),
- Context.BIND_AUTO_CREATE or Context.BIND_WAIVE_PRIORITY or Context.BIND_NOT_VISIBLE,
- context.userId,
- IScreenshotProxy.Stub::asInterface
- )
-
- override fun getDefaultDisplayId(): Int {
- return displayTracker.defaultDisplayId
- }
-
- override suspend fun isManagedProfile(@UserIdInt userId: Int): Boolean {
- val managed = withContext(bgDispatcher) { userMgr.isManagedProfile(userId) }
- Log.d(TAG, "isManagedProfile: $managed")
- return managed
- }
-
- private fun nonPipVisibleTask(info: RootTaskInfo): Boolean {
- if (DEBUG) {
- debugLogRootTaskInfo(info)
- }
- return info.windowingMode != WindowConfiguration.WINDOWING_MODE_PINNED &&
- info.isVisible &&
- info.isRunning &&
- info.numActivities > 0 &&
- info.topActivity != null &&
- info.childTaskIds.isNotEmpty()
- }
-
- /**
- * Uses RootTaskInfo from ActivityTaskManager to guess at the primary focused task within a
- * display. If no task is visible or the top task is covered by a system window, the info
- * reported will reference a SystemUI component instead.
- */
- override suspend fun findPrimaryContent(displayId: Int): DisplayContentInfo {
- // Determine if the notification shade is expanded. If so, task windows are not
- // visible behind it, so the screenshot should instead be associated with SystemUI.
- if (isNotificationShadeExpanded()) {
- return systemUiContent
- }
-
- val taskInfoList = getAllRootTaskInfosOnDisplay(displayId)
-
- // If no visible task is located, then report SystemUI as the foreground content
- val target = taskInfoList.firstOrNull(::nonPipVisibleTask) ?: return systemUiContent
- return target.toDisplayContentInfo()
- }
-
- private fun debugLogRootTaskInfo(info: RootTaskInfo) {
- Log.d(TAG, "RootTaskInfo={" +
- "taskId=${info.taskId} " +
- "parentTaskId=${info.parentTaskId} " +
- "position=${info.position} " +
- "positionInParent=${info.positionInParent} " +
- "isVisible=${info.isVisible()} " +
- "visible=${info.visible} " +
- "isFocused=${info.isFocused} " +
- "isSleeping=${info.isSleeping} " +
- "isRunning=${info.isRunning} " +
- "windowMode=${windowingModeToString(info.windowingMode)} " +
- "activityType=${activityTypeToString(info.activityType)} " +
- "topActivity=${info.topActivity} " +
- "topActivityInfo=${info.topActivityInfo} " +
- "numActivities=${info.numActivities} " +
- "childTaskIds=${Arrays.toString(info.childTaskIds)} " +
- "childUserIds=${Arrays.toString(info.childTaskUserIds)} " +
- "childTaskBounds=${Arrays.toString(info.childTaskBounds)} " +
- "childTaskNames=${Arrays.toString(info.childTaskNames)}" +
- "}"
- )
-
- for (j in 0 until info.childTaskIds.size) {
- Log.d(TAG, " *** [$j] ******")
- Log.d(TAG, " *** childTaskIds[$j]: ${info.childTaskIds[j]}")
- Log.d(TAG, " *** childTaskUserIds[$j]: ${info.childTaskUserIds[j]}")
- Log.d(TAG, " *** childTaskBounds[$j]: ${info.childTaskBounds[j]}")
- Log.d(TAG, " *** childTaskNames[$j]: ${info.childTaskNames[j]}")
- }
- }
-
- @VisibleForTesting
- open suspend fun getAllRootTaskInfosOnDisplay(displayId: Int): List<RootTaskInfo> =
- withContext(bgDispatcher) {
- try {
- atmService.getAllRootTaskInfosOnDisplay(displayId)
- } catch (e: RemoteException) {
- Log.e(TAG, "getAllRootTaskInfosOnDisplay", e)
- listOf()
- }
- }
-
- @VisibleForTesting
- open suspend fun isNotificationShadeExpanded(): Boolean = suspendCoroutine { k ->
- proxyConnector
- .postForResult { it.isNotificationShadeExpanded }
- .whenComplete { expanded, error ->
- if (error != null) {
- Log.e(TAG, "isNotificationShadeExpanded", error)
- }
- k.resume(expanded ?: false)
- }
- }
-
- @VisibleForTesting
- internal val systemUiContent =
- DisplayContentInfo(
- ComponentName(context, SystemUIService::class.java),
- Rect(),
- Process.myUserHandle(),
- ActivityTaskManager.INVALID_TASK_ID
- )
-}
-
-private const val TAG: String = "ScreenshotPolicyImpl"
-private const val DEBUG: Boolean = false
-
-@VisibleForTesting
-internal fun RootTaskInfo.toDisplayContentInfo(): DisplayContentInfo {
- val topActivity: ComponentName = topActivity ?: error("should not be null")
- val topChildTask = childTaskIds.size - 1
- val childTaskId = childTaskIds[topChildTask]
- val childTaskUserId = childTaskUserIds[topChildTask]
- val childTaskBounds = childTaskBounds[topChildTask]
-
- return DisplayContentInfo(
- topActivity,
- childTaskBounds,
- UserHandle.of(childTaskUserId),
- childTaskId)
-}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
index 254dde45148c..90695fa00ceb 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/dagger/ScreenshotModule.java
@@ -27,8 +27,6 @@ import com.android.systemui.screenshot.ImageCaptureImpl;
import com.android.systemui.screenshot.InteractiveScreenshotHandler;
import com.android.systemui.screenshot.LegacyScreenshotController;
import com.android.systemui.screenshot.ScreenshotController;
-import com.android.systemui.screenshot.ScreenshotPolicy;
-import com.android.systemui.screenshot.ScreenshotPolicyImpl;
import com.android.systemui.screenshot.ScreenshotSoundController;
import com.android.systemui.screenshot.ScreenshotSoundControllerImpl;
import com.android.systemui.screenshot.ScreenshotSoundProvider;
@@ -66,9 +64,6 @@ public abstract class ScreenshotModule {
TakeScreenshotExecutorImpl impl);
@Binds
- abstract ScreenshotPolicy bindScreenshotPolicyImpl(ScreenshotPolicyImpl impl);
-
- @Binds
abstract ImageCapture bindImageCaptureImpl(ImageCaptureImpl capture);
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserContextProvider.kt b/packages/SystemUI/src/com/android/systemui/settings/UserContextProvider.kt
index dae851252271..258befe61bfe 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/UserContextProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserContextProvider.kt
@@ -18,15 +18,19 @@ package com.android.systemui.settings
import android.content.Context
-/**
- * Implemented by [UserTrackerImpl].
- */
+/** Implemented by [UserTrackerImpl]. */
interface UserContextProvider {
+ /**
+ * provides system context, not current user context.
+ *
+ * To get current user context use [createCurrentUserContext] passing [userContext] as context
+ */
val userContext: Context
/**
* Creates the {@code context} with the current user.
+ *
* @see Context#createContextAsUser(UserHandle, int)
*/
fun createCurrentUserContext(context: Context): Context
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
index 75165cb5610e..8703f68f39aa 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
@@ -40,6 +40,8 @@ import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.util.ViewController;
import com.android.systemui.util.time.SystemClock;
+import com.google.android.msdl.domain.MSDLPlayer;
+
import javax.inject.Inject;
/**
@@ -283,12 +285,14 @@ public class BrightnessSliderController extends ViewController<BrightnessSliderV
private final VibratorHelper mVibratorHelper;
private final SystemClock mSystemClock;
private final ActivityStarter mActivityStarter;
+ private final MSDLPlayer mMSDLPlayer;
@Inject
public Factory(
FalsingManager falsingManager,
UiEventLogger uiEventLogger,
VibratorHelper vibratorHelper,
+ MSDLPlayer msdlPlayer,
SystemClock clock,
ActivityStarter activityStarter
) {
@@ -297,6 +301,7 @@ public class BrightnessSliderController extends ViewController<BrightnessSliderV
mVibratorHelper = vibratorHelper;
mSystemClock = clock;
mActivityStarter = activityStarter;
+ mMSDLPlayer = msdlPlayer;
}
/**
@@ -314,6 +319,7 @@ public class BrightnessSliderController extends ViewController<BrightnessSliderV
.inflate(layout, viewRoot, false);
SeekbarHapticPlugin plugin = new SeekbarHapticPlugin(
mVibratorHelper,
+ mMSDLPlayer,
mSystemClock);
HapticSliderViewBinder.bind(viewRoot, plugin);
return new BrightnessSliderController(
diff --git a/packages/SystemUI/src/com/android/systemui/shade/LockscreenHostedDreamGestureListener.kt b/packages/SystemUI/src/com/android/systemui/shade/LockscreenHostedDreamGestureListener.kt
deleted file mode 100644
index 45fc68a793bd..000000000000
--- a/packages/SystemUI/src/com/android/systemui/shade/LockscreenHostedDreamGestureListener.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.shade
-
-import android.os.PowerManager
-import android.view.GestureDetector
-import android.view.MotionEvent
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.data.repository.KeyguardRepository
-import com.android.systemui.plugins.FalsingManager
-import com.android.systemui.plugins.FalsingManager.LOW_PENALTY
-import com.android.systemui.plugins.statusbar.StatusBarStateController
-import com.android.systemui.power.domain.interactor.PowerInteractor
-import com.android.systemui.statusbar.StatusBarState
-import javax.inject.Inject
-
-/**
- * This gestureListener will wake up by tap when the device is dreaming but not dozing, and the
- * selected screensaver is hosted in lockscreen. Tap is gated by the falsing manager.
- *
- * Touches go through the [NotificationShadeWindowViewController].
- */
-@SysUISingleton
-class LockscreenHostedDreamGestureListener
-@Inject
-constructor(
- private val falsingManager: FalsingManager,
- private val powerInteractor: PowerInteractor,
- private val statusBarStateController: StatusBarStateController,
- private val primaryBouncerInteractor: PrimaryBouncerInteractor,
- private val keyguardRepository: KeyguardRepository,
- private val shadeLogger: ShadeLogger,
-) : GestureDetector.SimpleOnGestureListener() {
- private val TAG = this::class.simpleName
-
- override fun onSingleTapUp(e: MotionEvent): Boolean {
- if (shouldHandleMotionEvent()) {
- if (!falsingManager.isFalseTap(LOW_PENALTY)) {
- shadeLogger.d("$TAG#onSingleTapUp tap handled, requesting wakeUpIfDreaming")
- powerInteractor.wakeUpIfDreaming(
- "DREAMING_SINGLE_TAP",
- PowerManager.WAKE_REASON_TAP
- )
- } else {
- shadeLogger.d("$TAG#onSingleTapUp false tap ignored")
- }
- return true
- }
- return false
- }
-
- private fun shouldHandleMotionEvent(): Boolean {
- return keyguardRepository.isActiveDreamLockscreenHosted.value &&
- statusBarStateController.state == StatusBarState.KEYGUARD &&
- !primaryBouncerInteractor.isBouncerShowing()
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAware.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAware.kt
new file mode 100644
index 000000000000..111d335d0d0f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeDisplayAware.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.shade
+
+import javax.inject.Qualifier
+
+/**
+ * Qualifies classes that provide display-specific info for shade window components.
+ *
+ * The Shade window can be moved between displays with different characteristics (e.g., density,
+ * size). This annotation ensures that components within the shade window use the correct context
+ * and resources for the display they are currently on.
+ *
+ * Classes annotated with `@ShadeDisplayAware` (e.g., 'Context`, `Resources`, `LayoutInflater`,
+ * `ConfigurationController`) will be dynamically updated to reflect the current display's
+ * configuration. This ensures consistent rendering even when the shade window is moved to an
+ * external display.
+ */
+@Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class ShadeDisplayAware
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index f99d8f140670..520cbf9d80d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -214,7 +214,7 @@ public class KeyguardIndicationController {
private boolean mEnableBatteryDefender;
private boolean mIncompatibleCharger;
private int mChargingWattage;
- private int mBatteryLevel;
+ private int mBatteryLevel = -1;
private boolean mBatteryPresent = true;
protected long mChargingTimeRemaining;
private Pair<String, BiometricSourceType> mBiometricErrorMessageToShowOnScreenOn;
@@ -1032,12 +1032,16 @@ public class KeyguardIndicationController {
} else if (!TextUtils.isEmpty(mTransientIndication)) {
newIndication = mTransientIndication;
} else if (!mBatteryPresent) {
- // If there is no battery detected, hide the indication and bail
+ // If there is no battery detected, hide the indication area and bail
mIndicationArea.setVisibility(GONE);
return;
} else if (!TextUtils.isEmpty(mAlignmentIndication)) {
useMisalignmentColor = true;
newIndication = mAlignmentIndication;
+ } else if (mBatteryLevel == -1) {
+ // If the battery level is not initialized, hide the indication area
+ mIndicationArea.setVisibility(GONE);
+ return;
} else if (mPowerPluggedIn || mEnableBatteryDefender) {
newIndication = computePowerIndication();
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
index 2930de2fd9ee..0eef8d63c2d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
@@ -44,8 +44,12 @@ import com.android.systemui.util.leak.RotationUtils.ROTATION_NONE
import com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE
import com.android.systemui.util.leak.RotationUtils.ROTATION_UPSIDE_DOWN
import com.android.systemui.util.leak.RotationUtils.Rotation
+import dagger.Module
+import dagger.Provides
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
import java.util.concurrent.Executor
-import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
@@ -63,26 +67,57 @@ import kotlinx.coroutines.launch
* NOTE: any operation that modifies views directly must run on the provided executor, because these
* views are owned by ScreenDecorations and it runs in its own thread
*/
-@SysUISingleton
-open class PrivacyDotViewController
-@Inject
+interface PrivacyDotViewController {
+
+ // Only can be modified on @UiThread
+ var currentViewState: ViewState
+
+ var showingListener: ShowingListener?
+
+ fun setUiExecutor(e: DelayableExecutor)
+
+ fun getUiExecutor(): DelayableExecutor?
+
+ @UiThread fun setNewRotation(rot: Int)
+
+ @UiThread fun hideDotView(dot: View, animate: Boolean)
+
+ @UiThread fun showDotView(dot: View, animate: Boolean)
+
+ // Update the gravity and margins of the privacy views
+ @UiThread fun updateRotations(rotation: Int, paddingTop: Int)
+
+ @UiThread fun setCornerSizes(state: ViewState)
+
+ fun initialize(topLeft: View, topRight: View, bottomLeft: View, bottomRight: View)
+
+ @UiThread fun updateDotView(state: ViewState)
+
+ interface ShowingListener {
+ fun onPrivacyDotShown(v: View?)
+
+ fun onPrivacyDotHidden(v: View?)
+ }
+}
+
+open class PrivacyDotViewControllerImpl
+@AssistedInject
constructor(
@Main private val mainExecutor: Executor,
- @Application scope: CoroutineScope,
+ @Assisted scope: CoroutineScope,
private val stateController: StatusBarStateController,
- private val configurationController: ConfigurationController,
- private val contentInsetsProvider: StatusBarContentInsetsProvider,
+ @Assisted private val configurationController: ConfigurationController,
+ @Assisted private val contentInsetsProvider: StatusBarContentInsetsProvider,
private val animationScheduler: SystemStatusAnimationScheduler,
- shadeInteractor: ShadeInteractor?
-) {
+ shadeInteractor: ShadeInteractor?,
+) : PrivacyDotViewController {
private lateinit var tl: View
private lateinit var tr: View
private lateinit var bl: View
private lateinit var br: View
// Only can be modified on @UiThread
- var currentViewState: ViewState = ViewState()
- get() = field
+ override var currentViewState: ViewState = ViewState()
@GuardedBy("lock")
private var nextViewState: ViewState = currentViewState.copy()
@@ -100,11 +135,7 @@ constructor(
private val views: Sequence<View>
get() = if (!this::tl.isInitialized) sequenceOf() else sequenceOf(tl, tr, br, bl)
- var showingListener: ShowingListener? = null
- set(value) {
- field = value
- }
- get() = field
+ override var showingListener: PrivacyDotViewController.ShowingListener? = null
init {
contentInsetsProvider.addCallback(
@@ -153,16 +184,16 @@ constructor(
}
}
- fun setUiExecutor(e: DelayableExecutor) {
+ override fun setUiExecutor(e: DelayableExecutor) {
uiExecutor = e
}
- fun getUiExecutor(): DelayableExecutor? {
+ override fun getUiExecutor(): DelayableExecutor? {
return uiExecutor
}
@UiThread
- fun setNewRotation(rot: Int) {
+ override fun setNewRotation(rot: Int) {
dlog("updateRotation: $rot")
val isRtl: Boolean
@@ -187,13 +218,13 @@ constructor(
rotation = rot,
paddingTop = paddingTop,
designatedCorner = newCorner,
- cornerIndex = index
+ cornerIndex = index,
)
}
}
@UiThread
- fun hideDotView(dot: View, animate: Boolean) {
+ override fun hideDotView(dot: View, animate: Boolean) {
dot.clearAnimation()
if (animate) {
dot.animate()
@@ -212,7 +243,7 @@ constructor(
}
@UiThread
- fun showDotView(dot: View, animate: Boolean) {
+ override fun showDotView(dot: View, animate: Boolean) {
dot.clearAnimation()
if (animate) {
dot.visibility = View.VISIBLE
@@ -229,9 +260,8 @@ constructor(
showingListener?.onPrivacyDotShown(dot)
}
- // Update the gravity and margins of the privacy views
@UiThread
- open fun updateRotations(rotation: Int, paddingTop: Int) {
+ override fun updateRotations(rotation: Int, paddingTop: Int) {
// To keep a view in the corner, its gravity is always the description of its current corner
// Therefore, just figure out which view is in which corner. This turns out to be something
// like (myCorner - rot) mod 4, where topLeft = 0, topRight = 1, etc. and portrait = 0, and
@@ -262,7 +292,7 @@ constructor(
}
@UiThread
- open fun setCornerSizes(state: ViewState) {
+ override fun setCornerSizes(state: ViewState) {
// StatusBarContentInsetsProvider can tell us the location of the privacy indicator dot
// in every rotation. The only thing we need to check is rtl
val rtl = state.layoutRtl
@@ -415,7 +445,7 @@ constructor(
}
}
- fun initialize(topLeft: View, topRight: View, bottomLeft: View, bottomRight: View) {
+ override fun initialize(topLeft: View, topRight: View, bottomLeft: View, bottomRight: View) {
if (
this::tl.isInitialized &&
this::tr.isInitialized &&
@@ -457,7 +487,7 @@ constructor(
landscapeRect = right,
upsideDownRect = bottom,
paddingTop = paddingTop,
- layoutRtl = rtl
+ layoutRtl = rtl,
)
}
}
@@ -533,7 +563,7 @@ constructor(
}
@UiThread
- open fun updateDotView(state: ViewState) {
+ override fun updateDotView(state: ViewState) {
val shouldShow = state.shouldShowDot()
if (shouldShow != currentViewState.shouldShowDot()) {
if (shouldShow && state.designatedCorner != null) {
@@ -553,7 +583,7 @@ constructor(
nextViewState =
nextViewState.copy(
systemPrivacyEventIsActive = true,
- contentDescription = contentDescr
+ contentDescription = contentDescr,
)
}
@@ -595,15 +625,18 @@ constructor(
seascapeRect = rects[0],
portraitRect = rects[1],
landscapeRect = rects[2],
- upsideDownRect = rects[3]
+ upsideDownRect = rects[3],
)
}
}
- interface ShowingListener {
- fun onPrivacyDotShown(v: View?)
-
- fun onPrivacyDotHidden(v: View?)
+ @AssistedFactory
+ interface Factory {
+ fun create(
+ scope: CoroutineScope,
+ configurationController: ConfigurationController,
+ contentInsetsProvider: StatusBarContentInsetsProvider,
+ ): PrivacyDotViewControllerImpl
}
}
@@ -662,7 +695,7 @@ data class ViewState(
val paddingTop: Int = 0,
val cornerIndex: Int = -1,
val designatedCorner: View? = null,
- val contentDescription: String? = null
+ val contentDescription: String? = null,
) {
fun shouldShowDot(): Boolean {
return systemPrivacyEventIsActive && !shadeExpanded && !qsExpanded
@@ -687,3 +720,18 @@ data class ViewState(
}
}
}
+
+@Module
+object PrivacyDotViewControllerModule {
+
+ @Provides
+ @SysUISingleton
+ fun controller(
+ factory: PrivacyDotViewControllerImpl.Factory,
+ @Application scope: CoroutineScope,
+ configurationController: ConfigurationController,
+ contentInsetsProvider: StatusBarContentInsetsProvider,
+ ): PrivacyDotViewController {
+ return factory.create(scope, configurationController, contentInsetsProvider)
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.kt
index 231a0b0b21cb..9fe4a5499ceb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationActivityStarter.kt
@@ -32,13 +32,13 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
interface NotificationActivityStarter {
/** Called when the user clicks on the notification bubble icon. */
- fun onNotificationBubbleIconClicked(entry: NotificationEntry?)
+ fun onNotificationBubbleIconClicked(entry: NotificationEntry)
/** Called when the user clicks on the surface of a notification. */
- fun onNotificationClicked(entry: NotificationEntry?, row: ExpandableNotificationRow?)
+ fun onNotificationClicked(entry: NotificationEntry, row: ExpandableNotificationRow)
/** Called when the user clicks on a button in the notification guts which fires an intent. */
- fun startNotificationGutsIntent(intent: Intent?, appUid: Int, row: ExpandableNotificationRow?)
+ fun startNotificationGutsIntent(intent: Intent, appUid: Int, row: ExpandableNotificationRow)
/**
* Called when the user clicks "Manage" or "History" in the Shade. Prefer using
@@ -56,7 +56,7 @@ interface NotificationActivityStarter {
fun startSettingsIntent(view: View, intentInfo: SettingsIntent)
/** Called when the user succeed to drop notification to proper target view. */
- fun onDragSuccess(entry: NotificationEntry?)
+ fun onDragSuccess(entry: NotificationEntry)
val isCollapsingToShowActivityOverLockscreen: Boolean
get() = false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionCache.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionCache.kt
index 2ee1dffd14f3..958001625a07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionCache.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollectionCache.kt
@@ -35,6 +35,9 @@ import java.util.concurrent.atomic.AtomicInteger
* This cache is safe for multithreaded usage, and is recommended for objects that take a while to
* resolve (such as drawables, or things that require binder calls). As such, [getOrFetch] is
* recommended to be run on a background thread, while [purge] can be done from any thread.
+ *
+ * Important: This cache does NOT have a maximum size, cleaning it up (via [purge]) is the
+ * responsibility of the caller, to avoid keeping things in memory unnecessarily.
*/
@SuppressLint("DumpableNotRegistered") // this will be dumped by container classes
class NotifCollectionCache<V>(
@@ -151,7 +154,7 @@ class NotifCollectionCache<V>(
* purge((c)); // deletes a from the cache and marks b for deletion, etc.
* ```
*/
- fun purge(wantedKeys: List<String>) {
+ fun purge(wantedKeys: Collection<String>) {
for ((key, entry) in cache) {
if (key in wantedKeys) {
entry.resetLives()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
index 9b075a650b48..f75163d2662b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
@@ -27,6 +27,7 @@ import android.os.Trace;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -49,13 +50,18 @@ import com.android.systemui.statusbar.notification.collection.render.NotifViewBa
import com.android.systemui.statusbar.notification.collection.render.NotifViewController;
import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager.NotifInflationErrorListener;
+import com.android.systemui.statusbar.notification.row.icon.AppIconProvider;
+import com.android.systemui.statusbar.notification.row.icon.NotificationIconStyleProvider;
import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.inject.Inject;
@@ -104,6 +110,8 @@ public class PreparationCoordinator implements Coordinator {
/** How long we can delay a group while waiting for all children to inflate */
private final long mMaxGroupInflationDelay;
private final BindEventManagerImpl mBindEventManager;
+ private final AppIconProvider mAppIconProvider;
+ private final NotificationIconStyleProvider mNotificationIconStyleProvider;
@Inject
public PreparationCoordinator(
@@ -113,7 +121,9 @@ public class PreparationCoordinator implements Coordinator {
NotifViewBarn viewBarn,
NotifUiAdjustmentProvider adjustmentProvider,
IStatusBarService service,
- BindEventManagerImpl bindEventManager) {
+ BindEventManagerImpl bindEventManager,
+ AppIconProvider appIconProvider,
+ NotificationIconStyleProvider notificationIconStyleProvider) {
this(
logger,
notifInflater,
@@ -122,6 +132,8 @@ public class PreparationCoordinator implements Coordinator {
adjustmentProvider,
service,
bindEventManager,
+ appIconProvider,
+ notificationIconStyleProvider,
CHILD_BIND_CUTOFF,
MAX_GROUP_INFLATION_DELAY);
}
@@ -135,6 +147,8 @@ public class PreparationCoordinator implements Coordinator {
NotifUiAdjustmentProvider adjustmentProvider,
IStatusBarService service,
BindEventManagerImpl bindEventManager,
+ AppIconProvider appIconProvider,
+ NotificationIconStyleProvider notificationIconStyleProvider,
int childBindCutoff,
long maxGroupInflationDelay) {
mLogger = logger;
@@ -146,6 +160,8 @@ public class PreparationCoordinator implements Coordinator {
mChildBindCutoff = childBindCutoff;
mMaxGroupInflationDelay = maxGroupInflationDelay;
mBindEventManager = bindEventManager;
+ mAppIconProvider = appIconProvider;
+ mNotificationIconStyleProvider = notificationIconStyleProvider;
}
@Override
@@ -155,6 +171,9 @@ public class PreparationCoordinator implements Coordinator {
() -> mNotifInflatingFilter.invalidateList("adjustmentProviderChanged"));
pipeline.addCollectionListener(mNotifCollectionListener);
+ if (android.app.Flags.notificationsRedesignAppIcons()) {
+ pipeline.addOnBeforeTransformGroupsListener(this::purgeCaches);
+ }
// Inflate after grouping/sorting since that affects what views to inflate.
pipeline.addOnBeforeFinalizeFilterListener(this::inflateAllRequiredViews);
pipeline.addFinalizeFilter(mNotifInflationErrorFilter);
@@ -260,6 +279,29 @@ public class PreparationCoordinator implements Coordinator {
}
};
+ private void purgeCaches(Collection<ListEntry> entries) {
+ Set<String> wantedPackages = getPackages(entries);
+ mAppIconProvider.purgeCache(wantedPackages);
+ mNotificationIconStyleProvider.purgeCache(wantedPackages);
+ }
+
+ /**
+ * Get all app packages present in {@param entries}.
+ */
+ private static @NonNull Set<String> getPackages(Collection<ListEntry> entries) {
+ Set<String> packages = new HashSet<>();
+ for (ListEntry entry : entries) {
+ NotificationEntry notificationEntry = entry.getRepresentativeEntry();
+ if (notificationEntry == null) {
+ Log.wtf(TAG, "notification entry " + entry.getKey()
+ + " has no representative entry");
+ continue;
+ }
+ packages.add(notificationEntry.getSbn().getPackageName());
+ }
+ return packages;
+ }
+
private void inflateAllRequiredViews(List<ListEntry> entries) {
for (int i = 0, size = entries.size(); i < size; i++) {
ListEntry entry = entries.get(i);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/EnsureEnrViewsVisibility.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/EnsureEnrViewsVisibility.kt
new file mode 100644
index 000000000000..aa63f4ddbd45
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/EnsureEnrViewsVisibility.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.row
+
+import com.android.systemui.Flags
+import com.android.systemui.flags.FlagToken
+import com.android.systemui.flags.RefactorFlagUtils
+
+/** Helper for reading or using the ensure enr views visibility flag state. */
+@Suppress("NOTHING_TO_INLINE")
+object EnsureEnrViewsVisibility {
+ /** The aconfig flag name */
+ const val FLAG_NAME = Flags.FLAG_ENSURE_ENR_VIEWS_VISIBILITY
+
+ /** A token used for dependency declaration */
+ val token: FlagToken
+ get() = FlagToken(FLAG_NAME, isEnabled)
+
+ /** Is the refactor enabled */
+ @JvmStatic
+ inline val isEnabled
+ get() = Flags.ensureEnrViewsVisibility()
+
+ /**
+ * Called to ensure code is only run when the flag is enabled. This protects users from the
+ * unintended behaviors caused by accidentally running new logic, while also crashing on an eng
+ * build to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ inline fun isUnexpectedlyInLegacyMode() =
+ RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, FLAG_NAME)
+
+ /**
+ * Called to ensure code is only run when the flag is disabled. This will throw an exception if
+ * the flag is not enabled to ensure that the refactor author catches issues in testing.
+ * Caution!! Using this check incorrectly will cause crashes in nextfood builds!
+ */
+ @JvmStatic
+ inline fun assertInNewMode() = RefactorFlagUtils.assertInNewMode(isEnabled, FLAG_NAME)
+
+ /**
+ * Called to ensure code is only run when the flag is disabled. This will throw an exception if
+ * the flag is enabled to ensure that the refactor author catches issues in testing.
+ */
+ @JvmStatic
+ inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 933f79341b27..a4c43a1b65c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -2507,6 +2507,10 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
}
private void updateChildrenVisibility() {
+ if (EnsureEnrViewsVisibility.isEnabled()) {
+ mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
+ }
+
boolean hideContentWhileLaunching = mExpandAnimationRunning && mGuts != null
&& mGuts.isExposed();
mPrivateLayout.setVisibility(!mShowingPublic && !mIsSummaryWithChildren
@@ -3073,7 +3077,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
} else {
mLogger.logSkipResetAllContentAlphas(getEntry());
}
- mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
+
+ if (!EnsureEnrViewsVisibility.isEnabled()) {
+ // mPublicLayout.setVisibility moved to updateChildrenVisibility when the flag is on
+ // in order to ensure public and private views are not visible
+ // together at the same time.
+ mPublicLayout.setVisibility(mShowingPublic ? View.VISIBLE : View.INVISIBLE);
+ }
updateChildrenVisibility();
} else {
animateShowingPublic(delay, duration, mShowingPublic);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/icon/AppIconProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/icon/AppIconProvider.kt
index 24b5cf1aa33b..0ddf9f7270df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/icon/AppIconProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/icon/AppIconProvider.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.notification.row.icon
+import android.annotation.WorkerThread
import android.app.ActivityManager
import android.app.Flags
import android.content.Context
@@ -27,20 +28,45 @@ import android.graphics.drawable.Drawable
import android.util.Log
import com.android.internal.R
import com.android.launcher3.icons.BaseIconFactory
+import com.android.systemui.Dumpable
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.notification.collection.NotifCollectionCache
+import com.android.systemui.util.asIndenting
+import com.android.systemui.util.withIncreasedIndent
import dagger.Module
import dagger.Provides
+import java.io.PrintWriter
import javax.inject.Inject
import javax.inject.Provider
/** A provider used to cache and fetch app icons used by notifications. */
interface AppIconProvider {
+ /**
+ * Loads the icon corresponding to [packageName] into cache, or fetches it from there if already
+ * present. This should only be called from the background.
+ */
@Throws(NameNotFoundException::class)
+ @WorkerThread
fun getOrFetchAppIcon(packageName: String, context: Context): Drawable
+
+ /**
+ * Mark all the entries in the cache that are NOT in [wantedPackages] to be cleared. If they're
+ * still not needed on the next call of this method (made after a timeout of 1s, in case they
+ * happen more frequently than that), they will be purged. This can be done from any thread.
+ */
+ fun purgeCache(wantedPackages: Collection<String>)
}
@SysUISingleton
-class AppIconProviderImpl @Inject constructor(private val sysuiContext: Context) : AppIconProvider {
+class AppIconProviderImpl
+@Inject
+constructor(private val sysuiContext: Context, dumpManager: DumpManager) :
+ AppIconProvider, Dumpable {
+ init {
+ dumpManager.registerNormalDumpable(TAG, this)
+ }
+
private val iconFactory: BaseIconFactory
get() {
val isLowRam = ActivityManager.isLowRamDeviceStatic()
@@ -53,13 +79,42 @@ class AppIconProviderImpl @Inject constructor(private val sysuiContext: Context)
return BaseIconFactory(sysuiContext, res.configuration.densityDpi, iconSize)
}
+ private val cache = NotifCollectionCache<Drawable>()
+
override fun getOrFetchAppIcon(packageName: String, context: Context): Drawable {
+ return cache.getOrFetch(packageName) { fetchAppIcon(packageName, context) }
+ }
+
+ @WorkerThread
+ private fun fetchAppIcon(packageName: String, context: Context): BitmapDrawable {
val icon = context.packageManager.getApplicationIcon(packageName)
return BitmapDrawable(
context.resources,
iconFactory.createScaledBitmap(icon, BaseIconFactory.MODE_HARDWARE),
)
}
+
+ override fun purgeCache(wantedPackages: Collection<String>) {
+ cache.purge(wantedPackages)
+ }
+
+ override fun dump(pwOrig: PrintWriter, args: Array<out String>) {
+ val pw = pwOrig.asIndenting()
+
+ pw.println("cache information:")
+ pw.withIncreasedIndent { cache.dump(pw, args) }
+
+ val iconFactory = iconFactory
+ pw.println("icon factory information:")
+ pw.withIncreasedIndent {
+ pw.println("fullResIconDpi = ${iconFactory.fullResIconDpi}")
+ pw.println("iconSize = ${iconFactory.iconBitmapSize}")
+ }
+ }
+
+ companion object {
+ const val TAG = "AppIconProviderImpl"
+ }
}
class NoOpIconProvider : AppIconProvider {
@@ -71,6 +126,10 @@ class NoOpIconProvider : AppIconProvider {
Log.wtf(TAG, "NoOpIconProvider should not be used anywhere.")
return ColorDrawable(Color.WHITE)
}
+
+ override fun purgeCache(wantedPackages: Collection<String>) {
+ Log.wtf(TAG, "NoOpIconProvider should not be used anywhere.")
+ }
}
@Module
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/icon/NotificationIconStyleProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/icon/NotificationIconStyleProvider.kt
index 165c1a7803a9..35e38c2c0c14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/icon/NotificationIconStyleProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/icon/NotificationIconStyleProvider.kt
@@ -22,9 +22,15 @@ import android.content.Context
import android.content.pm.ApplicationInfo
import android.service.notification.StatusBarNotification
import android.util.Log
+import com.android.systemui.Dumpable
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.notification.collection.NotifCollectionCache
+import com.android.systemui.util.asIndenting
+import com.android.systemui.util.withIncreasedIndent
import dagger.Module
import dagger.Provides
+import java.io.PrintWriter
import javax.inject.Inject
import javax.inject.Provider
@@ -33,15 +39,35 @@ import javax.inject.Provider
* notifications.
*/
interface NotificationIconStyleProvider {
+ /**
+ * Determines whether the [notification] should display the app icon instead of the small icon.
+ * This can result in a binder call, and therefore should only be called from the background.
+ */
@WorkerThread
fun shouldShowAppIcon(notification: StatusBarNotification, context: Context): Boolean
+
+ /**
+ * Mark all the entries in the cache that are NOT in [wantedPackages] to be cleared. If they're
+ * still not needed on the next call of this method (made after a timeout of 1s, in case they
+ * happen more frequently than that), they will be purged. This can be done from any thread.
+ */
+ fun purgeCache(wantedPackages: Collection<String>)
}
@SysUISingleton
-class NotificationIconStyleProviderImpl @Inject constructor() : NotificationIconStyleProvider {
+class NotificationIconStyleProviderImpl @Inject constructor(dumpManager: DumpManager) :
+ NotificationIconStyleProvider, Dumpable {
+ init {
+ dumpManager.registerNormalDumpable(TAG, this)
+ }
+
+ private val cache = NotifCollectionCache<Boolean>()
+
override fun shouldShowAppIcon(notification: StatusBarNotification, context: Context): Boolean {
val packageContext = notification.getPackageContext(context)
- return !belongsToHeadlessSystemApp(packageContext)
+ return cache.getOrFetch(notification.packageName) {
+ !belongsToHeadlessSystemApp(packageContext)
+ }
}
@WorkerThread
@@ -62,6 +88,20 @@ class NotificationIconStyleProviderImpl @Inject constructor() : NotificationIcon
return false
}
}
+
+ override fun purgeCache(wantedPackages: Collection<String>) {
+ cache.purge(wantedPackages)
+ }
+
+ override fun dump(pwOrig: PrintWriter, args: Array<out String>) {
+ val pw = pwOrig.asIndenting()
+ pw.println("cache information:")
+ pw.withIncreasedIndent { cache.dump(pw, args) }
+ }
+
+ companion object {
+ const val TAG = "NotificationIconStyleProviderImpl"
+ }
}
class NoOpIconStyleProvider : NotificationIconStyleProvider {
@@ -73,6 +113,10 @@ class NoOpIconStyleProvider : NotificationIconStyleProvider {
Log.wtf(TAG, "NoOpIconStyleProvider should not be used anywhere.")
return true
}
+
+ override fun purgeCache(wantedPackages: Collection<String>) {
+ Log.wtf(TAG, "NoOpIconStyleProvider should not be used anywhere.")
+ }
}
@Module
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
index a8c823c35213..858cac111525 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
@@ -29,9 +29,8 @@ import dagger.assisted.AssistedInject
class ConfigurationControllerImpl
@AssistedInject
-constructor(
- @Assisted private val context: Context,
-) : ConfigurationController, StatusBarConfigurationController {
+constructor(@Assisted private val context: Context) :
+ ConfigurationController, StatusBarConfigurationController {
private val listeners: MutableList<ConfigurationListener> = ArrayList()
private val lastConfig = Configuration()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationForwarder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationForwarder.kt
new file mode 100644
index 000000000000..3fd46fc484a9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationForwarder.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone
+
+import android.content.res.Configuration
+
+/**
+ * Used to forward a configuration change to other components.
+ *
+ * This is commonly used to propagate configs to [ConfigurationController]. Note that there could be
+ * different configuration forwarder, for example each display, window or group of classes (e.g.
+ * shade window classes).
+ */
+interface ConfigurationForwarder {
+ /** Should be called when a new configuration is received. */
+ fun onConfigurationChanged(newConfiguration: Configuration)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 74c6e72d3400..f7fea7b0d334 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -1535,6 +1535,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
}
public boolean interceptMediaKey(KeyEvent event) {
+ ComposeBouncerFlags.assertInLegacyMode();
return mPrimaryBouncerView.getDelegate() != null
&& mPrimaryBouncerView.getDelegate().interceptMediaKey(event);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
index 93db2db918b0..af98311c937f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -20,7 +20,6 @@ import static android.app.ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED
import static android.service.notification.NotificationListenerService.REASON_CLICK;
import static com.android.systemui.statusbar.phone.CentralSurfaces.getActivityOptions;
-import static com.android.systemui.util.kotlin.NullabilityKt.expectNotNull;
import android.app.ActivityManager;
import android.app.ActivityOptions;
@@ -231,8 +230,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
* @param entry notification that bubble icon was clicked
*/
@Override
- public void onNotificationBubbleIconClicked(NotificationEntry entry) {
- expectNotNull(TAG, "entry", entry);
+ public void onNotificationBubbleIconClicked(@NonNull NotificationEntry entry) {
Runnable action = () -> {
mBubblesManagerOptional.ifPresent(bubblesManager ->
bubblesManager.onUserChangedBubble(entry, !entry.isBubble()));
@@ -258,9 +256,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
* @param row row for that notification
*/
@Override
- public void onNotificationClicked(NotificationEntry entry, ExpandableNotificationRow row) {
- expectNotNull(TAG, "entry", entry);
- expectNotNull(TAG, "row", row);
+ public void onNotificationClicked(@NonNull NotificationEntry entry,
+ @NonNull ExpandableNotificationRow row) {
mLogger.logStartingActivityFromClick(entry, row.isHeadsUpState(),
mKeyguardStateController.isVisible(),
mNotificationShadeWindowController.getPanelExpanded());
@@ -442,8 +439,7 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
* @param entry notification entry that is dropped.
*/
@Override
- public void onDragSuccess(NotificationEntry entry) {
- expectNotNull(TAG, "entry", entry);
+ public void onDragSuccess(@NonNull NotificationEntry entry) {
// this method is not responsible for intent sending.
// will focus follow operation only after drag-and-drop that notification.
final NotificationVisibility nv = mVisibilityProvider.obtain(entry, true);
@@ -534,10 +530,8 @@ public class StatusBarNotificationActivityStarter implements NotificationActivit
}
@Override
- public void startNotificationGutsIntent(final Intent intent, final int appUid,
- ExpandableNotificationRow row) {
- expectNotNull(TAG, "intent", intent);
- expectNotNull(TAG, "row", row);
+ public void startNotificationGutsIntent(@NonNull final Intent intent, final int appUid,
+ @NonNull ExpandableNotificationRow row) {
boolean animate = mActivityStarter.shouldAnimateLaunch(true /* isActivityIntent */);
ActivityStarter.OnDismissAction onDismissAction = new ActivityStarter.OnDismissAction() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt
index 09e191dd1911..92d0ebecf8d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt
@@ -32,6 +32,7 @@ import com.android.systemui.statusbar.core.StatusBarInitializerStore
import com.android.systemui.statusbar.core.StatusBarOrchestrator
import com.android.systemui.statusbar.core.StatusBarSimpleFragment
import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore
+import com.android.systemui.statusbar.events.PrivacyDotViewControllerModule
import com.android.systemui.statusbar.phone.CentralSurfacesCommandQueueCallbacks
import com.android.systemui.statusbar.window.StatusBarWindowControllerStore
import com.android.systemui.statusbar.window.data.repository.StatusBarWindowStateRepositoryStore
@@ -45,7 +46,7 @@ import dagger.multibindings.IntoMap
import kotlinx.coroutines.CoroutineScope
/** Similar in purpose to [StatusBarModule], but scoped only to phones */
-@Module
+@Module(includes = [PrivacyDotViewControllerModule::class])
interface StatusBarPhoneModule {
@Binds
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
index cec77c12a40b..1bb4e8c66ef1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ConfigurationController.java
@@ -16,16 +16,15 @@ package com.android.systemui.statusbar.policy;
import android.content.res.Configuration;
+import com.android.systemui.statusbar.phone.ConfigurationForwarder;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
/**
* Common listener for configuration or subsets of configuration changes (like density or
* font scaling), providing easy static dependence on these events.
*/
-public interface ConfigurationController extends CallbackController<ConfigurationListener> {
-
- /** Alert controller of a change in the configuration. */
- void onConfigurationChanged(Configuration newConfiguration);
+public interface ConfigurationController extends CallbackController<ConfigurationListener>,
+ ConfigurationForwarder {
/** Alert controller of a change in between light and dark themes. */
void notifyThemeChanged();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
index c256e6430af9..00116aa71246 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
@@ -40,6 +40,7 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.res.R;
import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
@@ -71,6 +72,7 @@ public class KeyguardStateControllerImpl implements KeyguardStateController {
new UpdateMonitorCallback();
private final Lazy<KeyguardUnlockAnimationController> mUnlockAnimationControllerLazy;
private final KeyguardUpdateMonitorLogger mLogger;
+ private final Lazy<KeyguardInteractor> mKeyguardInteractorLazy;
private boolean mCanDismissLockScreen;
private boolean mShowing;
@@ -123,6 +125,7 @@ public class KeyguardStateControllerImpl implements KeyguardStateController {
Lazy<KeyguardUnlockAnimationController> keyguardUnlockAnimationController,
KeyguardUpdateMonitorLogger logger,
DumpManager dumpManager,
+ Lazy<KeyguardInteractor> keyguardInteractor,
FeatureFlags featureFlags,
SelectedUserInteractor userInteractor) {
mContext = context;
@@ -133,6 +136,7 @@ public class KeyguardStateControllerImpl implements KeyguardStateController {
mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
mUnlockAnimationControllerLazy = keyguardUnlockAnimationController;
mFeatureFlags = featureFlags;
+ mKeyguardInteractorLazy = keyguardInteractor;
dumpManager.registerDumpable(getClass().getSimpleName(), this);
@@ -354,6 +358,7 @@ public class KeyguardStateControllerImpl implements KeyguardStateController {
Trace.traceCounter(Trace.TRACE_TAG_APP, "keyguardGoingAway",
keyguardGoingAway ? 1 : 0);
mKeyguardGoingAway = keyguardGoingAway;
+ mKeyguardInteractorLazy.get().setIsKeyguardGoingAway(keyguardGoingAway);
invokeForEachCallback(Callback::onKeyguardGoingAwayChanged);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
index b81af86b0779..c7bd5a1bb9a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
@@ -37,6 +37,7 @@ import com.android.systemui.statusbar.connectivity.NetworkController;
import com.android.systemui.statusbar.connectivity.NetworkControllerImpl;
import com.android.systemui.statusbar.connectivity.WifiPickerTrackerFactory;
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
+import com.android.systemui.statusbar.phone.ConfigurationForwarder;
import com.android.systemui.statusbar.policy.BatteryControllerLogger;
import com.android.systemui.statusbar.policy.BluetoothController;
import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
@@ -186,6 +187,13 @@ public interface StatusBarPolicyModule {
DevicePostureControllerImpl devicePostureControllerImpl);
/** */
+ @Binds
+ @SysUISingleton
+ @GlobalConfig
+ ConfigurationForwarder provideGlobalConfigurationForwarder(
+ @GlobalConfig ConfigurationController configurationController);
+
+ /** */
@Provides
@SysUISingleton
@GlobalConfig
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt
index e89a31f8fad3..618722a79a6f 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/BackGestureTutorialScreen.kt
@@ -27,7 +27,10 @@ import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialScreenCon
import com.android.systemui.inputdevice.tutorial.ui.composable.rememberColorFilterProperty
import com.android.systemui.res.R
import com.android.systemui.touchpad.tutorial.ui.gesture.BackGestureRecognizer
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureFlowAdapter
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureRecognizer
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
@Composable
fun BackGestureTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: () -> Unit) {
@@ -48,7 +51,17 @@ fun BackGestureTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: () -> Uni
),
)
val recognizer = rememberBackGestureRecognizer(LocalContext.current.resources)
- GestureTutorialScreen(screenConfig, recognizer, onDoneButtonClicked, onBack)
+ val gestureUiState: Flow<GestureUiState> =
+ remember(recognizer) {
+ GestureFlowAdapter(recognizer).gestureStateAsFlow.map {
+ it.toGestureUiState(
+ progressStartMark = "",
+ progressEndMark = "",
+ successAnimation = R.raw.trackpad_back_success,
+ )
+ }
+ }
+ GestureTutorialScreen(screenConfig, recognizer, gestureUiState, onDoneButtonClicked, onBack)
}
@Composable
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt
index 7899f5b42a25..11e1ff49074a 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/GestureTutorialScreen.kt
@@ -17,6 +17,7 @@
package com.android.systemui.touchpad.tutorial.ui.composable
import androidx.activity.compose.BackHandler
+import androidx.annotation.RawRes
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Box
@@ -31,23 +32,49 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInteropFilter
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.systemui.inputdevice.tutorial.ui.composable.ActionTutorialContent
import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialActionState
import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialScreenConfig
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.Finished
+import com.android.systemui.touchpad.tutorial.ui.composable.GestureUiState.NotStarted
import com.android.systemui.touchpad.tutorial.ui.gesture.EasterEggGestureMonitor
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureRecognizer
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.Finished
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.InProgress
-import com.android.systemui.touchpad.tutorial.ui.gesture.GestureState.NotStarted
import com.android.systemui.touchpad.tutorial.ui.gesture.TouchpadGestureHandler
+import kotlinx.coroutines.flow.Flow
-fun GestureState.toTutorialActionState(): TutorialActionState {
+sealed interface GestureUiState {
+ data object NotStarted : GestureUiState
+
+ data class Finished(@RawRes val successAnimation: Int) : GestureUiState
+
+ data class InProgress(
+ val progress: Float = 0f,
+ val progressStartMark: String = "",
+ val progressEndMark: String = "",
+ ) : GestureUiState
+}
+
+fun GestureState.toGestureUiState(
+ progressStartMark: String,
+ progressEndMark: String,
+ successAnimation: Int,
+): GestureUiState {
+ return when (this) {
+ GestureState.NotStarted -> NotStarted
+ is GestureState.InProgress ->
+ GestureUiState.InProgress(this.progress, progressStartMark, progressEndMark)
+ is GestureState.Finished -> GestureUiState.Finished(successAnimation)
+ }
+}
+
+fun GestureUiState.toTutorialActionState(): TutorialActionState {
return when (this) {
NotStarted -> TutorialActionState.NotStarted
// progress is disabled for now as views are not ready to handle varying progress
- is InProgress -> TutorialActionState.InProgress(0f)
- Finished -> TutorialActionState.Finished
+ is GestureUiState.InProgress -> TutorialActionState.InProgress(progress = 0f)
+ is Finished -> TutorialActionState.Finished
}
}
@@ -55,15 +82,13 @@ fun GestureState.toTutorialActionState(): TutorialActionState {
fun GestureTutorialScreen(
screenConfig: TutorialScreenConfig,
gestureRecognizer: GestureRecognizer,
+ gestureUiStateFlow: Flow<GestureUiState>,
onDoneButtonClicked: () -> Unit,
onBack: () -> Unit,
) {
BackHandler(onBack = onBack)
- var gestureState: GestureState by remember { mutableStateOf(NotStarted) }
var easterEggTriggered by remember { mutableStateOf(false) }
- LaunchedEffect(gestureRecognizer) {
- gestureRecognizer.addGestureStateCallback { gestureState = it }
- }
+ val gestureState by gestureUiStateFlow.collectAsStateWithLifecycle(NotStarted)
val easterEggMonitor = EasterEggGestureMonitor { easterEggTriggered = true }
val gestureHandler =
remember(gestureRecognizer) { TouchpadGestureHandler(gestureRecognizer, easterEggMonitor) }
@@ -84,7 +109,7 @@ fun GestureTutorialScreen(
@Composable
private fun TouchpadGesturesHandlingBox(
gestureHandler: TouchpadGestureHandler,
- gestureState: GestureState,
+ gestureState: GestureUiState,
easterEggTriggered: Boolean,
resetEasterEggFlag: () -> Unit,
modifier: Modifier = Modifier,
@@ -110,7 +135,7 @@ private fun TouchpadGesturesHandlingBox(
.pointerInteropFilter(
onTouchEvent = { event ->
// FINISHED is the final state so we don't need to process touches anymore
- if (gestureState == Finished) {
+ if (gestureState is Finished) {
false
} else {
gestureHandler.onMotionEvent(event)
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt
index 3ddf760b9704..05871ce91e39 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/HomeGestureTutorialScreen.kt
@@ -25,8 +25,11 @@ import com.android.compose.theme.LocalAndroidColorScheme
import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialScreenConfig
import com.android.systemui.inputdevice.tutorial.ui.composable.rememberColorFilterProperty
import com.android.systemui.res.R
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureFlowAdapter
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureRecognizer
import com.android.systemui.touchpad.tutorial.ui.gesture.HomeGestureRecognizer
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
@Composable
fun HomeGestureTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: () -> Unit) {
@@ -47,7 +50,17 @@ fun HomeGestureTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: () -> Uni
),
)
val recognizer = rememberHomeGestureRecognizer(LocalContext.current.resources)
- GestureTutorialScreen(screenConfig, recognizer, onDoneButtonClicked, onBack)
+ val gestureUiState: Flow<GestureUiState> =
+ remember(recognizer) {
+ GestureFlowAdapter(recognizer).gestureStateAsFlow.map {
+ it.toGestureUiState(
+ progressStartMark = "",
+ progressEndMark = "",
+ successAnimation = R.raw.trackpad_home_success,
+ )
+ }
+ }
+ GestureTutorialScreen(screenConfig, recognizer, gestureUiState, onDoneButtonClicked, onBack)
}
@Composable
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt
index 30a21bf3b632..4fd16448e9f2 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/composable/RecentAppsGestureTutorialScreen.kt
@@ -25,8 +25,11 @@ import com.android.compose.theme.LocalAndroidColorScheme
import com.android.systemui.inputdevice.tutorial.ui.composable.TutorialScreenConfig
import com.android.systemui.inputdevice.tutorial.ui.composable.rememberColorFilterProperty
import com.android.systemui.res.R
+import com.android.systemui.touchpad.tutorial.ui.gesture.GestureFlowAdapter
import com.android.systemui.touchpad.tutorial.ui.gesture.GestureRecognizer
import com.android.systemui.touchpad.tutorial.ui.gesture.RecentAppsGestureRecognizer
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
@Composable
fun RecentAppsGestureTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: () -> Unit) {
@@ -47,7 +50,17 @@ fun RecentAppsGestureTutorialScreen(onDoneButtonClicked: () -> Unit, onBack: ()
),
)
val recognizer = rememberRecentAppsGestureRecognizer(LocalContext.current.resources)
- GestureTutorialScreen(screenConfig, recognizer, onDoneButtonClicked, onBack)
+ val gestureUiState: Flow<GestureUiState> =
+ remember(recognizer) {
+ GestureFlowAdapter(recognizer).gestureStateAsFlow.map {
+ it.toGestureUiState(
+ progressStartMark = "",
+ progressEndMark = "",
+ successAnimation = R.raw.trackpad_recent_apps_success,
+ )
+ }
+ }
+ GestureTutorialScreen(screenConfig, recognizer, gestureUiState, onDoneButtonClicked, onBack)
}
@Composable
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureRecognizer.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureRecognizer.kt
index 80f800390852..024048cbbb24 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureRecognizer.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/BackGestureRecognizer.kt
@@ -33,6 +33,10 @@ class BackGestureRecognizer(private val gestureDistanceThresholdPx: Int) : Gestu
gestureStateChangedCallback = callback
}
+ override fun clearGestureStateCallback() {
+ gestureStateChangedCallback = {}
+ }
+
override fun accept(event: MotionEvent) {
if (!isThreeFingerTouchpadSwipe(event)) return
val gestureState = distanceTracker.processEvent(event)
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/GestureFlowAdapter.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/GestureFlowAdapter.kt
new file mode 100644
index 000000000000..23e31b0a9efd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/GestureFlowAdapter.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 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.touchpad.tutorial.ui.gesture
+
+import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+
+class GestureFlowAdapter(gestureRecognizer: GestureRecognizer) {
+
+ val gestureStateAsFlow: Flow<GestureState> = conflatedCallbackFlow {
+ val callback: (GestureState) -> Unit = { trySend(it) }
+ gestureRecognizer.addGestureStateCallback(callback)
+ awaitClose { gestureRecognizer.clearGestureStateCallback() }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/GestureRecognizer.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/GestureRecognizer.kt
index d146268304a6..68a2ef9528eb 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/GestureRecognizer.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/GestureRecognizer.kt
@@ -22,6 +22,8 @@ import java.util.function.Consumer
/** Based on passed [MotionEvent]s recognizes different states of gesture and notifies callback. */
interface GestureRecognizer : Consumer<MotionEvent> {
fun addGestureStateCallback(callback: (GestureState) -> Unit)
+
+ fun clearGestureStateCallback()
}
fun isThreeFingerTouchpadSwipe(event: MotionEvent) = isNFingerTouchpadSwipe(event, fingerCount = 3)
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/HomeGestureRecognizer.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/HomeGestureRecognizer.kt
index 2b84a4c50613..b804b9a0d4c7 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/HomeGestureRecognizer.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/HomeGestureRecognizer.kt
@@ -29,6 +29,10 @@ class HomeGestureRecognizer(private val gestureDistanceThresholdPx: Int) : Gestu
gestureStateChangedCallback = callback
}
+ override fun clearGestureStateCallback() {
+ gestureStateChangedCallback = {}
+ }
+
override fun accept(event: MotionEvent) {
if (!isThreeFingerTouchpadSwipe(event)) return
val gestureState = distanceTracker.processEvent(event)
diff --git a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/RecentAppsGestureRecognizer.kt b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/RecentAppsGestureRecognizer.kt
index 69b7c5edd750..7d484ee85b7c 100644
--- a/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/RecentAppsGestureRecognizer.kt
+++ b/packages/SystemUI/src/com/android/systemui/touchpad/tutorial/ui/gesture/RecentAppsGestureRecognizer.kt
@@ -38,6 +38,10 @@ class RecentAppsGestureRecognizer(
gestureStateChangedCallback = callback
}
+ override fun clearGestureStateCallback() {
+ gestureStateChangedCallback = {}
+ }
+
override fun accept(event: MotionEvent) {
if (!isThreeFingerTouchpadSwipe(event)) return
val gestureState = distanceTracker.processEvent(event)
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 7c5116dbf72c..07509e6368fb 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -64,6 +64,8 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.graphics.drawable.RotateDrawable;
+import android.graphics.drawable.ShapeDrawable;
+import android.graphics.drawable.shapes.RoundRectShape;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.os.Debug;
@@ -115,6 +117,7 @@ import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.view.RotationPolicy;
import com.android.settingslib.Utils;
import com.android.systemui.Dumpable;
+import com.android.systemui.Flags;
import com.android.systemui.Prefs;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.haptics.slider.HapticSliderViewBinder;
@@ -140,6 +143,7 @@ import com.android.systemui.volume.domain.interactor.VolumePanelNavigationIntera
import com.android.systemui.volume.panel.shared.flag.VolumePanelFlag;
import com.android.systemui.volume.ui.navigation.VolumeNavigator;
+import com.google.android.msdl.domain.MSDLPlayer;
import com.google.common.collect.ImmutableList;
import dagger.Lazy;
@@ -315,6 +319,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
private final Lazy<SecureSettings> mSecureSettings;
private int mDialogTimeoutMillis;
private final VibratorHelper mVibratorHelper;
+ private final MSDLPlayer mMSDLPlayer;
private final com.android.systemui.util.time.SystemClock mSystemClock;
private final VolumePanelFlag mVolumePanelFlag;
private final VolumeDialogInteractor mInteractor;
@@ -340,12 +345,14 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
DumpManager dumpManager,
Lazy<SecureSettings> secureSettings,
VibratorHelper vibratorHelper,
+ MSDLPlayer msdlPlayer,
com.android.systemui.util.time.SystemClock systemClock,
VolumeDialogInteractor interactor) {
mContext =
new ContextThemeWrapper(context, R.style.volume_dialog_theme);
mHandler = new H(looper);
mVibratorHelper = vibratorHelper;
+ mMSDLPlayer = msdlPlayer;
mSystemClock = systemClock;
mShouldListenForJank = shouldListenForJank;
mController = volumeDialogController;
@@ -652,6 +659,11 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
mRingerIcon = mRinger.findViewById(R.id.ringer_icon);
}
+ if (Flags.hideRingerButtonInSingleVolumeMode() && AudioSystem.isSingleVolume(mContext)) {
+ mRingerAndDrawerContainer.setVisibility(INVISIBLE);
+ mRinger.setVisibility(INVISIBLE);
+ }
+
mSelectedRingerIcon = mDialog.findViewById(R.id.volume_new_ringer_active_icon);
mSelectedRingerContainer = mDialog.findViewById(
R.id.volume_new_ringer_active_icon_container);
@@ -927,7 +939,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
}
private void addSliderHapticsToRow(VolumeRow row) {
- row.createPlugin(mVibratorHelper, mSystemClock);
+ row.createPlugin(mVibratorHelper, mMSDLPlayer, mSystemClock);
HapticSliderViewBinder.bind(row.slider, row.mHapticPlugin);
}
@@ -2337,10 +2349,31 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
return;
}
- final ColorDrawable solidDrawable = new ColorDrawable(
+ LayerDrawable background;
+ // mRingerAndDrawerContainer has rounded corner.
+ // But when it's not visible, mTopContainer needs to have rounded corner.
+ if (Flags.hideRingerButtonInSingleVolumeMode()
+ && mRingerAndDrawerContainer.getVisibility() != VISIBLE
+ ) {
+ float[] radius = new float[] {
+ mDialogCornerRadius, mDialogCornerRadius, // Top-left corner
+ mDialogCornerRadius, mDialogCornerRadius, // Top-right corner
+ 0, 0, // Bottom-right corner
+ 0, 0 // Bottom-left corner
+ };
+
+ ShapeDrawable roundedDrawable = new ShapeDrawable(
+ new RoundRectShape(radius, null, null));
+ roundedDrawable.getPaint().setColor(Utils.getColorAttrDefaultColor(
+ mContext, com.android.internal.R.attr.colorSurface));
+
+ background = new LayerDrawable(new Drawable[] { roundedDrawable });
+ } else {
+ final ColorDrawable solidDrawable = new ColorDrawable(
Utils.getColorAttrDefaultColor(mContext, com.android.internal.R.attr.colorSurface));
- final LayerDrawable background = new LayerDrawable(new Drawable[] { solidDrawable });
+ background = new LayerDrawable(new Drawable[] { solidDrawable });
+ }
// Size the solid color to match the primary volume row. In landscape, extend it upwards
// slightly so that it fills in the bottom corners of the ringer icon, whose background is
@@ -2707,11 +2740,13 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
void createPlugin(
VibratorHelper vibratorHelper,
+ MSDLPlayer msdlPlayer,
com.android.systemui.util.time.SystemClock systemClock) {
if (mHapticPlugin != null) return;
mHapticPlugin = new SeekbarHapticPlugin(
vibratorHelper,
+ msdlPlayer,
systemClock,
sSliderHapticFeedbackConfig,
sSliderTrackerConfig);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
index ed8de69ec482..2009143859d3 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/dagger/VolumeModule.java
@@ -50,6 +50,8 @@ import com.android.systemui.volume.panel.dagger.factory.VolumePanelComponentFact
import com.android.systemui.volume.panel.shared.flag.VolumePanelFlag;
import com.android.systemui.volume.ui.navigation.VolumeNavigator;
+import com.google.android.msdl.domain.MSDLPlayer;
+
import dagger.Binds;
import dagger.Lazy;
import dagger.Module;
@@ -121,6 +123,7 @@ public interface VolumeModule {
DumpManager dumpManager,
Lazy<SecureSettings> secureSettings,
VibratorHelper vibratorHelper,
+ MSDLPlayer msdlPlayer,
SystemClock systemClock,
VolumeDialogInteractor interactor) {
if (Flags.volumeRedesign()) {
@@ -144,6 +147,7 @@ public interface VolumeModule {
dumpManager,
secureSettings,
vibratorHelper,
+ msdlPlayer,
systemClock,
interactor);
impl.setStreamImportant(AudioManager.STREAM_SYSTEM, false);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractor.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractor.kt
new file mode 100644
index 000000000000..7265b82148ba
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractor.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 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.volume.dialog.ringer.domain
+
+import android.media.AudioManager
+import android.media.AudioManager.RINGER_MODE_NORMAL
+import android.media.AudioManager.RINGER_MODE_SILENT
+import android.media.AudioManager.RINGER_MODE_VIBRATE
+import android.provider.Settings
+import com.android.settingslib.volume.shared.model.RingerMode
+import com.android.systemui.plugins.VolumeDialogController
+import com.android.systemui.volume.dialog.dagger.scope.VolumeDialog
+import com.android.systemui.volume.dialog.domain.interactor.VolumeDialogStateInteractor
+import com.android.systemui.volume.dialog.ringer.shared.model.VolumeDialogRingerModel
+import com.android.systemui.volume.dialog.shared.model.VolumeDialogStateModel
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.mapNotNull
+import kotlinx.coroutines.flow.stateIn
+
+/** Exposes [VolumeDialogRingerModel]. */
+@VolumeDialog
+class VolumeDialogRingerInteractor
+@Inject
+constructor(
+ @VolumeDialog private val coroutineScope: CoroutineScope,
+ volumeDialogStateInteractor: VolumeDialogStateInteractor,
+ private val controller: VolumeDialogController,
+) {
+
+ val ringerModel: Flow<VolumeDialogRingerModel> =
+ volumeDialogStateInteractor.volumeDialogState
+ .mapNotNull { toRingerModel(it) }
+ .stateIn(coroutineScope, SharingStarted.Eagerly, null)
+ .filterNotNull()
+
+ private fun toRingerModel(state: VolumeDialogStateModel): VolumeDialogRingerModel? {
+ return state.streamModels[AudioManager.STREAM_RING]?.let {
+ VolumeDialogRingerModel(
+ availableModes =
+ mutableListOf(RingerMode(RINGER_MODE_NORMAL), RingerMode(RINGER_MODE_SILENT))
+ .also { list ->
+ if (controller.hasVibrator()) {
+ list.add(RingerMode(RINGER_MODE_VIBRATE))
+ }
+ },
+ currentRingerMode = RingerMode(state.ringerModeInternal),
+ isEnabled =
+ !(state.zenMode == Settings.Global.ZEN_MODE_ALARMS ||
+ state.zenMode == Settings.Global.ZEN_MODE_NO_INTERRUPTIONS ||
+ (state.zenMode == Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS &&
+ state.disallowRinger)),
+ isMuted = it.level == 0 || it.muted,
+ level = it.level,
+ levelMax = it.levelMax,
+ )
+ }
+ }
+
+ fun setRingerMode(ringerMode: RingerMode) {
+ controller.setRingerMode(ringerMode.value, false)
+ }
+
+ fun scheduleTouchFeedback() {
+ controller.scheduleTouchFeedback()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/shared/model/VolumeDialogRingerModel.kt b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/shared/model/VolumeDialogRingerModel.kt
new file mode 100644
index 000000000000..cf23f1a985f7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/dialog/ringer/shared/model/VolumeDialogRingerModel.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 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.volume.dialog.ringer.shared.model
+
+import com.android.settingslib.volume.shared.model.RingerMode
+
+/** Models the state of the volume dialog ringer. */
+data class VolumeDialogRingerModel(
+ val availableModes: List<RingerMode>,
+ /** Current ringer mode internal */
+ val currentRingerMode: RingerMode,
+ /** whether the ringer is allowed given the current ZenMode */
+ val isEnabled: Boolean,
+ /** Whether the current ring stream level is zero or the controller state is muted */
+ val isMuted: Boolean,
+ /** Ring stream level */
+ val level: Int,
+ /** Ring stream maximum level */
+ val levelMax: Int,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 02d0b577feb1..8039e00159f0 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -281,13 +281,13 @@ public final class WMShell implements
void initSplitScreen(SplitScreen splitScreen) {
mWakefulnessLifecycle.addObserver(new WakefulnessLifecycle.Observer() {
@Override
- public void onFinishedWakingUp() {
- splitScreen.onFinishedWakingUp();
+ public void onStartedGoingToSleep() {
+ splitScreen.onStartedGoingToSleep();
}
@Override
- public void onStartedGoingToSleep() {
- splitScreen.onStartedGoingToSleep();
+ public void onStartedWakingUp() {
+ splitScreen.onStartedWakingUp();
}
});
mCommandQueue.addCallback(new CommandQueue.Callbacks() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
index 3d1a0d0cef3c..96f4a60271d2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java
@@ -481,6 +481,25 @@ public class DozeTriggersTest extends SysuiTestCase {
verify(mAuthController).onAodInterrupt(anyInt(), anyInt(), anyFloat(), anyFloat());
}
+ @Test
+ @EnableFlags(android.hardware.biometrics.Flags.FLAG_SCREEN_OFF_UNLOCK_UDFPS)
+ public void udfpsLongPress_triggeredWhenDoze() {
+ // GIVEN device is DOZE
+ when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE);
+
+ // WHEN udfps long-press is triggered
+ mTriggers.onSensor(DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS, 100, 100,
+ new float[]{0, 1, 2, 3, 4});
+
+ // THEN the pulse is NOT dropped
+ verify(mDozeLog, never()).tracePulseDropped(anyString(), any());
+
+ // WHEN the screen state is OFF
+ mTriggers.onScreenState(Display.STATE_OFF);
+
+ // THEN aod interrupt never be sent
+ verify(mAuthController, never()).onAodInterrupt(anyInt(), anyInt(), anyFloat(), anyFloat());
+ }
@Test
public void udfpsLongPress_dozeState_notRegistered() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt
index 6b607400edfd..7383faf2fd78 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutHelperViewModelTest.kt
@@ -21,6 +21,9 @@ import android.app.role.mockRoleManager
import android.view.KeyEvent
import android.view.KeyboardShortcutGroup
import android.view.KeyboardShortcutInfo
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Tv
+import androidx.compose.material.icons.filled.VerticalSplit
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -41,13 +44,17 @@ import com.android.systemui.keyboard.shortcut.shortcutHelperMultiTaskingShortcut
import com.android.systemui.keyboard.shortcut.shortcutHelperSystemShortcutsSource
import com.android.systemui.keyboard.shortcut.shortcutHelperTestHelper
import com.android.systemui.keyboard.shortcut.shortcutHelperViewModel
+import com.android.systemui.keyboard.shortcut.ui.model.IconSource
+import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCategoryUi
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutsUiState
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testCase
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
import com.android.systemui.model.sysUiState
+import com.android.systemui.settings.FakeUserTracker
import com.android.systemui.settings.fakeUserTracker
+import com.android.systemui.settings.userTracker
import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SHORTCUT_HELPER_SHOWING
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
@@ -76,6 +83,7 @@ class ShortcutHelperViewModelTest : SysuiTestCase() {
it.shortcutHelperAppCategoriesShortcutsSource = FakeKeyboardShortcutGroupsSource()
it.shortcutHelperInputShortcutsSource = FakeKeyboardShortcutGroupsSource()
it.shortcutHelperCurrentAppShortcutsSource = fakeCurrentAppsSource
+ it.userTracker = FakeUserTracker(onCreateCurrentUserContext = { context })
}
private val testScope = kosmos.testScope
@@ -253,7 +261,7 @@ class ShortcutHelperViewModelTest : SysuiTestCase() {
whenever(
mockRoleManager.getRoleHoldersAsUser(
RoleManager.ROLE_HOME,
- fakeUserTracker.userHandle
+ fakeUserTracker.userHandle,
)
)
.thenReturn(listOf(TestShortcuts.currentAppPackageName))
@@ -283,15 +291,25 @@ class ShortcutHelperViewModelTest : SysuiTestCase() {
val activeUiState = uiState as ShortcutsUiState.Active
assertThat(activeUiState.shortcutCategories)
.containsExactly(
- ShortcutCategory(
- System,
- subCategoryWithShortcutLabels("first Foo shortcut1"),
- subCategoryWithShortcutLabels("second foO shortcut2")
+ ShortcutCategoryUi(
+ label = "System",
+ iconSource = IconSource(imageVector = Icons.Default.Tv),
+ shortcutCategory =
+ ShortcutCategory(
+ System,
+ subCategoryWithShortcutLabels("first Foo shortcut1"),
+ subCategoryWithShortcutLabels("second foO shortcut2"),
+ ),
+ ),
+ ShortcutCategoryUi(
+ label = "Multitasking",
+ iconSource = IconSource(imageVector = Icons.Default.VerticalSplit),
+ shortcutCategory =
+ ShortcutCategory(
+ MultiTasking,
+ subCategoryWithShortcutLabels("third FoO shortcut1"),
+ ),
),
- ShortcutCategory(
- MultiTasking,
- subCategoryWithShortcutLabels("third FoO shortcut1")
- )
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
index e981d627b582..cad22d360508 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WorkLockActivityControllerTest.java
@@ -16,11 +16,11 @@
package com.android.systemui.keyguard;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.argThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt
index dcf32a5f574d..51c852531697 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaTimeoutListenerTest.kt
@@ -38,11 +38,11 @@ import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Captor
import org.mockito.Mock
-import org.mockito.Mockito
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
@@ -61,7 +61,7 @@ private const val SESSION_TITLE = "SESSION_TITLE"
private const val SMARTSPACE_KEY = "SMARTSPACE_KEY"
private fun <T> anyObject(): T {
- return Mockito.anyObject<T>()
+ return ArgumentMatchers.any<T>()
}
@SmallTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
index bdd8dc8875e9..2aa300df4f7c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
@@ -21,7 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.mock;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
index 2f41ac17892d..338ed7596bd6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
@@ -19,9 +19,8 @@ import static android.provider.Settings.Global.SHOW_USB_TEMPERATURE_ALARM;
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.anyObject;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -194,7 +193,7 @@ public class PowerUITest extends SysuiTestCase {
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(1))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_SKIN));
}
@Test
@@ -207,7 +206,7 @@ public class PowerUITest extends SysuiTestCase {
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(1))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_USB_PORT));
}
@Test
@@ -220,7 +219,7 @@ public class PowerUITest extends SysuiTestCase {
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(0))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_SKIN));
}
@Test
@@ -233,7 +232,7 @@ public class PowerUITest extends SysuiTestCase {
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(0))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_USB_PORT));
}
@Test
@@ -243,14 +242,14 @@ public class PowerUITest extends SysuiTestCase {
// success registering skin thermal event listener
when(mThermalServiceMock.registerThermalEventListenerWithType(
- anyObject(), eq(Temperature.TYPE_SKIN))).thenReturn(true);
+ any(), eq(Temperature.TYPE_SKIN))).thenReturn(true);
mPowerUI.doSkinThermalEventListenerRegistration();
// verify registering skin thermal event listener, return true (success)
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(1))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_SKIN));
// Settings SHOW_TEMPERATURE_WARNING is set to 0
Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 0);
@@ -259,7 +258,7 @@ public class PowerUITest extends SysuiTestCase {
// verify unregistering skin thermal event listener
TestableLooper.get(this).processAllMessages();
- verify(mThermalServiceMock, times(1)).unregisterThermalEventListener(anyObject());
+ verify(mThermalServiceMock, times(1)).unregisterThermalEventListener(any());
}
@Test
@@ -269,14 +268,14 @@ public class PowerUITest extends SysuiTestCase {
// fail registering skin thermal event listener
when(mThermalServiceMock.registerThermalEventListenerWithType(
- anyObject(), eq(Temperature.TYPE_SKIN))).thenReturn(false);
+ any(), eq(Temperature.TYPE_SKIN))).thenReturn(false);
mPowerUI.doSkinThermalEventListenerRegistration();
// verify registering skin thermal event listener, return false (fail)
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(1))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_SKIN));
// Settings SHOW_TEMPERATURE_WARNING is set to 0
Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 0);
@@ -285,7 +284,7 @@ public class PowerUITest extends SysuiTestCase {
// verify that cannot unregister listener (current state is unregistered)
TestableLooper.get(this).processAllMessages();
- verify(mThermalServiceMock, times(0)).unregisterThermalEventListener(anyObject());
+ verify(mThermalServiceMock, times(0)).unregisterThermalEventListener(any());
// Settings SHOW_TEMPERATURE_WARNING is set to 1
Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 1);
@@ -295,7 +294,7 @@ public class PowerUITest extends SysuiTestCase {
// verify that can register listener (current state is unregistered)
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(2))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_SKIN));
}
@Test
@@ -305,14 +304,14 @@ public class PowerUITest extends SysuiTestCase {
// success registering usb thermal event listener
when(mThermalServiceMock.registerThermalEventListenerWithType(
- anyObject(), eq(Temperature.TYPE_USB_PORT))).thenReturn(true);
+ any(), eq(Temperature.TYPE_USB_PORT))).thenReturn(true);
mPowerUI.doUsbThermalEventListenerRegistration();
// verify registering usb thermal event listener, return true (success)
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(1))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_USB_PORT));
// Settings SHOW_USB_TEMPERATURE_ALARM is set to 0
Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 0);
@@ -320,7 +319,7 @@ public class PowerUITest extends SysuiTestCase {
// verify unregistering usb thermal event listener
mPowerUI.doUsbThermalEventListenerRegistration();
TestableLooper.get(this).processAllMessages();
- verify(mThermalServiceMock, times(1)).unregisterThermalEventListener(anyObject());
+ verify(mThermalServiceMock, times(1)).unregisterThermalEventListener(any());
}
@Test
@@ -330,14 +329,14 @@ public class PowerUITest extends SysuiTestCase {
// fail registering usb thermal event listener
when(mThermalServiceMock.registerThermalEventListenerWithType(
- anyObject(), eq(Temperature.TYPE_USB_PORT))).thenReturn(false);
+ any(), eq(Temperature.TYPE_USB_PORT))).thenReturn(false);
mPowerUI.doUsbThermalEventListenerRegistration();
// verify registering usb thermal event listener, return false (fail)
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(1))
- .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
+ .registerThermalEventListenerWithType(any(), eq(Temperature.TYPE_USB_PORT));
// Settings SHOW_USB_TEMPERATURE_ALARM is set to 0
Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 0);
@@ -346,7 +345,7 @@ public class PowerUITest extends SysuiTestCase {
// verify that cannot unregister listener (current state is unregistered)
TestableLooper.get(this).processAllMessages();
- verify(mThermalServiceMock, times(0)).unregisterThermalEventListener(anyObject());
+ verify(mThermalServiceMock, times(0)).unregisterThermalEventListener(any());
// Settings SHOW_USB_TEMPERATURE_ALARM is set to 1
Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 1);
@@ -356,7 +355,7 @@ public class PowerUITest extends SysuiTestCase {
// verify that can register listener (current state is unregistered)
TestableLooper.get(this).processAllMessages();
verify(mThermalServiceMock, times(2)).registerThermalEventListenerWithType(
- anyObject(), eq(Temperature.TYPE_USB_PORT));
+ any(), eq(Temperature.TYPE_USB_PORT));
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
index dad65f5add42..f6d57325bb1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java
@@ -25,7 +25,7 @@ import static junit.framework.Assert.assertNull;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
index 748c7d9d939b..296478be77e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSTileImplTest.java
@@ -36,7 +36,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Matchers.argThat;
+import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
deleted file mode 100644
index 3756ec14503c..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotPolicyImplTest.kt
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.screenshot
-
-import android.app.ActivityTaskManager.RootTaskInfo
-import android.app.IActivityTaskManager
-import android.content.ComponentName
-import android.content.Context
-import android.graphics.Rect
-import android.os.UserHandle
-import android.os.UserManager
-import android.testing.AndroidTestingRunner
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.screenshot.ScreenshotPolicy.DisplayContentInfo
-import com.android.systemui.screenshot.policy.ActivityType.Home
-import com.android.systemui.screenshot.policy.ActivityType.Undefined
-import com.android.systemui.screenshot.policy.WindowingMode.FullScreen
-import com.android.systemui.screenshot.policy.WindowingMode.PictureInPicture
-import com.android.systemui.screenshot.policy.newChildTask
-import com.android.systemui.screenshot.policy.newRootTaskInfo
-import com.android.systemui.settings.FakeDisplayTracker
-import com.android.systemui.util.mockito.mock
-import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.runBlocking
-import org.junit.Test
-import org.junit.runner.RunWith
-
-// The following values are chosen to be distinct from commonly seen real values
-private const val DISPLAY_ID = 100
-private const val PRIMARY_USER = 2000
-private const val MANAGED_PROFILE_USER = 3000
-
-@RunWith(AndroidTestingRunner::class)
-class ScreenshotPolicyImplTest : SysuiTestCase() {
-
- @Test
- fun testToDisplayContentInfo() {
- assertThat(fullScreenWorkProfileTask.toDisplayContentInfo())
- .isEqualTo(
- DisplayContentInfo(
- ComponentName(
- "com.google.android.apps.nbu.files",
- "com.google.android.apps.nbu.files.home.HomeActivity"
- ),
- Rect(0, 0, 1080, 2400),
- UserHandle.of(MANAGED_PROFILE_USER),
- 65
- )
- )
- }
-
- @Test
- fun findPrimaryContent_ignoresPipTask() = runBlocking {
- val policy =
- fakeTasksPolicyImpl(
- mContext,
- shadeExpanded = false,
- tasks = listOf(pipTask, fullScreenWorkProfileTask, launcherTask, emptyTask)
- )
-
- val info = policy.findPrimaryContent(DISPLAY_ID)
- assertThat(info).isEqualTo(fullScreenWorkProfileTask.toDisplayContentInfo())
- }
-
- @Test
- fun findPrimaryContent_shadeExpanded_ignoresTopTask() = runBlocking {
- val policy =
- fakeTasksPolicyImpl(
- mContext,
- shadeExpanded = true,
- tasks = listOf(fullScreenWorkProfileTask, launcherTask, emptyTask)
- )
-
- val info = policy.findPrimaryContent(DISPLAY_ID)
- assertThat(info).isEqualTo(policy.systemUiContent)
- }
-
- @Test
- fun findPrimaryContent_emptyTaskList() = runBlocking {
- val policy = fakeTasksPolicyImpl(mContext, shadeExpanded = false, tasks = listOf())
-
- val info = policy.findPrimaryContent(DISPLAY_ID)
- assertThat(info).isEqualTo(policy.systemUiContent)
- }
-
- @Test
- fun findPrimaryContent_workProfileNotOnTop() = runBlocking {
- val policy =
- fakeTasksPolicyImpl(
- mContext,
- shadeExpanded = false,
- tasks = listOf(launcherTask, fullScreenWorkProfileTask, emptyTask)
- )
-
- val info = policy.findPrimaryContent(DISPLAY_ID)
- assertThat(info).isEqualTo(launcherTask.toDisplayContentInfo())
- }
-
- private fun fakeTasksPolicyImpl(
- context: Context,
- shadeExpanded: Boolean,
- tasks: List<RootTaskInfo>
- ): ScreenshotPolicyImpl {
- val userManager = mock<UserManager>()
- val atmService = mock<IActivityTaskManager>()
- val dispatcher = Dispatchers.Unconfined
- val displayTracker = FakeDisplayTracker(context)
-
- return object :
- ScreenshotPolicyImpl(context, userManager, atmService, dispatcher, displayTracker) {
- override suspend fun isManagedProfile(userId: Int) = (userId == MANAGED_PROFILE_USER)
- override suspend fun getAllRootTaskInfosOnDisplay(displayId: Int) = tasks
- override suspend fun isNotificationShadeExpanded() = shadeExpanded
- }
- }
-
- private val pipTask =
- newRootTaskInfo(
- taskId = 66,
- userId = PRIMARY_USER,
- displayId = DISPLAY_ID,
- bounds = Rect(628, 1885, 1038, 2295),
- windowingMode = PictureInPicture,
- topActivity = ComponentName.unflattenFromString(YOUTUBE_PIP_ACTIVITY),
- ) {
- listOf(newChildTask(taskId = 66, userId = 0, name = YOUTUBE_HOME_ACTIVITY))
- }
-
- private val fullScreenWorkProfileTask =
- newRootTaskInfo(
- taskId = 65,
- userId = MANAGED_PROFILE_USER,
- displayId = DISPLAY_ID,
- bounds = Rect(0, 0, 1080, 2400),
- windowingMode = FullScreen,
- topActivity = ComponentName.unflattenFromString(FILES_HOME_ACTIVITY),
- ) {
- listOf(
- newChildTask(taskId = 65, userId = MANAGED_PROFILE_USER, name = FILES_HOME_ACTIVITY)
- )
- }
- private val launcherTask =
- newRootTaskInfo(
- taskId = 1,
- userId = PRIMARY_USER,
- displayId = DISPLAY_ID,
- activityType = Home,
- windowingMode = FullScreen,
- bounds = Rect(0, 0, 1080, 2400),
- topActivity = ComponentName.unflattenFromString(LAUNCHER_ACTIVITY),
- ) {
- listOf(newChildTask(taskId = 1, userId = 0, name = LAUNCHER_ACTIVITY))
- }
-
- private val emptyTask =
- newRootTaskInfo(
- taskId = 2,
- userId = PRIMARY_USER,
- displayId = DISPLAY_ID,
- visible = false,
- running = false,
- numActivities = 0,
- activityType = Undefined,
- bounds = Rect(0, 0, 1080, 2400),
- ) {
- listOf(
- newChildTask(taskId = 3, name = ""),
- newChildTask(taskId = 4, name = ""),
- )
- }
-}
-
-private const val YOUTUBE_HOME_ACTIVITY =
- "com.google.android.youtube/" + "com.google.android.youtube.app.honeycomb.Shell\$HomeActivity"
-
-private const val FILES_HOME_ACTIVITY =
- "com.google.android.apps.nbu.files/" + "com.google.android.apps.nbu.files.home.HomeActivity"
-
-private const val YOUTUBE_PIP_ACTIVITY =
- "com.google.android.youtube/" +
- "com.google.android.apps.youtube.app.watchwhile.WatchWhileActivity"
-
-private const val LAUNCHER_ACTIVITY =
- "com.google.android.apps.nexuslauncher/" +
- "com.google.android.apps.nexuslauncher.NexusLauncherActivity"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextViewTest.kt
index 040a9e959094..8bd8b72e5527 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/clocks/view/SimpleDigitalClockTextViewTest.kt
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package systemui.shared.clocks.view
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java
index e9222c3ef6ad..3ad0605f2781 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shared/plugins/PluginActionManagerTest.java
@@ -19,8 +19,8 @@ package com.android.systemui.shared.plugins;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index 2b5e014b2048..b730b3703515 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -21,8 +21,8 @@ import static android.inputmethodservice.InputMethodService.IME_ACTIVE;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowInsetsController.BEHAVIOR_DEFAULT;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index a75d7b23a92c..da0029ff6746 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -21,6 +21,8 @@ import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK;
import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
@@ -777,6 +779,24 @@ public class KeyguardIndicationControllerTest extends KeyguardIndicationControll
}
@Test
+ public void indicationAreaHidden_untilBatteryInfoArrives() {
+ createController();
+ // level of -1 indicates missing info
+ BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_UNKNOWN,
+ -1 /* level */, BatteryManager.BATTERY_PLUGGED_WIRELESS, 100 /* health */,
+ 0 /* maxChargingWattage */, true /* present */);
+
+ mController.setVisible(true);
+ mStatusBarStateListener.onDozingChanged(true);
+ reset(mIndicationArea);
+
+ mController.getKeyguardCallback().onRefreshBatteryInfo(status);
+ // VISIBLE is always called first
+ verify(mIndicationArea).setVisibility(VISIBLE);
+ verify(mIndicationArea).setVisibility(GONE);
+ }
+
+ @Test
public void onRefreshBatteryInfo_computesChargingTime() throws RemoteException {
createController();
BatteryStatus status = new BatteryStatus(BatteryManager.BATTERY_STATUS_CHARGING,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
index b18b7f8f8129..72ffa0ee0855 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/commandline/CommandRegistryTest.kt
@@ -16,41 +16,39 @@
package com.android.systemui.statusbar.commandline
-import androidx.test.filters.SmallTest
-import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
-
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
-
+import java.io.PrintWriter
+import java.io.StringWriter
+import java.util.concurrent.Executor
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyList
import org.mockito.ArgumentMatchers.eq
-import org.mockito.Mockito
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-
-import java.io.PrintWriter
-import java.io.StringWriter
-import java.util.concurrent.Executor
private fun <T> anyObject(): T {
- return Mockito.anyObject<T>()
+ return any<T>()
}
private fun <T : Any> safeEq(value: T): T = eq(value) ?: value
-@RunWith(AndroidTestingRunner::class)
+@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@SmallTest
class CommandRegistryTest : SysuiTestCase() {
lateinit var registry: CommandRegistry
- val inLineExecutor = object : Executor {
- override fun execute(command: Runnable) {
- command.run()
+ val inLineExecutor =
+ object : Executor {
+ override fun execute(command: Runnable) {
+ command.run()
+ }
}
- }
val writer: PrintWriter = PrintWriter(StringWriter())
@@ -83,11 +81,9 @@ class CommandRegistryTest : SysuiTestCase() {
}
class FakeCommand() : Command {
- override fun execute(pw: PrintWriter, args: List<String>) {
- }
+ override fun execute(pw: PrintWriter, args: List<String>) {}
- override fun help(pw: PrintWriter) {
- }
+ override fun help(pw: PrintWriter) {}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/CallbackHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/CallbackHandlerTest.java
index 7bd77a62ffcd..5fce08b08137 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/CallbackHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/CallbackHandlerTest.java
@@ -18,7 +18,7 @@ package com.android.systemui.statusbar.connectivity;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.eq;
import android.os.HandlerThread;
import android.telephony.SubscriptionInfo;
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 83dbfa0682ad..b00f9e9f01d3 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
@@ -25,10 +25,10 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isA;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
@@ -297,7 +297,8 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
assertNotNull(mDefaultCallbackInWifiTracker);
assertNotNull(mDefaultCallbackInNetworkController);
verify(mMockCm, atLeastOnce()).registerNetworkCallback(
- isA(NetworkRequest.class), callbackArg.capture(), isA(Handler.class));
+ isA(NetworkRequest.class), callbackArg.capture(),
+ isA(Handler.class));
mNetworkCallback = callbackArg.getValue();
assertNotNull(mNetworkCallback);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt
index 0b5f8d5e948c..723c0d701305 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerWithScenesTest.kt
@@ -74,22 +74,31 @@ import com.android.systemui.testKosmos
import com.android.systemui.util.kotlin.JavaAdapter
import com.android.systemui.wmshell.BubblesManager
import java.util.Optional
-import junit.framework.Assert
import kotlin.test.assertEquals
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runCurrent
+import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers
import org.mockito.Mock
-import org.mockito.Mockito
-import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import org.mockito.invocation.InvocationOnMock
+import org.mockito.kotlin.any
+import org.mockito.kotlin.anyOrNull
+import org.mockito.kotlin.argumentCaptor
+import org.mockito.kotlin.doNothing
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.never
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
/** Tests for [NotificationGutsManager] with the scene container enabled. */
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWithLooper
@@ -99,7 +108,7 @@ class NotificationGutsManagerWithScenesTest : SysuiTestCase() {
NotificationChannel(
TEST_CHANNEL_ID,
TEST_CHANNEL_ID,
- NotificationManager.IMPORTANCE_DEFAULT
+ NotificationManager.IMPORTANCE_DEFAULT,
)
private val kosmos = testKosmos()
@@ -146,7 +155,7 @@ class NotificationGutsManagerWithScenesTest : SysuiTestCase() {
MockitoAnnotations.initMocks(this)
allowTestableLooperAsMainThread()
helper = NotificationTestHelper(mContext, mDependency)
- Mockito.`when`(accessibilityManager.isTouchExplorationEnabled).thenReturn(false)
+ whenever(accessibilityManager.isTouchExplorationEnabled).thenReturn(false)
windowRootViewVisibilityInteractor =
WindowRootViewVisibilityInteractor(
testScope.backgroundScope,
@@ -185,12 +194,12 @@ class NotificationGutsManagerWithScenesTest : SysuiTestCase() {
deviceProvisionedController,
metricsLogger,
headsUpManager,
- activityStarter
+ activityStarter,
)
gutsManager.setUpWithPresenter(
presenter,
notificationListContainer,
- onSettingsClickListener
+ onSettingsClickListener,
)
gutsManager.setNotificationActivityStarter(notificationActivityStarter)
gutsManager.start()
@@ -198,49 +207,31 @@ class NotificationGutsManagerWithScenesTest : SysuiTestCase() {
@Test
fun testOpenAndCloseGuts() {
- val guts = Mockito.spy(NotificationGuts(mContext))
- Mockito.`when`(guts.post(ArgumentMatchers.any())).thenAnswer { invocation: InvocationOnMock
- ->
+ val guts = spy(NotificationGuts(mContext))
+ whenever(guts.post(any())).thenAnswer { invocation: InvocationOnMock ->
handler.post((invocation.arguments[0] as Runnable))
null
}
// Test doesn't support animation since the guts view is not attached.
- Mockito.doNothing()
- .`when`(guts)
- .openControls(
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyBoolean(),
- ArgumentMatchers.any(Runnable::class.java)
- )
+ doNothing()
+ .whenever(guts)
+ .openControls(any<Int>(), any<Int>(), any<Boolean>(), any<Runnable>())
val realRow = createTestNotificationRow()
val menuItem = createTestMenuItem(realRow)
- val row = Mockito.spy(realRow)
- Mockito.`when`(row!!.windowToken).thenReturn(Binder())
- Mockito.`when`(row.guts).thenReturn(guts)
+ val row = spy(realRow)
+ whenever(row!!.windowToken).thenReturn(Binder())
+ whenever(row.guts).thenReturn(guts)
Assert.assertTrue(gutsManager.openGutsInternal(row, 0, 0, menuItem))
assertEquals(View.INVISIBLE.toLong(), guts.visibility.toLong())
executor.runAllReady()
- verify(guts)
- .openControls(
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyBoolean(),
- ArgumentMatchers.any(Runnable::class.java)
- )
+ verify(guts).openControls(any<Int>(), any<Int>(), any<Boolean>(), any<Runnable>())
verify(headsUpManager).setGutsShown(realRow!!.entry, true)
assertEquals(View.VISIBLE.toLong(), guts.visibility.toLong())
gutsManager.closeAndSaveGuts(false, false, true, 0, 0, false)
verify(guts)
- .closeControls(
- ArgumentMatchers.anyBoolean(),
- ArgumentMatchers.anyBoolean(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyBoolean()
- )
- verify(row, Mockito.times(1)).setGutsView(ArgumentMatchers.any())
+ .closeControls(any<Boolean>(), any<Boolean>(), any<Int>(), any<Int>(), any<Boolean>())
+ verify(row, times(1)).setGutsView(any())
executor.runAllReady()
verify(headsUpManager).setGutsShown(realRow.entry, false)
}
@@ -250,7 +241,7 @@ class NotificationGutsManagerWithScenesTest : SysuiTestCase() {
// First, start out lockscreen or shade as not visible
setIsLockscreenOrShadeVisible(false)
testScope.testScheduler.runCurrent()
- val guts = Mockito.mock(NotificationGuts::class.java)
+ val guts = mock<NotificationGuts>()
gutsManager.exposedGuts = guts
// WHEN the lockscreen or shade becomes visible
@@ -258,15 +249,9 @@ class NotificationGutsManagerWithScenesTest : SysuiTestCase() {
testScope.testScheduler.runCurrent()
// THEN the guts are not closed
- verify(guts, Mockito.never()).removeCallbacks(ArgumentMatchers.any())
- verify(guts, Mockito.never())
- .closeControls(
- ArgumentMatchers.anyBoolean(),
- ArgumentMatchers.anyBoolean(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyBoolean()
- )
+ verify(guts, never()).removeCallbacks(any())
+ verify(guts, never())
+ .closeControls(any<Boolean>(), any<Boolean>(), any<Int>(), any<Int>(), any<Boolean>())
}
@Test
@@ -274,7 +259,7 @@ class NotificationGutsManagerWithScenesTest : SysuiTestCase() {
// First, start out lockscreen or shade as visible
setIsLockscreenOrShadeVisible(true)
testScope.testScheduler.runCurrent()
- val guts = Mockito.mock(NotificationGuts::class.java)
+ val guts = mock<NotificationGuts>()
gutsManager.exposedGuts = guts
// WHEN the lockscreen or shade is no longer visible
@@ -282,14 +267,14 @@ class NotificationGutsManagerWithScenesTest : SysuiTestCase() {
testScope.testScheduler.runCurrent()
// THEN the guts are closed
- verify(guts).removeCallbacks(ArgumentMatchers.any())
+ verify(guts).removeCallbacks(anyOrNull())
verify(guts)
.closeControls(
- /* leavebehinds= */ ArgumentMatchers.eq(true),
- /* controls= */ ArgumentMatchers.eq(true),
- /* x= */ ArgumentMatchers.anyInt(),
- /* y= */ ArgumentMatchers.anyInt(),
- /* force= */ ArgumentMatchers.eq(true)
+ /* leavebehinds= */ eq(true),
+ /* controls= */ eq(true),
+ /* x= */ any<Int>(),
+ /* y= */ any<Int>(),
+ /* force= */ eq(true),
)
}
@@ -304,95 +289,68 @@ class NotificationGutsManagerWithScenesTest : SysuiTestCase() {
testScope.testScheduler.runCurrent()
// THEN the list container is reset
- verify(notificationListContainer)
- .resetExposedMenuView(ArgumentMatchers.anyBoolean(), ArgumentMatchers.anyBoolean())
+ verify(notificationListContainer).resetExposedMenuView(any<Boolean>(), any<Boolean>())
}
@Test
fun testChangeDensityOrFontScale() {
- val guts = Mockito.spy(NotificationGuts(mContext))
- Mockito.`when`(guts.post(ArgumentMatchers.any())).thenAnswer { invocation: InvocationOnMock
- ->
+ val guts = spy(NotificationGuts(mContext))
+ whenever(guts.post(any())).thenAnswer { invocation: InvocationOnMock ->
handler.post((invocation.arguments[0] as Runnable))
null
}
// Test doesn't support animation since the guts view is not attached.
- Mockito.doNothing()
- .`when`(guts)
- .openControls(
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyBoolean(),
- ArgumentMatchers.any(Runnable::class.java)
- )
+ doNothing()
+ .whenever(guts)
+ .openControls(any<Int>(), any<Int>(), any<Boolean>(), any<Runnable>())
val realRow = createTestNotificationRow()
val menuItem = createTestMenuItem(realRow)
- val row = Mockito.spy(realRow)
- Mockito.`when`(row!!.windowToken).thenReturn(Binder())
- Mockito.`when`(row.guts).thenReturn(guts)
- Mockito.doNothing().`when`(row).ensureGutsInflated()
+ val row = spy(realRow)
+ whenever(row!!.windowToken).thenReturn(Binder())
+ whenever(row.guts).thenReturn(guts)
+ doNothing().whenever(row).ensureGutsInflated()
val realEntry = realRow!!.entry
- val entry = Mockito.spy(realEntry)
- Mockito.`when`(entry.row).thenReturn(row)
- Mockito.`when`(entry.getGuts()).thenReturn(guts)
+ val entry = spy(realEntry)
+ whenever(entry.row).thenReturn(row)
+ whenever(entry.getGuts()).thenReturn(guts)
Assert.assertTrue(gutsManager.openGutsInternal(row, 0, 0, menuItem))
executor.runAllReady()
- verify(guts)
- .openControls(
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyBoolean(),
- ArgumentMatchers.any(Runnable::class.java)
- )
+ verify(guts).openControls(any<Int>(), any<Int>(), any<Boolean>(), any<Runnable>())
// called once by mGutsManager.bindGuts() in mGutsManager.openGuts()
- verify(row).setGutsView(ArgumentMatchers.any())
+ verify(row).setGutsView(any())
row.onDensityOrFontScaleChanged()
gutsManager.onDensityOrFontScaleChanged(entry)
executor.runAllReady()
gutsManager.closeAndSaveGuts(false, false, false, 0, 0, false)
verify(guts)
- .closeControls(
- ArgumentMatchers.anyBoolean(),
- ArgumentMatchers.anyBoolean(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.anyBoolean()
- )
+ .closeControls(any<Boolean>(), any<Boolean>(), any<Int>(), any<Int>(), any<Boolean>())
// called again by mGutsManager.bindGuts(), in mGutsManager.onDensityOrFontScaleChanged()
- verify(row, Mockito.times(2)).setGutsView(ArgumentMatchers.any())
+ verify(row, times(2)).setGutsView(any())
}
@Test
fun testAppOpsSettingsIntent_camera() {
val ops = ArraySet<Int>()
ops.add(AppOpsManager.OP_CAMERA)
- gutsManager.startAppOpsSettingsActivity("", 0, ops, null)
- val captor = ArgumentCaptor.forClass(Intent::class.java)
- verify(notificationActivityStarter, Mockito.times(1))
- .startNotificationGutsIntent(
- captor.capture(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.any()
- )
- assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.value.action)
+ gutsManager.startAppOpsSettingsActivity("", 0, ops, mock<ExpandableNotificationRow>())
+ val captor = argumentCaptor<Intent>()
+ verify(notificationActivityStarter, times(1))
+ .startNotificationGutsIntent(captor.capture(), any<Int>(), any())
+ assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.lastValue.action)
}
@Test
fun testAppOpsSettingsIntent_mic() {
val ops = ArraySet<Int>()
ops.add(AppOpsManager.OP_RECORD_AUDIO)
- gutsManager.startAppOpsSettingsActivity("", 0, ops, null)
- val captor = ArgumentCaptor.forClass(Intent::class.java)
- verify(notificationActivityStarter, Mockito.times(1))
- .startNotificationGutsIntent(
- captor.capture(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.any()
- )
- assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.value.action)
+ gutsManager.startAppOpsSettingsActivity("", 0, ops, mock<ExpandableNotificationRow>())
+ val captor = argumentCaptor<Intent>()
+ verify(notificationActivityStarter, times(1))
+ .startNotificationGutsIntent(captor.capture(), any<Int>(), any())
+ assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.lastValue.action)
}
@Test
@@ -400,30 +358,22 @@ class NotificationGutsManagerWithScenesTest : SysuiTestCase() {
val ops = ArraySet<Int>()
ops.add(AppOpsManager.OP_CAMERA)
ops.add(AppOpsManager.OP_RECORD_AUDIO)
- gutsManager.startAppOpsSettingsActivity("", 0, ops, null)
- val captor = ArgumentCaptor.forClass(Intent::class.java)
- verify(notificationActivityStarter, Mockito.times(1))
- .startNotificationGutsIntent(
- captor.capture(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.any()
- )
- assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.value.action)
+ gutsManager.startAppOpsSettingsActivity("", 0, ops, mock<ExpandableNotificationRow>())
+ val captor = argumentCaptor<Intent>()
+ verify(notificationActivityStarter, times(1))
+ .startNotificationGutsIntent(captor.capture(), any<Int>(), any())
+ assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.lastValue.action)
}
@Test
fun testAppOpsSettingsIntent_overlay() {
val ops = ArraySet<Int>()
ops.add(AppOpsManager.OP_SYSTEM_ALERT_WINDOW)
- gutsManager.startAppOpsSettingsActivity("", 0, ops, null)
- val captor = ArgumentCaptor.forClass(Intent::class.java)
- verify(notificationActivityStarter, Mockito.times(1))
- .startNotificationGutsIntent(
- captor.capture(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.any()
- )
- assertEquals(Settings.ACTION_MANAGE_APP_OVERLAY_PERMISSION, captor.value.action)
+ gutsManager.startAppOpsSettingsActivity("", 0, ops, mock<ExpandableNotificationRow>())
+ val captor = argumentCaptor<Intent>()
+ verify(notificationActivityStarter, times(1))
+ .startNotificationGutsIntent(captor.capture(), any<Int>(), any())
+ assertEquals(Settings.ACTION_MANAGE_APP_OVERLAY_PERMISSION, captor.lastValue.action)
}
@Test
@@ -432,15 +382,11 @@ class NotificationGutsManagerWithScenesTest : SysuiTestCase() {
ops.add(AppOpsManager.OP_CAMERA)
ops.add(AppOpsManager.OP_RECORD_AUDIO)
ops.add(AppOpsManager.OP_SYSTEM_ALERT_WINDOW)
- gutsManager.startAppOpsSettingsActivity("", 0, ops, null)
- val captor = ArgumentCaptor.forClass(Intent::class.java)
- verify(notificationActivityStarter, Mockito.times(1))
- .startNotificationGutsIntent(
- captor.capture(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.any()
- )
- assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.value.action)
+ gutsManager.startAppOpsSettingsActivity("", 0, ops, mock<ExpandableNotificationRow>())
+ val captor = argumentCaptor<Intent>()
+ verify(notificationActivityStarter, times(1))
+ .startNotificationGutsIntent(captor.capture(), any<Int>(), any())
+ assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.lastValue.action)
}
@Test
@@ -448,15 +394,11 @@ class NotificationGutsManagerWithScenesTest : SysuiTestCase() {
val ops = ArraySet<Int>()
ops.add(AppOpsManager.OP_CAMERA)
ops.add(AppOpsManager.OP_SYSTEM_ALERT_WINDOW)
- gutsManager.startAppOpsSettingsActivity("", 0, ops, null)
- val captor = ArgumentCaptor.forClass(Intent::class.java)
- verify(notificationActivityStarter, Mockito.times(1))
- .startNotificationGutsIntent(
- captor.capture(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.any()
- )
- assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.value.action)
+ gutsManager.startAppOpsSettingsActivity("", 0, ops, mock<ExpandableNotificationRow>())
+ val captor = argumentCaptor<Intent>()
+ verify(notificationActivityStarter, times(1))
+ .startNotificationGutsIntent(captor.capture(), any<Int>(), any())
+ assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.lastValue.action)
}
@Test
@@ -464,112 +406,108 @@ class NotificationGutsManagerWithScenesTest : SysuiTestCase() {
val ops = ArraySet<Int>()
ops.add(AppOpsManager.OP_RECORD_AUDIO)
ops.add(AppOpsManager.OP_SYSTEM_ALERT_WINDOW)
- gutsManager.startAppOpsSettingsActivity("", 0, ops, null)
- val captor = ArgumentCaptor.forClass(Intent::class.java)
- verify(notificationActivityStarter, Mockito.times(1))
- .startNotificationGutsIntent(
- captor.capture(),
- ArgumentMatchers.anyInt(),
- ArgumentMatchers.any()
- )
- assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.value.action)
+ gutsManager.startAppOpsSettingsActivity("", 0, ops, mock<ExpandableNotificationRow>())
+ val captor = argumentCaptor<Intent>()
+ verify(notificationActivityStarter, times(1))
+ .startNotificationGutsIntent(captor.capture(), any<Int>(), any())
+ assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.lastValue.action)
}
@Test
@Throws(Exception::class)
fun testInitializeNotificationInfoView_highPriority() {
- val notificationInfoView = Mockito.mock(NotificationInfo::class.java)
- val row = Mockito.spy(helper.createRow())
+ val notificationInfoView = mock<NotificationInfo>()
+ val row = spy(helper.createRow())
val entry = row.entry
NotificationEntryHelper.modifyRanking(entry)
.setUserSentiment(Ranking.USER_SENTIMENT_NEGATIVE)
.setImportance(NotificationManager.IMPORTANCE_HIGH)
.build()
- Mockito.`when`(row.getIsNonblockable()).thenReturn(false)
- Mockito.`when`(highPriorityProvider.isHighPriority(entry)).thenReturn(true)
+ whenever(row.getIsNonblockable()).thenReturn(false)
+ whenever(highPriorityProvider.isHighPriority(entry)).thenReturn(true)
val statusBarNotification = entry.sbn
gutsManager.initializeNotificationInfo(row, notificationInfoView)
verify(notificationInfoView)
.bindNotification(
- ArgumentMatchers.any(PackageManager::class.java),
- ArgumentMatchers.any(INotificationManager::class.java),
- ArgumentMatchers.eq(onUserInteractionCallback),
- ArgumentMatchers.eq(channelEditorDialogController),
- ArgumentMatchers.eq(statusBarNotification.packageName),
- ArgumentMatchers.any(NotificationChannel::class.java),
- ArgumentMatchers.eq(entry),
- ArgumentMatchers.any(NotificationInfo.OnSettingsClickListener::class.java),
- ArgumentMatchers.any(NotificationInfo.OnAppSettingsClickListener::class.java),
- ArgumentMatchers.any(UiEventLogger::class.java),
- ArgumentMatchers.eq(true),
- ArgumentMatchers.eq(false),
- ArgumentMatchers.eq(true), /* wasShownHighPriority */
- ArgumentMatchers.eq(assistantFeedbackController),
- ArgumentMatchers.any(MetricsLogger::class.java)
+ any<PackageManager>(),
+ any<INotificationManager>(),
+ eq(onUserInteractionCallback),
+ eq(channelEditorDialogController),
+ eq(statusBarNotification.packageName),
+ any<NotificationChannel>(),
+ eq(entry),
+ any<NotificationInfo.OnSettingsClickListener>(),
+ any<NotificationInfo.OnAppSettingsClickListener>(),
+ any<UiEventLogger>(),
+ eq(true),
+ eq(false),
+ eq(true), /* wasShownHighPriority */
+ eq(assistantFeedbackController),
+ any<MetricsLogger>(),
)
}
@Test
@Throws(Exception::class)
fun testInitializeNotificationInfoView_PassesAlongProvisionedState() {
- val notificationInfoView = Mockito.mock(NotificationInfo::class.java)
- val row = Mockito.spy(helper.createRow())
+ val notificationInfoView = mock<NotificationInfo>()
+ val row = spy(helper.createRow())
NotificationEntryHelper.modifyRanking(row.entry)
.setUserSentiment(Ranking.USER_SENTIMENT_NEGATIVE)
.build()
- Mockito.`when`(row.getIsNonblockable()).thenReturn(false)
+ whenever(row.getIsNonblockable()).thenReturn(false)
val statusBarNotification = row.entry.sbn
val entry = row.entry
gutsManager.initializeNotificationInfo(row, notificationInfoView)
verify(notificationInfoView)
.bindNotification(
- ArgumentMatchers.any(PackageManager::class.java),
- ArgumentMatchers.any(INotificationManager::class.java),
- ArgumentMatchers.eq(onUserInteractionCallback),
- ArgumentMatchers.eq(channelEditorDialogController),
- ArgumentMatchers.eq(statusBarNotification.packageName),
- ArgumentMatchers.any(NotificationChannel::class.java),
- ArgumentMatchers.eq(entry),
- ArgumentMatchers.any(NotificationInfo.OnSettingsClickListener::class.java),
- ArgumentMatchers.any(NotificationInfo.OnAppSettingsClickListener::class.java),
- ArgumentMatchers.any(UiEventLogger::class.java),
- ArgumentMatchers.eq(true),
- ArgumentMatchers.eq(false),
- ArgumentMatchers.eq(false), /* wasShownHighPriority */
- ArgumentMatchers.eq(assistantFeedbackController),
- ArgumentMatchers.any(MetricsLogger::class.java)
+ any<PackageManager>(),
+ any<INotificationManager>(),
+ eq(onUserInteractionCallback),
+ eq(channelEditorDialogController),
+ eq(statusBarNotification.packageName),
+ any<NotificationChannel>(),
+ eq(entry),
+ any<NotificationInfo.OnSettingsClickListener>(),
+ any<NotificationInfo.OnAppSettingsClickListener>(),
+ any<UiEventLogger>(),
+ eq(true),
+ eq(false),
+ eq(false), /* wasShownHighPriority */
+ eq(assistantFeedbackController),
+ any<MetricsLogger>(),
)
}
@Test
@Throws(Exception::class)
fun testInitializeNotificationInfoView_withInitialAction() {
- val notificationInfoView = Mockito.mock(NotificationInfo::class.java)
- val row = Mockito.spy(helper.createRow())
+ val notificationInfoView = mock<NotificationInfo>()
+ val row = spy(helper.createRow())
NotificationEntryHelper.modifyRanking(row.entry)
.setUserSentiment(Ranking.USER_SENTIMENT_NEGATIVE)
.build()
- Mockito.`when`(row.getIsNonblockable()).thenReturn(false)
+ whenever(row.getIsNonblockable()).thenReturn(false)
val statusBarNotification = row.entry.sbn
val entry = row.entry
gutsManager.initializeNotificationInfo(row, notificationInfoView)
verify(notificationInfoView)
.bindNotification(
- ArgumentMatchers.any(PackageManager::class.java),
- ArgumentMatchers.any(INotificationManager::class.java),
- ArgumentMatchers.eq(onUserInteractionCallback),
- ArgumentMatchers.eq(channelEditorDialogController),
- ArgumentMatchers.eq(statusBarNotification.packageName),
- ArgumentMatchers.any(NotificationChannel::class.java),
- ArgumentMatchers.eq(entry),
- ArgumentMatchers.any(NotificationInfo.OnSettingsClickListener::class.java),
- ArgumentMatchers.any(NotificationInfo.OnAppSettingsClickListener::class.java),
- ArgumentMatchers.any(UiEventLogger::class.java),
- ArgumentMatchers.eq(true),
- ArgumentMatchers.eq(false),
- ArgumentMatchers.eq(false), /* wasShownHighPriority */
- ArgumentMatchers.eq(assistantFeedbackController),
- ArgumentMatchers.any(MetricsLogger::class.java)
+ any<PackageManager>(),
+ any<INotificationManager>(),
+ eq(onUserInteractionCallback),
+ eq(channelEditorDialogController),
+ eq(statusBarNotification.packageName),
+ any<NotificationChannel>(),
+ eq(entry),
+ any<NotificationInfo.OnSettingsClickListener>(),
+ any<NotificationInfo.OnAppSettingsClickListener>(),
+ any<UiEventLogger>(),
+ eq(true),
+ eq(false),
+ eq(false), /* wasShownHighPriority */
+ eq(assistantFeedbackController),
+ any<MetricsLogger>(),
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
index dcd57f137d71..c2460f93b862 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt
@@ -17,30 +17,27 @@
package com.android.systemui.statusbar.policy
import android.app.NotificationManager
-import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
-
+import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
-
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.anyString
import org.mockito.Mock
-import org.mockito.Mockito
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
private fun <T> anyObject(): T {
- return Mockito.anyObject<T>()
+ return any<T>()
}
-@RunWith(AndroidTestingRunner::class)
+@RunWith(AndroidJUnit4::class)
@RunWithLooper()
@SmallTest
class BatteryStateNotifierTest : SysuiTestCase() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
index 9bb760760cd7..f91f373dfc2c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/SecurityControllerTest.java
@@ -22,10 +22,9 @@ import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyObject;
-import static org.mockito.Matchers.argThat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -120,9 +119,9 @@ public class SecurityControllerTest extends SysuiTestCase {
verify(mBroadcastDispatcher).registerReceiverWithHandler(
brCaptor.capture(),
- anyObject(),
- anyObject(),
- anyObject());
+ any(),
+ any(),
+ any());
mBroadcastReceiver = brCaptor.getValue();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
index ecc7909a857a..3007eabba0b8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java
@@ -92,6 +92,7 @@ import com.android.systemui.volume.domain.interactor.VolumePanelNavigationIntera
import com.android.systemui.volume.panel.shared.flag.VolumePanelFlag;
import com.android.systemui.volume.ui.navigation.VolumeNavigator;
+import com.google.android.msdl.domain.MSDLPlayer;
import com.google.common.collect.ImmutableList;
import dagger.Lazy;
@@ -169,6 +170,9 @@ public class VolumeDialogImplTest extends SysuiTestCase {
@Mock
private VibratorHelper mVibratorHelper;
+ @Mock
+ private MSDLPlayer mMSDLPlayer;
+
private int mLongestHideShowAnimationDuration = 250;
private FakeSettings mSecureSettings;
@@ -222,6 +226,7 @@ public class VolumeDialogImplTest extends SysuiTestCase {
mDumpManager,
mLazySecureSettings,
mVibratorHelper,
+ mMSDLPlayer,
new FakeSystemClock(),
mVolumeDialogInteractor);
mDialog.init(0, null);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt
index 1b1d8c5d0f63..c77d0aab653d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt
@@ -28,6 +28,7 @@ import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor
import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer
import com.android.systemui.haptics.msdl.bouncerHapticPlayer
import com.android.systemui.inputmethod.domain.interactor.inputMethodInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardMediaKeyInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.user.domain.interactor.selectedUserInteractor
@@ -60,6 +61,7 @@ val Kosmos.bouncerSceneContentViewModel by Fixture {
patternViewModelFactory = patternBouncerViewModelFactory,
passwordViewModelFactory = passwordBouncerViewModelFactory,
bouncerHapticPlayer = bouncerHapticPlayer,
+ keyguardMediaKeyInteractor = keyguardMediaKeyInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/FakeMSDLPlayer.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/FakeMSDLPlayer.kt
index 2b81da33b9bc..fe82ab9ff7ed 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/FakeMSDLPlayer.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/msdl/FakeMSDLPlayer.kt
@@ -23,19 +23,24 @@ import com.google.android.msdl.domain.MSDLPlayer
import com.google.android.msdl.logging.MSDLEvent
class FakeMSDLPlayer : MSDLPlayer {
+ val tokensPlayed = mutableListOf<MSDLToken>()
+ val propertiesPlayed = mutableListOf<InteractionProperties?>()
private val history = arrayListOf<MSDLEvent>()
+
var currentFeedbackLevel = FeedbackLevel.DEFAULT
var latestTokenPlayed: MSDLToken? = null
+ get() = tokensPlayed.lastOrNull()
private set
var latestPropertiesPlayed: InteractionProperties? = null
+ get() = propertiesPlayed.lastOrNull()
private set
override fun getSystemFeedbackLevel(): FeedbackLevel = currentFeedbackLevel
override fun playToken(token: MSDLToken, properties: InteractionProperties?) {
- latestTokenPlayed = token
- latestPropertiesPlayed = properties
+ tokensPlayed.add(token)
+ propertiesPlayed.add(properties)
history.add(MSDLEvent(token, properties))
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/slider/SliderHapticsViewModelFactoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/slider/SliderHapticsViewModelFactoryKosmos.kt
index 257d758fe6e6..3fbcf7773eb7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/slider/SliderHapticsViewModelFactoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/haptics/slider/SliderHapticsViewModelFactoryKosmos.kt
@@ -18,6 +18,7 @@ package com.android.systemui.haptics.slider
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.interaction.InteractionSource
+import com.android.systemui.haptics.msdl.msdlPlayer
import com.android.systemui.haptics.slider.compose.ui.SliderHapticsViewModel
import com.android.systemui.haptics.vibratorHelper
import com.android.systemui.kosmos.Kosmos
@@ -40,6 +41,7 @@ val Kosmos.sliderHapticsViewModelFactory by
sliderHapticFeedbackConfig,
sliderTrackerConfig,
vibratorHelper,
+ msdlPlayer,
fakeSystemClock,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt
index fbfaba60ebf0..c41493eaa9c7 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/shortcut/KeyboardShortcutHelperKosmos.kt
@@ -41,7 +41,7 @@ import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
import com.android.systemui.model.sysUiState
import com.android.systemui.settings.displayTracker
-import com.android.systemui.settings.fakeUserTracker
+import com.android.systemui.settings.userTracker
var Kosmos.shortcutHelperAppCategoriesShortcutsSource: KeyboardShortcutGroupsSource by
Kosmos.Fixture { AppCategoriesShortcutsSource(windowManager, testDispatcher) }
@@ -114,7 +114,7 @@ val Kosmos.shortcutHelperViewModel by
Kosmos.Fixture {
ShortcutHelperViewModel(
mockRoleManager,
- fakeUserTracker,
+ userTracker,
applicationCoroutineScope,
testDispatcher,
shortcutHelperStateInteractor,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index e513e8d2a350..08786495eca4 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -88,9 +88,6 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository {
private val _isDreamingWithOverlay = MutableStateFlow(false)
override val isDreamingWithOverlay: Flow<Boolean> = _isDreamingWithOverlay
- private val _isActiveDreamLockscreenHosted = MutableStateFlow(false)
- override val isActiveDreamLockscreenHosted: StateFlow<Boolean> = _isActiveDreamLockscreenHosted
-
private val _dozeAmount = MutableStateFlow(0f)
override val linearDozeAmount: Flow<Float> = _dozeAmount
@@ -102,8 +99,7 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository {
private val _isUdfpsSupported = MutableStateFlow(false)
- private val _isKeyguardGoingAway = MutableStateFlow(false)
- override val isKeyguardGoingAway: Flow<Boolean> = _isKeyguardGoingAway
+ override val isKeyguardGoingAway = MutableStateFlow(false)
private val _biometricUnlockState =
MutableStateFlow(BiometricUnlockModel(BiometricUnlockMode.NONE, null))
@@ -169,7 +165,7 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository {
}
fun setKeyguardGoingAway(isGoingAway: Boolean) {
- _isKeyguardGoingAway.value = isGoingAway
+ isKeyguardGoingAway.value = isGoingAway
}
fun setKeyguardOccluded(isOccluded: Boolean) {
@@ -235,10 +231,6 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository {
_isDreamingWithOverlay.value = isDreaming
}
- override fun setIsActiveDreamLockscreenHosted(isLockscreenHosted: Boolean) {
- _isActiveDreamLockscreenHosted.value = isLockscreenHosted
- }
-
fun setDozeAmount(dozeAmount: Float) {
_dozeAmount.value = dozeAmount
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardMediaKeyInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardMediaKeyInteractorKosmos.kt
new file mode 100644
index 000000000000..6f4787b0290b
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardMediaKeyInteractorKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 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.keyguard.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.telephony.domain.interactor.telephonyInteractor
+import com.android.systemui.volume.data.repository.audioRepository
+
+val Kosmos.keyguardMediaKeyInteractor: KeyguardMediaKeyInteractor by
+ Kosmos.Fixture {
+ KeyguardMediaKeyInteractor(
+ telephonyInteractor = telephonyInteractor,
+ audioRepository = audioRepository,
+ )
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/BrightnessSliderControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/BrightnessSliderControllerKosmos.kt
index 8b7e5d8f54c5..88063c9b5db9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/settings/BrightnessSliderControllerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/settings/BrightnessSliderControllerKosmos.kt
@@ -18,6 +18,7 @@ package com.android.systemui.settings
import com.android.internal.logging.uiEventLogger
import com.android.systemui.classifier.falsingManager
+import com.android.systemui.haptics.msdl.msdlPlayer
import com.android.systemui.haptics.vibratorHelper
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.plugins.activityStarter
@@ -31,6 +32,7 @@ var Kosmos.brightnessSliderControllerFactory by
falsingManager,
uiEventLogger,
vibratorHelper,
+ msdlPlayer,
systemClock,
activityStarter,
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt
index 7f4c670b05aa..c3996e400726 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowBuilder.kt
@@ -85,7 +85,6 @@ import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent
import com.android.systemui.util.Assert.runWithCurrentThreadAsMainThread
import com.android.systemui.util.DeviceConfigProxyFake
import com.android.systemui.util.concurrency.FakeExecutor
-import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.wmshell.BubblesManager
@@ -126,6 +125,7 @@ class ExpandableNotificationRowBuilder(
private val mMainCoroutineContext = mTestScope.coroutineContext
private val mFakeSystemClock = FakeSystemClock()
private val mMainExecutor = FakeExecutor(mFakeSystemClock)
+ private val mDumpManager = DumpManager()
init {
featureFlags.setDefault(Flags.ENABLE_NOTIFICATIONS_SIMULATE_SLOW_MEASURE)
@@ -142,8 +142,7 @@ class ExpandableNotificationRowBuilder(
mGroupMembershipManager = GroupMembershipManagerImpl()
mSmartReplyController = Mockito.mock(SmartReplyController::class.java, STUB_ONLY)
- val dumpManager = DumpManager()
- mGroupExpansionManager = GroupExpansionManagerImpl(dumpManager, mGroupMembershipManager)
+ mGroupExpansionManager = GroupExpansionManagerImpl(mDumpManager, mGroupMembershipManager)
mHeadsUpManager = Mockito.mock(HeadsUpManager::class.java, STUB_ONLY)
mIconManager =
IconManager(
@@ -289,8 +288,8 @@ class ExpandableNotificationRowBuilder(
NotificationOptimizedLinearLayoutFactory(),
{ Mockito.mock(NotificationViewFlipperFactory::class.java) },
NotificationRowIconViewInflaterFactory(
- AppIconProviderImpl(context),
- NotificationIconStyleProviderImpl(),
+ AppIconProviderImpl(context, mDumpManager),
+ NotificationIconStyleProviderImpl(mDumpManager),
),
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/icon/AppIconProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/icon/AppIconProviderKosmos.kt
index 08c6bbab6dd6..0fd0f1469818 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/icon/AppIconProviderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/icon/AppIconProviderKosmos.kt
@@ -17,6 +17,8 @@
package com.android.systemui.statusbar.notification.row.icon
import android.content.applicationContext
+import com.android.systemui.dump.dumpManager
import com.android.systemui.kosmos.Kosmos
-val Kosmos.appIconProvider by Kosmos.Fixture { AppIconProviderImpl(applicationContext) }
+val Kosmos.appIconProvider by
+ Kosmos.Fixture { AppIconProviderImpl(applicationContext, dumpManager) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/icon/NotificationIconStyleProviderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/icon/NotificationIconStyleProviderKosmos.kt
index 611c90a6f4e8..0fe84fb135ab 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/icon/NotificationIconStyleProviderKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/row/icon/NotificationIconStyleProviderKosmos.kt
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.row.icon
+import com.android.systemui.dump.dumpManager
import com.android.systemui.kosmos.Kosmos
-val Kosmos.notificationIconStyleProvider by Kosmos.Fixture { NotificationIconStyleProviderImpl() }
+val Kosmos.notificationIconStyleProvider by
+ Kosmos.Fixture { NotificationIconStyleProviderImpl(dumpManager) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt
index 6be13be407d8..32191277c94a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt
@@ -23,7 +23,7 @@ class FakeConfigurationController @Inject constructor() :
listeners -= listener
}
- override fun onConfigurationChanged(newConfiguration: Configuration?) {
+ override fun onConfigurationChanged(newConfiguration: Configuration) {
listeners.forEach { it.onConfigChanged(newConfiguration) }
}
@@ -36,7 +36,7 @@ class FakeConfigurationController @Inject constructor() :
}
fun notifyConfigurationChanged() {
- onConfigurationChanged(newConfiguration = null)
+ onConfigurationChanged(newConfiguration = Configuration())
}
fun notifyLayoutDirectionChanged(isRtl: Boolean) {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/window/FakeStatusBarWindowControllerFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/window/FakeStatusBarWindowControllerFactory.kt
index bca13c6f502d..65247a55348d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/window/FakeStatusBarWindowControllerFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/window/FakeStatusBarWindowControllerFactory.kt
@@ -24,6 +24,6 @@ class FakeStatusBarWindowControllerFactory : StatusBarWindowController.Factory {
override fun create(
context: Context,
viewCaptureAwareWindowManager: ViewCaptureAwareWindowManager,
- statusBarConfigurationController: StatusBarConfigurationController
+ statusBarConfigurationController: StatusBarConfigurationController,
) = FakeStatusBarWindowController()
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/AudioRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/AudioRepositoryKosmos.kt
index 5cf214a4e04a..712ec41bbf2d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/AudioRepositoryKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/AudioRepositoryKosmos.kt
@@ -18,4 +18,5 @@ package com.android.systemui.volume.data.repository
import com.android.systemui.kosmos.Kosmos
-val Kosmos.audioRepository by Kosmos.Fixture { FakeAudioRepository() }
+val Kosmos.fakeAudioRepository by Kosmos.Fixture { FakeAudioRepository() }
+val Kosmos.audioRepository by Kosmos.Fixture { fakeAudioRepository }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt
index ba6ffd742611..16d2a18cd7b2 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt
@@ -18,6 +18,7 @@ package com.android.systemui.volume.data.repository
import android.media.AudioDeviceInfo
import android.media.AudioManager
+import android.view.KeyEvent
import com.android.settingslib.volume.data.model.VolumeControllerEvent
import com.android.settingslib.volume.data.repository.AudioRepository
import com.android.settingslib.volume.shared.model.AudioStream
@@ -61,6 +62,15 @@ class FakeAudioRepository : AudioRepository {
val isInitialized: Boolean
get() = mutableIsInitialized
+ private val _dispatchedKeyEvents = mutableListOf<KeyEvent>()
+
+ val dispatchedKeyEvents: List<KeyEvent>
+ get() {
+ val currentValue = _dispatchedKeyEvents.toList()
+ _dispatchedKeyEvents.clear()
+ return currentValue
+ }
+
override fun init() {
mutableIsInitialized = true
}
@@ -145,4 +155,8 @@ class FakeAudioRepository : AudioRepository {
mutableIsVolumeControllerVisible.value = isVisible
}
}
+
+ override fun dispatchMediaKeyEvent(event: KeyEvent) {
+ _dispatchedKeyEvents.add(event)
+ }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractorKosmos.kt
new file mode 100644
index 000000000000..c2a1544820c5
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/dialog/ringer/domain/VolumeDialogRingerInteractorKosmos.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2024 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.volume.dialog.ringer.domain
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.plugins.volumeDialogController
+import com.android.systemui.volume.dialog.domain.interactor.volumeDialogStateInteractor
+
+val Kosmos.volumeDialogRingerInteractor by
+ Kosmos.Fixture {
+ VolumeDialogRingerInteractor(
+ coroutineScope = applicationCoroutineScope,
+ volumeDialogStateInteractor = volumeDialogStateInteractor,
+ controller = volumeDialogController,
+ )
+ }
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index d9182010c1cb..ff2abd275f83 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -100,6 +100,9 @@ java_library_host {
srcs: [
"runtime-helper-src/libcore-fake/**/*.java",
],
+ libs: [
+ "app-compat-annotations",
+ ],
static_libs: [
"ravenwood-runtime-common",
],
@@ -121,6 +124,7 @@ java_library {
],
static_libs: [
"ravenwood-runtime-common",
+ "androidx.annotation_annotation",
],
libs: [
"framework-minus-apex.ravenwood",
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodConfigState.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodConfigState.java
index 3535cb2b1b79..870a10a1f57e 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodConfigState.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodConfigState.java
@@ -42,6 +42,10 @@ public class RavenwoodConfigState {
private final RavenwoodConfig mConfig;
+ // TODO: Move the other contexts from RavenwoodConfig to here too? They're used by
+ // RavenwoodRule too, but RavenwoodRule can probably use InstrumentationRegistry?
+ RavenwoodContext mSystemServerContext;
+
public RavenwoodConfigState(RavenwoodConfig config) {
mConfig = config;
}
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
index 9a145cb93811..c2806daf99a1 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java
@@ -16,6 +16,8 @@
package android.platform.test.ravenwood;
+import static android.platform.test.ravenwood.RavenwoodSystemServer.ANDROID_PACKAGE_NAME;
+
import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_INST_RESOURCE_APK;
import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_RESOURCE_APK;
import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING;
@@ -267,6 +269,13 @@ public class RavenwoodRuntimeEnvironmentController {
config.mInstContext = instContext;
config.mTargetContext = targetContext;
+ final Supplier<Resources> systemResourcesLoader = () -> {
+ return config.mState.loadResources(null);
+ };
+
+ config.mState.mSystemServerContext =
+ new RavenwoodContext(ANDROID_PACKAGE_NAME, main, systemResourcesLoader);
+
// Prepare other fields.
config.mInstrumentation = new Instrumentation();
config.mInstrumentation.basicInit(instContext, targetContext, createMockUiAutomation());
@@ -314,6 +323,9 @@ public class RavenwoodRuntimeEnvironmentController {
((RavenwoodContext) config.mTargetContext).cleanUp();
config.mTargetContext = null;
}
+ if (config.mState.mSystemServerContext != null) {
+ config.mState.mSystemServerContext.cleanUp();
+ }
Looper.getMainLooper().quit();
Looper.clearMainLooperForTest();
diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java
index 3946dd8471b0..f198a08a50e3 100644
--- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java
+++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java
@@ -33,6 +33,9 @@ import java.util.List;
import java.util.Set;
public class RavenwoodSystemServer {
+
+ static final String ANDROID_PACKAGE_NAME = "android";
+
/**
* Set of services that we know how to provide under Ravenwood. We keep this set distinct
* from {@code com.android.server.SystemServer} to give us the ability to choose either
@@ -67,7 +70,7 @@ public class RavenwoodSystemServer {
sStartedServices = new ArraySet<>();
sTimings = new TimingsTraceAndSlog();
- sServiceManager = new SystemServiceManager(config.mInstContext);
+ sServiceManager = new SystemServiceManager(config.mState.mSystemServerContext);
sServiceManager.setStartInfo(false,
SystemClock.elapsedRealtime(),
SystemClock.uptimeMillis());
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java
index 1f6e11dd5cf2..37b0abcceede 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java
@@ -67,6 +67,7 @@ public final class RavenwoodConfig {
String mTargetPackageName;
int mMinSdkLevel;
+ int mTargetSdkLevel;
boolean mProvideMainThread = false;
@@ -150,6 +151,14 @@ public final class RavenwoodConfig {
}
/**
+ * Configure the target SDK level of the test.
+ */
+ public Builder setTargetSdkLevel(int sdkLevel) {
+ mConfig.mTargetSdkLevel = sdkLevel;
+ return this;
+ }
+
+ /**
* Configure a "main" thread to be available for the duration of the test, as defined
* by {@code Looper.getMainLooper()}. Has no effect on non-Ravenwood environments.
*
diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java
index ced151927fdc..9bc45bee1775 100644
--- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java
+++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java
@@ -146,6 +146,9 @@ public class RavenwoodSystemProperties {
if (root.startsWith("soc.")) return true;
if (root.startsWith("system.")) return true;
+ // For PropertyInvalidatedCache
+ if (root.startsWith("cache_key.")) return true;
+
switch (key) {
case "gsm.version.baseband":
case "no.such.thing":
@@ -170,6 +173,9 @@ public class RavenwoodSystemProperties {
if (root.startsWith("debug.")) return true;
+ // For PropertyInvalidatedCache
+ if (root.startsWith("cache_key.")) return true;
+
return mKeyWritable.contains(key);
}
diff --git a/ravenwood/runtime-helper-src/framework/android/util/StatsEvent.java b/ravenwood/runtime-helper-src/framework/android/util/StatsEvent.java
new file mode 100644
index 000000000000..1e3b3fcd733f
--- /dev/null
+++ b/ravenwood/runtime-helper-src/framework/android/util/StatsEvent.java
@@ -0,0 +1,1035 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+// [ravenwood] This is an exact copy from StatsD, until we make StatsD available on Ravenwood.
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Build;
+import android.os.SystemClock;
+
+import androidx.annotation.RequiresApi;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+/**
+ * StatsEvent builds and stores the buffer sent over the statsd socket.
+ * This class defines and encapsulates the socket protocol.
+ *
+ * <p>Usage:</p>
+ * <pre>
+ * // Pushed event
+ * StatsEvent statsEvent = StatsEvent.newBuilder()
+ * .setAtomId(atomId)
+ * .writeBoolean(false)
+ * .writeString("annotated String field")
+ * .addBooleanAnnotation(annotationId, true)
+ * .usePooledBuffer()
+ * .build();
+ * StatsLog.write(statsEvent);
+ *
+ * // Pulled event
+ * StatsEvent statsEvent = StatsEvent.newBuilder()
+ * .setAtomId(atomId)
+ * .writeBoolean(false)
+ * .writeString("annotated String field")
+ * .addBooleanAnnotation(annotationId, true)
+ * .build();
+ * </pre>
+ * @hide
+ **/
+@SystemApi
+public final class StatsEvent {
+ // Type Ids.
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_INT = 0x00;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_LONG = 0x01;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_STRING = 0x02;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_LIST = 0x03;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_FLOAT = 0x04;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_BOOLEAN = 0x05;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_BYTE_ARRAY = 0x06;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_OBJECT = 0x07;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_KEY_VALUE_PAIRS = 0x08;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_ATTRIBUTION_CHAIN = 0x09;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final byte TYPE_ERRORS = 0x0F;
+
+ // Error flags.
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_NO_TIMESTAMP = 0x1;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_NO_ATOM_ID = 0x2;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_OVERFLOW = 0x4;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_ATTRIBUTION_CHAIN_TOO_LONG = 0x8;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_TOO_MANY_KEY_VALUE_PAIRS = 0x10;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD = 0x20;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_INVALID_ANNOTATION_ID = 0x40;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_ANNOTATION_ID_TOO_LARGE = 0x80;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_TOO_MANY_ANNOTATIONS = 0x100;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_TOO_MANY_FIELDS = 0x200;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL = 0x1000;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int ERROR_ATOM_ID_INVALID_POSITION = 0x2000;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting public static final int ERROR_LIST_TOO_LONG = 0x4000;
+
+ // Size limits.
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int MAX_ANNOTATION_COUNT = 15;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int MAX_ATTRIBUTION_NODES = 127;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int MAX_NUM_ELEMENTS = 127;
+
+ /**
+ * @hide
+ **/
+ @VisibleForTesting
+ public static final int MAX_KEY_VALUE_PAIRS = 127;
+
+ private static final int LOGGER_ENTRY_MAX_PAYLOAD = 4068;
+
+ // Max payload size is 4 bytes less as 4 bytes are reserved for statsEventTag.
+ // See android_util_StatsLog.cpp.
+ private static final int MAX_PUSH_PAYLOAD_SIZE = LOGGER_ENTRY_MAX_PAYLOAD - 4;
+
+ private static final int MAX_PULL_PAYLOAD_SIZE = 50 * 1024; // 50 KB
+
+ private final int mAtomId;
+ private final byte[] mPayload;
+ private Buffer mBuffer;
+ private final int mNumBytes;
+
+ private StatsEvent(final int atomId, @Nullable final Buffer buffer,
+ @NonNull final byte[] payload, final int numBytes) {
+ mAtomId = atomId;
+ mBuffer = buffer;
+ mPayload = payload;
+ mNumBytes = numBytes;
+ }
+
+ /**
+ * Returns a new StatsEvent.Builder for building StatsEvent object.
+ **/
+ @NonNull
+ public static Builder newBuilder() {
+ return new Builder(Buffer.obtain());
+ }
+
+ /**
+ * Get the atom Id of the atom encoded in this StatsEvent object.
+ *
+ * @hide
+ **/
+ public int getAtomId() {
+ return mAtomId;
+ }
+
+ /**
+ * Get the byte array that contains the encoded payload that can be sent to statsd.
+ *
+ * @hide
+ **/
+ @NonNull
+ public byte[] getBytes() {
+ return mPayload;
+ }
+
+ /**
+ * Get the number of bytes used to encode the StatsEvent payload.
+ *
+ * @hide
+ **/
+ public int getNumBytes() {
+ return mNumBytes;
+ }
+
+ /**
+ * Recycle resources used by this StatsEvent object.
+ * No actions should be taken on this StatsEvent after release() is called.
+ *
+ * @hide
+ **/
+ public void release() {
+ if (mBuffer != null) {
+ mBuffer.release();
+ mBuffer = null;
+ }
+ }
+
+ /**
+ * Builder for constructing a StatsEvent object.
+ *
+ * <p>This class defines and encapsulates the socket encoding for the
+ *buffer. The write methods must be called in the same order as the order of
+ *fields in the atom definition.</p>
+ *
+ * <p>setAtomId() must be called immediately after
+ *StatsEvent.newBuilder().</p>
+ *
+ * <p>Example:</p>
+ * <pre>
+ * // Atom definition.
+ * message MyAtom {
+ * optional int32 field1 = 1;
+ * optional int64 field2 = 2;
+ * optional string field3 = 3 [(annotation1) = true];
+ * optional repeated int32 field4 = 4;
+ * }
+ *
+ * // StatsEvent construction for pushed event.
+ * StatsEvent.newBuilder()
+ * StatsEvent statsEvent = StatsEvent.newBuilder()
+ * .setAtomId(atomId)
+ * .writeInt(3) // field1
+ * .writeLong(8L) // field2
+ * .writeString("foo") // field 3
+ * .addBooleanAnnotation(annotation1Id, true)
+ * .writeIntArray({ 1, 2, 3 });
+ * .usePooledBuffer()
+ * .build();
+ *
+ * // StatsEvent construction for pulled event.
+ * StatsEvent.newBuilder()
+ * StatsEvent statsEvent = StatsEvent.newBuilder()
+ * .setAtomId(atomId)
+ * .writeInt(3) // field1
+ * .writeLong(8L) // field2
+ * .writeString("foo") // field 3
+ * .addBooleanAnnotation(annotation1Id, true)
+ * .writeIntArray({ 1, 2, 3 });
+ * .build();
+ * </pre>
+ **/
+ public static final class Builder {
+ // Fixed positions.
+ private static final int POS_NUM_ELEMENTS = 1;
+ private static final int POS_TIMESTAMP_NS = POS_NUM_ELEMENTS + Byte.BYTES;
+ private static final int POS_ATOM_ID = POS_TIMESTAMP_NS + Byte.BYTES + Long.BYTES;
+
+ private final Buffer mBuffer;
+ private long mTimestampNs;
+ private int mAtomId;
+ private byte mCurrentAnnotationCount;
+ private int mPos;
+ private int mPosLastField;
+ private byte mLastType;
+ private int mNumElements;
+ private int mErrorMask;
+ private boolean mUsePooledBuffer = false;
+
+ private Builder(final Buffer buffer) {
+ mBuffer = buffer;
+ mCurrentAnnotationCount = 0;
+ mAtomId = 0;
+ mTimestampNs = SystemClock.elapsedRealtimeNanos();
+ mNumElements = 0;
+
+ // Set mPos to 0 for writing TYPE_OBJECT at 0th position.
+ mPos = 0;
+ writeTypeId(TYPE_OBJECT);
+
+ // Write timestamp.
+ mPos = POS_TIMESTAMP_NS;
+ writeLong(mTimestampNs);
+ }
+
+ /**
+ * Sets the atom id for this StatsEvent.
+ *
+ * This should be called immediately after StatsEvent.newBuilder()
+ * and should only be called once.
+ * Not calling setAtomId will result in ERROR_NO_ATOM_ID.
+ * Calling setAtomId out of order will result in ERROR_ATOM_ID_INVALID_POSITION.
+ **/
+ @NonNull
+ public Builder setAtomId(final int atomId) {
+ if (0 == mAtomId) {
+ mAtomId = atomId;
+
+ if (1 == mNumElements) { // Only timestamp is written so far.
+ writeInt(atomId);
+ } else {
+ // setAtomId called out of order.
+ mErrorMask |= ERROR_ATOM_ID_INVALID_POSITION;
+ }
+ }
+
+ return this;
+ }
+
+ /**
+ * Write a boolean field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeBoolean(final boolean value) {
+ // Write boolean typeId byte followed by boolean byte representation.
+ writeTypeId(TYPE_BOOLEAN);
+ mPos += mBuffer.putBoolean(mPos, value);
+ mNumElements++;
+ return this;
+ }
+
+ /**
+ * Write an integer field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeInt(final int value) {
+ // Write integer typeId byte followed by 4-byte representation of value.
+ writeTypeId(TYPE_INT);
+ mPos += mBuffer.putInt(mPos, value);
+ mNumElements++;
+ return this;
+ }
+
+ /**
+ * Write a long field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeLong(final long value) {
+ // Write long typeId byte followed by 8-byte representation of value.
+ writeTypeId(TYPE_LONG);
+ mPos += mBuffer.putLong(mPos, value);
+ mNumElements++;
+ return this;
+ }
+
+ /**
+ * Write a float field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeFloat(final float value) {
+ // Write float typeId byte followed by 4-byte representation of value.
+ writeTypeId(TYPE_FLOAT);
+ mPos += mBuffer.putFloat(mPos, value);
+ mNumElements++;
+ return this;
+ }
+
+ /**
+ * Write a String field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeString(@NonNull final String value) {
+ // Write String typeId byte, followed by 4-byte representation of number of bytes
+ // in the UTF-8 encoding, followed by the actual UTF-8 byte encoding of value.
+ final byte[] valueBytes = stringToBytes(value);
+ writeByteArray(valueBytes, TYPE_STRING);
+ return this;
+ }
+
+ /**
+ * Write a byte array field to this StatsEvent.
+ **/
+ @NonNull
+ public Builder writeByteArray(@NonNull final byte[] value) {
+ // Write byte array typeId byte, followed by 4-byte representation of number of bytes
+ // in value, followed by the actual byte array.
+ writeByteArray(value, TYPE_BYTE_ARRAY);
+ return this;
+ }
+
+ private void writeByteArray(@NonNull final byte[] value, final byte typeId) {
+ writeTypeId(typeId);
+ final int numBytes = value.length;
+ mPos += mBuffer.putInt(mPos, numBytes);
+ mPos += mBuffer.putByteArray(mPos, value);
+ mNumElements++;
+ }
+
+ /**
+ * Write an attribution chain field to this StatsEvent.
+ *
+ * The sizes of uids and tags must be equal. The AttributionNode at position i is
+ * made up of uids[i] and tags[i].
+ *
+ * @param uids array of uids in the attribution nodes.
+ * @param tags array of tags in the attribution nodes.
+ **/
+ @NonNull
+ public Builder writeAttributionChain(
+ @NonNull final int[] uids, @NonNull final String[] tags) {
+ final byte numUids = (byte) uids.length;
+ final byte numTags = (byte) tags.length;
+
+ if (numUids != numTags) {
+ mErrorMask |= ERROR_ATTRIBUTION_UIDS_TAGS_SIZES_NOT_EQUAL;
+ } else if (numUids > MAX_ATTRIBUTION_NODES) {
+ mErrorMask |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG;
+ } else {
+ // Write attribution chain typeId byte, followed by 1-byte representation of
+ // number of attribution nodes, followed by encoding of each attribution node.
+ writeTypeId(TYPE_ATTRIBUTION_CHAIN);
+ mPos += mBuffer.putByte(mPos, numUids);
+ for (int i = 0; i < numUids; i++) {
+ // Each uid is encoded as 4-byte representation of its int value.
+ mPos += mBuffer.putInt(mPos, uids[i]);
+
+ // Each tag is encoded as 4-byte representation of number of bytes in its
+ // UTF-8 encoding, followed by the actual UTF-8 bytes.
+ final byte[] tagBytes = stringToBytes(tags[i]);
+ mPos += mBuffer.putInt(mPos, tagBytes.length);
+ mPos += mBuffer.putByteArray(mPos, tagBytes);
+ }
+ mNumElements++;
+ }
+ return this;
+ }
+
+ /**
+ * Write KeyValuePairsAtom entries to this StatsEvent.
+ *
+ * @param intMap Integer key-value pairs.
+ * @param longMap Long key-value pairs.
+ * @param stringMap String key-value pairs.
+ * @param floatMap Float key-value pairs.
+ **/
+ @NonNull
+ public Builder writeKeyValuePairs(
+ @Nullable final SparseIntArray intMap,
+ @Nullable final SparseLongArray longMap,
+ @Nullable final SparseArray<String> stringMap,
+ @Nullable final SparseArray<Float> floatMap) {
+ final int intMapSize = null == intMap ? 0 : intMap.size();
+ final int longMapSize = null == longMap ? 0 : longMap.size();
+ final int stringMapSize = null == stringMap ? 0 : stringMap.size();
+ final int floatMapSize = null == floatMap ? 0 : floatMap.size();
+ final int totalCount = intMapSize + longMapSize + stringMapSize + floatMapSize;
+
+ if (totalCount > MAX_KEY_VALUE_PAIRS) {
+ mErrorMask |= ERROR_TOO_MANY_KEY_VALUE_PAIRS;
+ } else {
+ writeTypeId(TYPE_KEY_VALUE_PAIRS);
+ mPos += mBuffer.putByte(mPos, (byte) totalCount);
+
+ for (int i = 0; i < intMapSize; i++) {
+ final int key = intMap.keyAt(i);
+ final int value = intMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_INT);
+ mPos += mBuffer.putInt(mPos, value);
+ }
+
+ for (int i = 0; i < longMapSize; i++) {
+ final int key = longMap.keyAt(i);
+ final long value = longMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_LONG);
+ mPos += mBuffer.putLong(mPos, value);
+ }
+
+ for (int i = 0; i < stringMapSize; i++) {
+ final int key = stringMap.keyAt(i);
+ final String value = stringMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_STRING);
+ final byte[] valueBytes = stringToBytes(value);
+ mPos += mBuffer.putInt(mPos, valueBytes.length);
+ mPos += mBuffer.putByteArray(mPos, valueBytes);
+ }
+
+ for (int i = 0; i < floatMapSize; i++) {
+ final int key = floatMap.keyAt(i);
+ final float value = floatMap.valueAt(i);
+ mPos += mBuffer.putInt(mPos, key);
+ writeTypeId(TYPE_FLOAT);
+ mPos += mBuffer.putFloat(mPos, value);
+ }
+
+ mNumElements++;
+ }
+
+ return this;
+ }
+
+ /**
+ * Write a repeated boolean field to this StatsEvent.
+ *
+ * The list size must not exceed 127. Otherwise, the array isn't written
+ * to the StatsEvent and ERROR_LIST_TOO_LONG is appended to the
+ * StatsEvent errors field.
+ *
+ * @param elements array of booleans.
+ **/
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @NonNull
+ public Builder writeBooleanArray(@NonNull final boolean[] elements) {
+ final byte numElements = (byte)elements.length;
+
+ if (writeArrayInfo(numElements, TYPE_BOOLEAN)) {
+ // Write encoding of each element.
+ for (int i = 0; i < numElements; i++) {
+ mPos += mBuffer.putBoolean(mPos, elements[i]);
+ }
+ mNumElements++;
+ }
+ return this;
+ }
+
+ /**
+ * Write a repeated int field to this StatsEvent.
+ *
+ * The list size must not exceed 127. Otherwise, the array isn't written
+ * to the StatsEvent and ERROR_LIST_TOO_LONG is appended to the
+ * StatsEvent errors field.
+ *
+ * @param elements array of ints.
+ **/
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @NonNull
+ public Builder writeIntArray(@NonNull final int[] elements) {
+ final byte numElements = (byte)elements.length;
+
+ if (writeArrayInfo(numElements, TYPE_INT)) {
+ // Write encoding of each element.
+ for (int i = 0; i < numElements; i++) {
+ mPos += mBuffer.putInt(mPos, elements[i]);
+ }
+ mNumElements++;
+ }
+ return this;
+ }
+
+ /**
+ * Write a repeated long field to this StatsEvent.
+ *
+ * The list size must not exceed 127. Otherwise, the array isn't written
+ * to the StatsEvent and ERROR_LIST_TOO_LONG is appended to the
+ * StatsEvent errors field.
+ *
+ * @param elements array of longs.
+ **/
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @NonNull
+ public Builder writeLongArray(@NonNull final long[] elements) {
+ final byte numElements = (byte)elements.length;
+
+ if (writeArrayInfo(numElements, TYPE_LONG)) {
+ // Write encoding of each element.
+ for (int i = 0; i < numElements; i++) {
+ mPos += mBuffer.putLong(mPos, elements[i]);
+ }
+ mNumElements++;
+ }
+ return this;
+ }
+
+ /**
+ * Write a repeated float field to this StatsEvent.
+ *
+ * The list size must not exceed 127. Otherwise, the array isn't written
+ * to the StatsEvent and ERROR_LIST_TOO_LONG is appended to the
+ * StatsEvent errors field.
+ *
+ * @param elements array of floats.
+ **/
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @NonNull
+ public Builder writeFloatArray(@NonNull final float[] elements) {
+ final byte numElements = (byte)elements.length;
+
+ if (writeArrayInfo(numElements, TYPE_FLOAT)) {
+ // Write encoding of each element.
+ for (int i = 0; i < numElements; i++) {
+ mPos += mBuffer.putFloat(mPos, elements[i]);
+ }
+ mNumElements++;
+ }
+ return this;
+ }
+
+ /**
+ * Write a repeated string field to this StatsEvent.
+ *
+ * The list size must not exceed 127. Otherwise, the array isn't written
+ * to the StatsEvent and ERROR_LIST_TOO_LONG is appended to the
+ * StatsEvent errors field.
+ *
+ * @param elements array of strings.
+ **/
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ @NonNull
+ public Builder writeStringArray(@NonNull final String[] elements) {
+ final byte numElements = (byte)elements.length;
+
+ if (writeArrayInfo(numElements, TYPE_STRING)) {
+ // Write encoding of each element.
+ for (int i = 0; i < numElements; i++) {
+ final byte[] elementBytes = stringToBytes(elements[i]);
+ mPos += mBuffer.putInt(mPos, elementBytes.length);
+ mPos += mBuffer.putByteArray(mPos, elementBytes);
+ }
+ mNumElements++;
+ }
+ return this;
+ }
+
+ /**
+ * Write a boolean annotation for the last field written.
+ **/
+ @NonNull
+ public Builder addBooleanAnnotation(
+ final byte annotationId, final boolean value) {
+ // Ensure there's a field written to annotate.
+ if (mNumElements < 2) {
+ mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
+ } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) {
+ mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS;
+ } else {
+ mPos += mBuffer.putByte(mPos, annotationId);
+ mPos += mBuffer.putByte(mPos, TYPE_BOOLEAN);
+ mPos += mBuffer.putBoolean(mPos, value);
+ mCurrentAnnotationCount++;
+ writeAnnotationCount();
+ }
+
+ return this;
+ }
+
+ /**
+ * Write an integer annotation for the last field written.
+ **/
+ @NonNull
+ public Builder addIntAnnotation(final byte annotationId, final int value) {
+ if (mNumElements < 2) {
+ mErrorMask |= ERROR_ANNOTATION_DOES_NOT_FOLLOW_FIELD;
+ } else if (mCurrentAnnotationCount >= MAX_ANNOTATION_COUNT) {
+ mErrorMask |= ERROR_TOO_MANY_ANNOTATIONS;
+ } else {
+ mPos += mBuffer.putByte(mPos, annotationId);
+ mPos += mBuffer.putByte(mPos, TYPE_INT);
+ mPos += mBuffer.putInt(mPos, value);
+ mCurrentAnnotationCount++;
+ writeAnnotationCount();
+ }
+
+ return this;
+ }
+
+ /**
+ * Indicates to reuse Buffer's byte array as the underlying payload in StatsEvent.
+ * This should be called for pushed events to reduce memory allocations and garbage
+ * collections.
+ **/
+ @NonNull
+ public Builder usePooledBuffer() {
+ mUsePooledBuffer = true;
+ mBuffer.setMaxSize(MAX_PUSH_PAYLOAD_SIZE, mPos);
+ return this;
+ }
+
+ /**
+ * Builds a StatsEvent object with values entered in this Builder.
+ **/
+ @NonNull
+ public StatsEvent build() {
+ if (0L == mTimestampNs) {
+ mErrorMask |= ERROR_NO_TIMESTAMP;
+ }
+ if (0 == mAtomId) {
+ mErrorMask |= ERROR_NO_ATOM_ID;
+ }
+ if (mBuffer.hasOverflowed()) {
+ mErrorMask |= ERROR_OVERFLOW;
+ }
+ if (mNumElements > MAX_NUM_ELEMENTS) {
+ mErrorMask |= ERROR_TOO_MANY_FIELDS;
+ }
+
+ if (0 == mErrorMask) {
+ mBuffer.putByte(POS_NUM_ELEMENTS, (byte) mNumElements);
+ } else {
+ // Write atom id and error mask. Overwrite any annotations for atom Id.
+ mPos = POS_ATOM_ID;
+ mPos += mBuffer.putByte(mPos, TYPE_INT);
+ mPos += mBuffer.putInt(mPos, mAtomId);
+ mPos += mBuffer.putByte(mPos, TYPE_ERRORS);
+ mPos += mBuffer.putInt(mPos, mErrorMask);
+ mBuffer.putByte(POS_NUM_ELEMENTS, (byte) 3);
+ }
+
+ final int size = mPos;
+
+ if (mUsePooledBuffer) {
+ return new StatsEvent(mAtomId, mBuffer, mBuffer.getBytes(), size);
+ } else {
+ // Create a copy of the buffer with the required number of bytes.
+ final byte[] payload = new byte[size];
+ System.arraycopy(mBuffer.getBytes(), 0, payload, 0, size);
+
+ // Return Buffer instance to the pool.
+ mBuffer.release();
+
+ return new StatsEvent(mAtomId, null, payload, size);
+ }
+ }
+
+ private void writeTypeId(final byte typeId) {
+ mPosLastField = mPos;
+ mLastType = typeId;
+ mCurrentAnnotationCount = 0;
+ final byte encodedId = (byte) (typeId & 0x0F);
+ mPos += mBuffer.putByte(mPos, encodedId);
+ }
+
+ private void writeAnnotationCount() {
+ // Use first 4 bits for annotation count and last 4 bits for typeId.
+ final byte encodedId = (byte) ((mCurrentAnnotationCount << 4) | (mLastType & 0x0F));
+ mBuffer.putByte(mPosLastField, encodedId);
+ }
+
+ @NonNull
+ private static byte[] stringToBytes(@Nullable final String value) {
+ return (null == value ? "" : value).getBytes(UTF_8);
+ }
+
+ private boolean writeArrayInfo(final byte numElements,
+ final byte elementTypeId) {
+ if (numElements > MAX_NUM_ELEMENTS) {
+ mErrorMask |= ERROR_LIST_TOO_LONG;
+ return false;
+ }
+ // Write list typeId byte, 1-byte representation of number of
+ // elements, and element typeId byte.
+ writeTypeId(TYPE_LIST);
+ mPos += mBuffer.putByte(mPos, numElements);
+ // Write element typeId byte without setting mPosLastField and mLastType (i.e. don't use
+ // #writeTypeId)
+ final byte encodedId = (byte) (elementTypeId & 0x0F);
+ mPos += mBuffer.putByte(mPos, encodedId);
+ return true;
+ }
+ }
+
+ private static final class Buffer {
+ private static Object sLock = new Object();
+
+ @GuardedBy("sLock")
+ private static Buffer sPool;
+
+ private byte[] mBytes;
+ private boolean mOverflow = false;
+ private int mMaxSize = MAX_PULL_PAYLOAD_SIZE;
+
+ @NonNull
+ private static Buffer obtain() {
+ final Buffer buffer;
+ synchronized (sLock) {
+ buffer = null == sPool ? new Buffer() : sPool;
+ sPool = null;
+ }
+ buffer.reset();
+ return buffer;
+ }
+
+ private Buffer() {
+ final ByteBuffer tempBuffer = ByteBuffer.allocateDirect(MAX_PUSH_PAYLOAD_SIZE);
+ mBytes = tempBuffer.hasArray() ? tempBuffer.array() : new byte [MAX_PUSH_PAYLOAD_SIZE];
+ }
+
+ @NonNull
+ private byte[] getBytes() {
+ return mBytes;
+ }
+
+ private void release() {
+ // Recycle this Buffer if its size is MAX_PUSH_PAYLOAD_SIZE or under.
+ if (mMaxSize <= MAX_PUSH_PAYLOAD_SIZE) {
+ synchronized (sLock) {
+ if (null == sPool) {
+ sPool = this;
+ }
+ }
+ }
+ }
+
+ private void reset() {
+ mOverflow = false;
+ mMaxSize = MAX_PULL_PAYLOAD_SIZE;
+ }
+
+ private void setMaxSize(final int maxSize, final int numBytesWritten) {
+ mMaxSize = maxSize;
+ if (numBytesWritten > maxSize) {
+ mOverflow = true;
+ }
+ }
+
+ private boolean hasOverflowed() {
+ return mOverflow;
+ }
+
+ /**
+ * Checks for available space in the byte array.
+ *
+ * @param index starting position in the buffer to start the check.
+ * @param numBytes number of bytes to check from index.
+ * @return true if space is available, false otherwise.
+ **/
+ private boolean hasEnoughSpace(final int index, final int numBytes) {
+ final int totalBytesNeeded = index + numBytes;
+
+ if (totalBytesNeeded > mMaxSize) {
+ mOverflow = true;
+ return false;
+ }
+
+ // Expand buffer if needed.
+ if (mBytes.length < mMaxSize && totalBytesNeeded > mBytes.length) {
+ int newSize = mBytes.length;
+ do {
+ newSize *= 2;
+ } while (newSize <= totalBytesNeeded);
+
+ if (newSize > mMaxSize) {
+ newSize = mMaxSize;
+ }
+
+ mBytes = Arrays.copyOf(mBytes, newSize);
+ }
+
+ return true;
+ }
+
+ /**
+ * Writes a byte into the buffer.
+ *
+ * @param index position in the buffer where the byte is written.
+ * @param value the byte to write.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putByte(final int index, final byte value) {
+ if (hasEnoughSpace(index, Byte.BYTES)) {
+ mBytes[index] = (byte) (value);
+ return Byte.BYTES;
+ }
+ return 0;
+ }
+
+ /**
+ * Writes a boolean into the buffer.
+ *
+ * @param index position in the buffer where the boolean is written.
+ * @param value the boolean to write.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putBoolean(final int index, final boolean value) {
+ return putByte(index, (byte) (value ? 1 : 0));
+ }
+
+ /**
+ * Writes an integer into the buffer.
+ *
+ * @param index position in the buffer where the integer is written.
+ * @param value the integer to write.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putInt(final int index, final int value) {
+ if (hasEnoughSpace(index, Integer.BYTES)) {
+ // Use little endian byte order.
+ mBytes[index] = (byte) (value);
+ mBytes[index + 1] = (byte) (value >> 8);
+ mBytes[index + 2] = (byte) (value >> 16);
+ mBytes[index + 3] = (byte) (value >> 24);
+ return Integer.BYTES;
+ }
+ return 0;
+ }
+
+ /**
+ * Writes a long into the buffer.
+ *
+ * @param index position in the buffer where the long is written.
+ * @param value the long to write.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putLong(final int index, final long value) {
+ if (hasEnoughSpace(index, Long.BYTES)) {
+ // Use little endian byte order.
+ mBytes[index] = (byte) (value);
+ mBytes[index + 1] = (byte) (value >> 8);
+ mBytes[index + 2] = (byte) (value >> 16);
+ mBytes[index + 3] = (byte) (value >> 24);
+ mBytes[index + 4] = (byte) (value >> 32);
+ mBytes[index + 5] = (byte) (value >> 40);
+ mBytes[index + 6] = (byte) (value >> 48);
+ mBytes[index + 7] = (byte) (value >> 56);
+ return Long.BYTES;
+ }
+ return 0;
+ }
+
+ /**
+ * Writes a float into the buffer.
+ *
+ * @param index position in the buffer where the float is written.
+ * @param value the float to write.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putFloat(final int index, final float value) {
+ return putInt(index, Float.floatToIntBits(value));
+ }
+
+ /**
+ * Copies a byte array into the buffer.
+ *
+ * @param index position in the buffer where the byte array is copied.
+ * @param value the byte array to copy.
+ * @return number of bytes written to buffer from this write operation.
+ **/
+ private int putByteArray(final int index, @NonNull final byte[] value) {
+ final int numBytes = value.length;
+ if (hasEnoughSpace(index, numBytes)) {
+ System.arraycopy(value, 0, mBytes, index, numBytes);
+ return numBytes;
+ }
+ return 0;
+ }
+ }
+}
diff --git a/ravenwood/runtime-helper-src/framework/android/util/StatsLog.java b/ravenwood/runtime-helper-src/framework/android/util/StatsLog.java
new file mode 100644
index 000000000000..c1c20cfac9dd
--- /dev/null
+++ b/ravenwood/runtime-helper-src/framework/android/util/StatsLog.java
@@ -0,0 +1,478 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+/*
+ * [Ravenwood] This is copied from StatsD, with the following changes:
+ * - The static {} is commented out.
+ * - All references to IStatsD and StatsdStatsLog are commented out.
+ * - The native method is no-oped.
+ */
+
+import static android.Manifest.permission.DUMP;
+import static android.Manifest.permission.PACKAGE_USAGE_STATS;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.os.Build;
+//import android.os.IStatsd;
+import android.os.Process;
+import android.util.proto.ProtoOutputStream;
+
+import androidx.annotation.RequiresApi;
+
+//import com.android.internal.statsd.StatsdStatsLog;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * StatsLog provides an API for developers to send events to statsd. The events can be used to
+ * define custom metrics in side statsd.
+ */
+public final class StatsLog {
+
+// // Load JNI library
+// static {
+// System.loadLibrary("stats_jni");
+// }
+ private static final String TAG = "StatsLog";
+ private static final boolean DEBUG = false;
+ private static final int EXPERIMENT_IDS_FIELD_ID = 1;
+
+ /**
+ * Annotation ID constant for logging UID field.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ public static final byte ANNOTATION_ID_IS_UID = 1;
+
+ /**
+ * Annotation ID constant to indicate logged atom event's timestamp should be truncated.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ public static final byte ANNOTATION_ID_TRUNCATE_TIMESTAMP = 2;
+
+ /**
+ * Annotation ID constant for a state atom's primary field.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ public static final byte ANNOTATION_ID_PRIMARY_FIELD = 3;
+
+ /**
+ * Annotation ID constant for state atom's state field.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ public static final byte ANNOTATION_ID_EXCLUSIVE_STATE = 4;
+
+ /**
+ * Annotation ID constant to indicate the first UID in the attribution chain
+ * is a primary field.
+ * Should only be used for attribution chain fields.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ public static final byte ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID = 5;
+
+ /**
+ * Annotation ID constant to indicate which state is default for the state atom.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ public static final byte ANNOTATION_ID_DEFAULT_STATE = 6;
+
+ /**
+ * Annotation ID constant to signal all states should be reset to the default state.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ public static final byte ANNOTATION_ID_TRIGGER_STATE_RESET = 7;
+
+ /**
+ * Annotation ID constant to indicate state changes need to account for nesting.
+ * This should only be used with binary state atoms.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ public static final byte ANNOTATION_ID_STATE_NESTED = 8;
+
+ /**
+ * Annotation ID constant to indicate the restriction category of an atom.
+ * This annotation must only be attached to the atom id. This is an int annotation.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final byte ANNOTATION_ID_RESTRICTION_CATEGORY = 9;
+
+ /**
+ * Annotation ID to indicate that a field of an atom contains peripheral device info.
+ * This is a bool annotation.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final byte ANNOTATION_ID_FIELD_RESTRICTION_PERIPHERAL_DEVICE_INFO = 10;
+
+ /**
+ * Annotation ID to indicate that a field of an atom contains app usage information.
+ * This is a bool annotation.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final byte ANNOTATION_ID_FIELD_RESTRICTION_APP_USAGE = 11;
+
+ /**
+ * Annotation ID to indicate that a field of an atom contains app activity information.
+ * This is a bool annotation.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final byte ANNOTATION_ID_FIELD_RESTRICTION_APP_ACTIVITY = 12;
+
+ /**
+ * Annotation ID to indicate that a field of an atom contains health connect information.
+ * This is a bool annotation.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final byte ANNOTATION_ID_FIELD_RESTRICTION_HEALTH_CONNECT = 13;
+
+ /**
+ * Annotation ID to indicate that a field of an atom contains accessibility information.
+ * This is a bool annotation.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final byte ANNOTATION_ID_FIELD_RESTRICTION_ACCESSIBILITY = 14;
+
+ /**
+ * Annotation ID to indicate that a field of an atom contains system search information.
+ * This is a bool annotation.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final byte ANNOTATION_ID_FIELD_RESTRICTION_SYSTEM_SEARCH = 15;
+
+ /**
+ * Annotation ID to indicate that a field of an atom contains user engagement information.
+ * This is a bool annotation.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final byte ANNOTATION_ID_FIELD_RESTRICTION_USER_ENGAGEMENT = 16;
+
+ /**
+ * Annotation ID to indicate that a field of an atom contains ambient sensing information.
+ * This is a bool annotation.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final byte ANNOTATION_ID_FIELD_RESTRICTION_AMBIENT_SENSING = 17;
+
+ /**
+ * Annotation ID to indicate that a field of an atom contains demographic classification
+ * information. This is a bool annotation.
+ *
+ * The ID is a byte since StatsEvent.addBooleanAnnotation() and StatsEvent.addIntAnnotation()
+ * accept byte as the type for annotation ids to save space.
+ *
+ * @hide
+ */
+ @SuppressLint("NoByteOrShort")
+ @SystemApi
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final byte ANNOTATION_ID_FIELD_RESTRICTION_DEMOGRAPHIC_CLASSIFICATION = 18;
+
+
+ /** @hide */
+ @IntDef(prefix = { "RESTRICTION_CATEGORY_" }, value = {
+ RESTRICTION_CATEGORY_DIAGNOSTIC,
+ RESTRICTION_CATEGORY_SYSTEM_INTELLIGENCE,
+ RESTRICTION_CATEGORY_AUTHENTICATION,
+ RESTRICTION_CATEGORY_FRAUD_AND_ABUSE})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface RestrictionCategory {}
+
+ /**
+ * Restriction category for atoms about diagnostics.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final int RESTRICTION_CATEGORY_DIAGNOSTIC = 1;
+
+ /**
+ * Restriction category for atoms about system intelligence.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final int RESTRICTION_CATEGORY_SYSTEM_INTELLIGENCE = 2;
+
+ /**
+ * Restriction category for atoms about authentication.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final int RESTRICTION_CATEGORY_AUTHENTICATION = 3;
+
+ /**
+ * Restriction category for atoms about fraud and abuse.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
+ public static final int RESTRICTION_CATEGORY_FRAUD_AND_ABUSE = 4;
+
+ private StatsLog() {
+ }
+
+ /**
+ * Logs a start event.
+ *
+ * @param label developer-chosen label.
+ * @return True if the log request was sent to statsd.
+ */
+ public static boolean logStart(int label) {
+ int callingUid = Process.myUid();
+// StatsdStatsLog.write(
+// StatsdStatsLog.APP_BREADCRUMB_REPORTED,
+// callingUid,
+// label,
+// StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__START);
+ return true;
+ }
+
+ /**
+ * Logs a stop event.
+ *
+ * @param label developer-chosen label.
+ * @return True if the log request was sent to statsd.
+ */
+ public static boolean logStop(int label) {
+ int callingUid = Process.myUid();
+// StatsdStatsLog.write(
+// StatsdStatsLog.APP_BREADCRUMB_REPORTED,
+// callingUid,
+// label,
+// StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__STOP);
+ return true;
+ }
+
+ /**
+ * Logs an event that does not represent a start or stop boundary.
+ *
+ * @param label developer-chosen label.
+ * @return True if the log request was sent to statsd.
+ */
+ public static boolean logEvent(int label) {
+ int callingUid = Process.myUid();
+// StatsdStatsLog.write(
+// StatsdStatsLog.APP_BREADCRUMB_REPORTED,
+// callingUid,
+// label,
+// StatsdStatsLog.APP_BREADCRUMB_REPORTED__STATE__UNSPECIFIED);
+ return true;
+ }
+
+ /**
+ * Logs an event for binary push for module updates.
+ *
+ * @param trainName name of install train.
+ * @param trainVersionCode version code of the train.
+ * @param options optional flags about this install.
+ * The last 3 bits indicate options:
+ * 0x01: FLAG_REQUIRE_STAGING
+ * 0x02: FLAG_ROLLBACK_ENABLED
+ * 0x04: FLAG_REQUIRE_LOW_LATENCY_MONITOR
+ * @param state current install state. Defined as State enums in
+ * BinaryPushStateChanged atom in
+ * frameworks/proto_logging/stats/atoms.proto
+ * @param experimentIds experiment ids.
+ * @return True if the log request was sent to statsd.
+ */
+ @RequiresPermission(allOf = {DUMP, PACKAGE_USAGE_STATS})
+ public static boolean logBinaryPushStateChanged(@NonNull String trainName,
+ long trainVersionCode, int options, int state,
+ @NonNull long[] experimentIds) {
+ ProtoOutputStream proto = new ProtoOutputStream();
+ for (long id : experimentIds) {
+ proto.write(
+ ProtoOutputStream.FIELD_TYPE_INT64
+ | ProtoOutputStream.FIELD_COUNT_REPEATED
+ | EXPERIMENT_IDS_FIELD_ID,
+ id);
+ }
+// StatsdStatsLog.write(StatsdStatsLog.BINARY_PUSH_STATE_CHANGED,
+// trainName,
+// trainVersionCode,
+// (options & IStatsd.FLAG_REQUIRE_STAGING) > 0,
+// (options & IStatsd.FLAG_ROLLBACK_ENABLED) > 0,
+// (options & IStatsd.FLAG_REQUIRE_LOW_LATENCY_MONITOR) > 0,
+// state,
+// proto.getBytes(),
+// 0,
+// 0,
+// false);
+ return true;
+ }
+
+ /**
+ * Write an event to stats log using the raw format.
+ *
+ * @param buffer The encoded buffer of data to write.
+ * @param size The number of bytes from the buffer to write.
+ * @hide
+ * @deprecated Use {@link write(final StatsEvent statsEvent)} instead.
+ *
+ */
+ @Deprecated
+ @SystemApi
+ public static void writeRaw(@NonNull byte[] buffer, int size) {
+ writeImpl(buffer, size, 0);
+ }
+
+ /**
+ * Write an event to stats log using the raw format.
+ *
+ * @param buffer The encoded buffer of data to write.
+ * @param size The number of bytes from the buffer to write.
+ * @param atomId The id of the atom to which the event belongs.
+ */
+// private static native void writeImpl(@NonNull byte[] buffer, int size, int atomId);
+ private static void writeImpl(@NonNull byte[] buffer, int size, int atomId) {
+ // no-op for now
+ }
+
+ /**
+ * Write an event to stats log using the raw format encapsulated in StatsEvent.
+ * After writing to stats log, release() is called on the StatsEvent object.
+ * No further action should be taken on the StatsEvent object following this call.
+ *
+ * @param statsEvent The StatsEvent object containing the encoded buffer of data to write.
+ * @hide
+ */
+ @SystemApi
+ public static void write(@NonNull final StatsEvent statsEvent) {
+ writeImpl(statsEvent.getBytes(), statsEvent.getNumBytes(), statsEvent.getAtomId());
+ statsEvent.release();
+ }
+}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/android/compat/Compatibility.java b/ravenwood/runtime-helper-src/libcore-fake/android/compat/Compatibility.java
new file mode 100644
index 000000000000..c7376842d8f3
--- /dev/null
+++ b/ravenwood/runtime-helper-src/libcore-fake/android/compat/Compatibility.java
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.compat;
+
+// [Ravenwood] Copied from libcore, with "RAVENWOOD-CHANGE"
+
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
+import android.annotation.SystemApi;
+import android.compat.annotation.ChangeId;
+
+import libcore.api.IntraCoreApi;
+import libcore.util.NonNull;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Internal APIs for logging and gating compatibility changes.
+ *
+ * @see ChangeId
+ *
+ * @hide
+ */
+@SystemApi(client = MODULE_LIBRARIES)
+@IntraCoreApi
+public final class Compatibility {
+
+ private Compatibility() {}
+
+ /**
+ * Reports that a compatibility change is affecting the current process now.
+ *
+ * <p>Calls to this method from a non-app process are ignored. This allows code implementing
+ * APIs that are used by apps and by other code (e.g. the system server) to report changes
+ * regardless of the process it's running in. When called in a non-app process, this method is
+ * a no-op.
+ *
+ * <p>Note: for changes that are gated using {@link #isChangeEnabled(long)}, you do not need to
+ * call this API directly. The change will be reported for you in the case that
+ * {@link #isChangeEnabled(long)} returns {@code true}.
+ *
+ * @param changeId The ID of the compatibility change taking effect.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @IntraCoreApi
+ public static void reportUnconditionalChange(@ChangeId long changeId) {
+ sCallbacks.onChangeReported(changeId);
+ }
+
+ /**
+ * Query if a given compatibility change is enabled for the current process. This method should
+ * only be called by code running inside a process of the affected app.
+ *
+ * <p>If this method returns {@code true}, the calling code should implement the compatibility
+ * change, resulting in differing behaviour compared to earlier releases. If this method returns
+ * {@code false}, the calling code should behave as it did in earlier releases.
+ *
+ * <p>When this method returns {@code true}, it will also report the change as
+ * {@link #reportUnconditionalChange(long)} would, so there is no need to call that method
+ * directly.
+ *
+ * @param changeId The ID of the compatibility change in question.
+ * @return {@code true} if the change is enabled for the current app.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @IntraCoreApi
+ public static boolean isChangeEnabled(@ChangeId long changeId) {
+ return sCallbacks.isChangeEnabled(changeId);
+ }
+
+ private static final BehaviorChangeDelegate DEFAULT_CALLBACKS = new BehaviorChangeDelegate(){};
+
+ private volatile static BehaviorChangeDelegate sCallbacks = DEFAULT_CALLBACKS;
+
+ /**
+ * Sets the behavior change delegate.
+ *
+ * All changes reported via the {@link Compatibility} class will be forwarded to this class.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static void setBehaviorChangeDelegate(BehaviorChangeDelegate callbacks) {
+ sCallbacks = Objects.requireNonNull(callbacks);
+ }
+
+ /**
+ * Removes a behavior change delegate previously set via {@link #setBehaviorChangeDelegate}.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static void clearBehaviorChangeDelegate() {
+ sCallbacks = DEFAULT_CALLBACKS;
+ }
+
+ /**
+ * Return the behavior change delegate
+ *
+ * @hide
+ */
+ // VisibleForTesting
+ @NonNull
+ public static BehaviorChangeDelegate getBehaviorChangeDelegate() {
+ return sCallbacks;
+ }
+
+ /**
+ * For use by tests only. Causes values from {@code overrides} to be returned instead of the
+ * real value.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static void setOverrides(ChangeConfig overrides) {
+ // Setting overrides twice in a row does not need to be supported because
+ // this method is only for enabling/disabling changes for the duration of
+ // a single test.
+ // In production, the app is restarted when changes get enabled or disabled,
+ // and the ChangeConfig is then set exactly once on that app process.
+ if (sCallbacks instanceof OverrideCallbacks) {
+ throw new IllegalStateException("setOverrides has already been called!");
+ }
+ sCallbacks = new OverrideCallbacks(sCallbacks, overrides);
+ }
+
+ /**
+ * For use by tests only. Removes overrides set by {@link #setOverrides}.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public static void clearOverrides() {
+ if (!(sCallbacks instanceof OverrideCallbacks)) {
+ throw new IllegalStateException("No overrides set");
+ }
+ sCallbacks = ((OverrideCallbacks) sCallbacks).delegate;
+ }
+
+ /**
+ * Base class for compatibility API implementations. The default implementation logs a warning
+ * to logcat.
+ *
+ * This is provided as a class rather than an interface to allow new methods to be added without
+ * breaking @SystemApi binary compatibility.
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ public interface BehaviorChangeDelegate {
+ /**
+ * Called when a change is reported via {@link Compatibility#reportUnconditionalChange}
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ default void onChangeReported(long changeId) {
+ // Do not use String.format here (b/160912695)
+
+ // RAVENWOOD-CHANGE
+ System.out.println("No Compatibility callbacks set! Reporting change " + changeId);
+ }
+
+ /**
+ * Called when a change is queried via {@link Compatibility#isChangeEnabled}
+ *
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ default boolean isChangeEnabled(long changeId) {
+ // Do not use String.format here (b/160912695)
+ // TODO(b/289900411): Rate limit this log if it's necessary in the release build.
+ // System.logW("No Compatibility callbacks set! Querying change " + changeId);
+ return true;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @IntraCoreApi
+ public static final class ChangeConfig {
+ private final Set<Long> enabled;
+ private final Set<Long> disabled;
+
+ /**
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @IntraCoreApi
+ public ChangeConfig(@NonNull Set<@NonNull Long> enabled, @NonNull Set<@NonNull Long> disabled) {
+ this.enabled = Objects.requireNonNull(enabled);
+ this.disabled = Objects.requireNonNull(disabled);
+ if (enabled.contains(null)) {
+ throw new NullPointerException();
+ }
+ if (disabled.contains(null)) {
+ throw new NullPointerException();
+ }
+ Set<Long> intersection = new HashSet<>(enabled);
+ intersection.retainAll(disabled);
+ if (!intersection.isEmpty()) {
+ throw new IllegalArgumentException("Cannot have changes " + intersection
+ + " enabled and disabled!");
+ }
+ }
+
+ /**
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @IntraCoreApi
+ public boolean isEmpty() {
+ return enabled.isEmpty() && disabled.isEmpty();
+ }
+
+ private static long[] toLongArray(Set<Long> values) {
+ long[] result = new long[values.size()];
+ int idx = 0;
+ for (Long value: values) {
+ result[idx++] = value;
+ }
+ return result;
+ }
+
+ /**
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @IntraCoreApi
+ public @NonNull long[] getEnabledChangesArray() {
+ return toLongArray(enabled);
+ }
+
+
+ /**
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @IntraCoreApi
+ public @NonNull long[] getDisabledChangesArray() {
+ return toLongArray(disabled);
+ }
+
+
+ /**
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @IntraCoreApi
+ public @NonNull Set<@NonNull Long> getEnabledSet() {
+ return Collections.unmodifiableSet(enabled);
+ }
+
+
+ /**
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @IntraCoreApi
+ public @NonNull Set<@NonNull Long> getDisabledSet() {
+ return Collections.unmodifiableSet(disabled);
+ }
+
+
+ /**
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @IntraCoreApi
+ public boolean isForceEnabled(long changeId) {
+ return enabled.contains(changeId);
+ }
+
+
+ /**
+ * @hide
+ */
+ @SystemApi(client = MODULE_LIBRARIES)
+ @IntraCoreApi
+ public boolean isForceDisabled(long changeId) {
+ return disabled.contains(changeId);
+ }
+
+
+ /**
+ * @hide
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ChangeConfig)) {
+ return false;
+ }
+ ChangeConfig that = (ChangeConfig) o;
+ return enabled.equals(that.enabled) &&
+ disabled.equals(that.disabled);
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hash(enabled, disabled);
+ }
+
+
+ /**
+ * @hide
+ */
+ @Override
+ public String toString() {
+ return "ChangeConfig{enabled=" + enabled + ", disabled=" + disabled + '}';
+ }
+ }
+
+ private static class OverrideCallbacks implements BehaviorChangeDelegate {
+ private final BehaviorChangeDelegate delegate;
+ private final ChangeConfig changeConfig;
+
+ private OverrideCallbacks(BehaviorChangeDelegate delegate, ChangeConfig changeConfig) {
+ this.delegate = Objects.requireNonNull(delegate);
+ this.changeConfig = Objects.requireNonNull(changeConfig);
+ }
+ @Override
+ public boolean isChangeEnabled(long changeId) {
+ if (changeConfig.isForceEnabled(changeId)) {
+ return true;
+ }
+ if (changeConfig.isForceDisabled(changeId)) {
+ return false;
+ }
+ return delegate.isChangeEnabled(changeId);
+ }
+ }
+}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/api/CorePlatformApi.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/api/CorePlatformApi.java
new file mode 100644
index 000000000000..00730efc64b3
--- /dev/null
+++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/api/CorePlatformApi.java
@@ -0,0 +1,69 @@
+
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.api;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates an API is part of a contract provided by the "core" set of
+ * libraries to select parts of the Android software stack.
+ *
+ * <p>This annotation should only appear on either (a) classes that are hidden by <pre>@hide</pre>
+ * javadoc tags or equivalent annotations, or (b) members of such classes. It is for use with
+ * metalava's {@code --show-single-annotation} option and so must be applied at the class level and
+ * applied again each member that is to be made part of the API. Members that are not part of the
+ * API do not have to be explicitly hidden.
+ *
+ * @hide
+ */
+@IntraCoreApi
+@Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE})
+@Retention(RetentionPolicy.SOURCE)
+public @interface CorePlatformApi {
+
+ /** Enumeration of the possible statuses of the API in the core/platform API surface. */
+ @IntraCoreApi
+ enum Status {
+
+ /**
+ * This API is considered stable, and so present in both the stable and legacy version of
+ * the API surface.
+ */
+ @IntraCoreApi
+ STABLE,
+
+ /**
+ * This API is not (yet) considered stable, and so only present in the legacy version of
+ * the API surface.
+ */
+ @IntraCoreApi
+ LEGACY_ONLY
+ }
+
+ /** The status of the API in the core/platform API surface. */
+ @IntraCoreApi
+ Status status() default Status.LEGACY_ONLY;
+}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/api/Hide.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/api/Hide.java
new file mode 100644
index 000000000000..f87ff11df0ab
--- /dev/null
+++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/api/Hide.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.api;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates that an API is hidden by default, in a similar fashion to the
+ * <pre>@hide</pre> javadoc tag.
+ *
+ * <p>Note that, in order for this to work, metalava has to be invoked with
+ * the flag {@code --hide-annotation libcore.api.Hide}.
+ *
+ * <p>This annotation should be used in {@code .annotated.java} stub files which
+ * contain API inclusion information about {@code libcore/ojluni} classes, to
+ * avoid patching the source files with <pre>@hide</pre> javadoc tags. All
+ * build targets which consume these stub files should also apply the above
+ * metalava flag.
+ *
+ * @hide
+ */
+@Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE})
+@Retention(RetentionPolicy.SOURCE)
+public @interface Hide {
+}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/api/IntraCoreApi.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/api/IntraCoreApi.java
new file mode 100644
index 000000000000..87cfcff2474b
--- /dev/null
+++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/api/IntraCoreApi.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package libcore.api;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Indicates an API is part of a contract within the "core" set of libraries, some of which may
+ * be mmodules.
+ *
+ * <p>This annotation should only appear on either (a) classes that are hidden by <pre>@hide</pre>
+ * javadoc tags or equivalent annotations, or (b) members of such classes. It is for use with
+ * metalava's {@code --show-single-annotation} option and so must be applied at the class level and
+ * applied again each member that is to be made part of the API. Members that are not part of the
+ * API do not have to be explicitly hidden.
+ *
+ * @hide
+ */
+@IntraCoreApi // @IntraCoreApi is itself part of the intra-core API
+@Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE})
+@Retention(RetentionPolicy.SOURCE)
+public @interface IntraCoreApi {
+}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NonNull.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NonNull.java
new file mode 100644
index 000000000000..db3cd8ed712f
--- /dev/null
+++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/NonNull.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package libcore.util;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE_USE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that a type use can never be null.
+ * <p>
+ * This is a marker annotation and it has no specific attributes.
+ * @hide
+ */
+@Documented
+@Retention(SOURCE)
+@Target({FIELD, METHOD, PARAMETER, TYPE_USE})
+@libcore.api.IntraCoreApi
+public @interface NonNull {
+ /**
+ * Min Android API level (inclusive) to which this annotation is applied.
+ */
+ int from() default Integer.MIN_VALUE;
+
+ /**
+ * Max Android API level to which this annotation is applied.
+ */
+ int to() default Integer.MAX_VALUE;
+}
diff --git a/ravenwood/runtime-helper-src/libcore-fake/libcore/util/Nullable.java b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/Nullable.java
new file mode 100644
index 000000000000..3371978b0568
--- /dev/null
+++ b/ravenwood/runtime-helper-src/libcore-fake/libcore/util/Nullable.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package libcore.util;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE_USE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that a type use can be a null.
+ * <p>
+ * This is a marker annotation and it has no specific attributes.
+ * @hide
+ */
+@Documented
+@Retention(SOURCE)
+@Target({FIELD, METHOD, PARAMETER, TYPE_USE})
+@libcore.api.IntraCoreApi
+public @interface Nullable {
+ /**
+ * Min Android API level (inclusive) to which this annotation is applied.
+ */
+ int from() default Integer.MIN_VALUE;
+
+ /**
+ * Max Android API level to which this annotation is applied.
+ */
+ int to() default Integer.MAX_VALUE;
+}
diff --git a/ravenwood/texts/ravenwood-framework-policies.txt b/ravenwood/texts/ravenwood-framework-policies.txt
index 3649f0e78f09..b64944ee39ed 100644
--- a/ravenwood/texts/ravenwood-framework-policies.txt
+++ b/ravenwood/texts/ravenwood-framework-policies.txt
@@ -5,6 +5,10 @@
rename com/.*/nano/ devicenano/
rename android/.*/nano/ devicenano/
+
+# StatsD autogenerated classes. Maybe add a heuristic?
+class com.android.internal.util.FrameworkStatsLog keepclass
+
# Exported to Mainline modules; cannot use annotations
class com.android.internal.util.FastXmlSerializer keepclass
class com.android.internal.util.FileRotator keepclass
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
index a77ba624a68f..ce1a292fb069 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationController.java
@@ -64,6 +64,7 @@ import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.accessibility.AccessibilityTraceManager;
import com.android.server.accessibility.Flags;
+import com.android.server.input.InputManagerInternal;
import com.android.server.wm.WindowManagerInternal;
import java.util.ArrayList;
@@ -396,7 +397,7 @@ public class FullScreenMagnificationController implements
mCurrentMagnificationSpec.offsetX, mCurrentMagnificationSpec.offsetY)) {
sendSpecToAnimation(mCurrentMagnificationSpec, null);
}
- onMagnificationChangedLocked();
+ onMagnificationChangedLocked(/* isScaleTransient= */ false);
}
magnified.recycle();
}
@@ -474,8 +475,16 @@ public class FullScreenMagnificationController implements
return mIdOfLastServiceToMagnify;
}
+ /**
+ * This is invoked whenever magnification change happens.
+ *
+ * @param isScaleTransient represents that if the scale is being changed and the changed
+ * value may be short lived and be updated again soon.
+ * Calling the method usually notifies input manager to update the
+ * cursor scale, but setting this value {@code true} prevents it.
+ */
@GuardedBy("mLock")
- void onMagnificationChangedLocked() {
+ void onMagnificationChangedLocked(boolean isScaleTransient) {
final float scale = getScale();
final float centerX = getCenterX();
final float centerY = getCenterY();
@@ -498,6 +507,10 @@ public class FullScreenMagnificationController implements
} else {
hideThumbnail();
}
+
+ if (!isScaleTransient) {
+ notifyScaleForInput(mDisplayId, scale);
+ }
}
@GuardedBy("mLock")
@@ -611,8 +624,9 @@ public class FullScreenMagnificationController implements
* Directly Zooms out the scale to 1f with animating the transition. This method is
* triggered only by service automatically, such as when user context changed.
*/
+ @GuardedBy("mLock")
void zoomOutFromService() {
- setScaleAndCenter(1.0f, Float.NaN, Float.NaN,
+ setScaleAndCenter(1.0f, Float.NaN, Float.NaN, /* isScaleTransient= */ false,
transformToStubCallback(true),
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
mZoomedOutFromService = true;
@@ -640,7 +654,7 @@ public class FullScreenMagnificationController implements
setActivated(false);
if (changed) {
spec.clear();
- onMagnificationChangedLocked();
+ onMagnificationChangedLocked(/* isScaleTransient= */ false);
}
mIdOfLastServiceToMagnify = INVALID_SERVICE_ID;
sendSpecToAnimation(spec, animationCallback);
@@ -651,7 +665,7 @@ public class FullScreenMagnificationController implements
}
@GuardedBy("mLock")
- boolean setScale(float scale, float pivotX, float pivotY,
+ boolean setScale(float scale, float pivotX, float pivotY, boolean isScaleTransient,
boolean animate, int id) {
if (!mRegistered) {
return false;
@@ -674,12 +688,14 @@ public class FullScreenMagnificationController implements
final float centerX = normPivotX + offsetX;
final float centerY = normPivotY + offsetY;
mIdOfLastServiceToMagnify = id;
- return setScaleAndCenter(scale, centerX, centerY, transformToStubCallback(animate), id);
+ return setScaleAndCenter(scale, centerX, centerY, isScaleTransient,
+ transformToStubCallback(animate), id);
}
@GuardedBy("mLock")
boolean setScaleAndCenter(float scale, float centerX, float centerY,
- MagnificationAnimationCallback animationCallback, int id) {
+ boolean isScaleTransient, MagnificationAnimationCallback animationCallback,
+ int id) {
if (!mRegistered) {
return false;
}
@@ -696,7 +712,7 @@ public class FullScreenMagnificationController implements
+ animationCallback + ", id = " + id + ")");
}
boolean changed = setActivated(true);
- changed |= updateMagnificationSpecLocked(scale, centerX, centerY);
+ changed |= updateMagnificationSpecLocked(scale, centerX, centerY, isScaleTransient);
sendSpecToAnimation(mCurrentMagnificationSpec, animationCallback);
if (isActivated() && (id != INVALID_SERVICE_ID)) {
mIdOfLastServiceToMagnify = id;
@@ -773,7 +789,9 @@ public class FullScreenMagnificationController implements
* @return {@code true} if the magnification spec changed or {@code false}
* otherwise
*/
- boolean updateMagnificationSpecLocked(float scale, float centerX, float centerY) {
+ @GuardedBy("mLock")
+ boolean updateMagnificationSpecLocked(float scale, float centerX, float centerY,
+ boolean isScaleTransient) {
// Handle defaults.
if (Float.isNaN(centerX)) {
centerX = getCenterX();
@@ -801,7 +819,7 @@ public class FullScreenMagnificationController implements
changed |= updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY);
if (changed) {
- onMagnificationChangedLocked();
+ onMagnificationChangedLocked(isScaleTransient);
}
return changed;
@@ -816,7 +834,7 @@ public class FullScreenMagnificationController implements
final float nonNormOffsetX = mCurrentMagnificationSpec.offsetX - offsetX;
final float nonNormOffsetY = mCurrentMagnificationSpec.offsetY - offsetY;
if (updateCurrentSpecWithOffsetsLocked(nonNormOffsetX, nonNormOffsetY)) {
- onMagnificationChangedLocked();
+ onMagnificationChangedLocked(/* isScaleTransient= */ false);
}
if (id != INVALID_SERVICE_ID) {
mIdOfLastServiceToMagnify = id;
@@ -861,7 +879,7 @@ public class FullScreenMagnificationController implements
}
synchronized (mLock) {
mCurrentMagnificationSpec.setTo(lastSpecSent);
- onMagnificationChangedLocked();
+ onMagnificationChangedLocked(/* isScaleTransient= */ false);
}
}
});
@@ -955,6 +973,7 @@ public class FullScreenMagnificationController implements
context,
traceManager,
LocalServices.getService(WindowManagerInternal.class),
+ LocalServices.getService(InputManagerInternal.class),
new Handler(context.getMainLooper()),
context.getResources().getInteger(R.integer.config_longAnimTime)),
lock,
@@ -1464,20 +1483,24 @@ public class FullScreenMagnificationController implements
* @param scale the target scale, must be >= 1
* @param pivotX the screen-relative X coordinate around which to scale
* @param pivotY the screen-relative Y coordinate around which to scale
+ * @param isScaleTransient {@code true} if the scale is for a short time and potentially changed
+ * soon. {@code false} otherwise.
* @param animate {@code true} to animate the transition, {@code false}
* to transition immediately
* @param id the ID of the service requesting the change
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
+ @SuppressWarnings("GuardedBy")
+ // errorprone cannot recognize an inner class guarded by an outer class member.
public boolean setScale(int displayId, float scale, float pivotX, float pivotY,
- boolean animate, int id) {
+ boolean isScaleTransient, boolean animate, int id) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
if (display == null) {
return false;
}
- return display.setScale(scale, pivotX, pivotY, animate, id);
+ return display.setScale(scale, pivotX, pivotY, isScaleTransient, animate, id);
}
}
@@ -1496,6 +1519,8 @@ public class FullScreenMagnificationController implements
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
+ @SuppressWarnings("GuardedBy")
+ // errorprone cannot recognize an inner class guarded by an outer class member.
public boolean setCenter(int displayId, float centerX, float centerY, boolean animate, int id) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
@@ -1503,7 +1528,7 @@ public class FullScreenMagnificationController implements
return false;
}
return display.setScaleAndCenter(Float.NaN, centerX, centerY,
- animate ? STUB_ANIMATION_CALLBACK : null, id);
+ /* isScaleTransient= */ false, animate ? STUB_ANIMATION_CALLBACK : null, id);
}
}
@@ -1526,7 +1551,32 @@ public class FullScreenMagnificationController implements
*/
public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY,
boolean animate, int id) {
- return setScaleAndCenter(displayId, scale, centerX, centerY,
+ return setScaleAndCenter(displayId, scale, centerX, centerY, /* isScaleTransient= */ false,
+ transformToStubCallback(animate), id);
+ }
+
+ /**
+ * Sets the scale and center of the magnified region, optionally
+ * animating the transition. If animation is disabled, the transition
+ * is immediate.
+ *
+ * @param displayId The logical display id.
+ * @param scale the target scale, or {@link Float#NaN} to leave unchanged
+ * @param centerX the screen-relative X coordinate around which to
+ * center and scale, or {@link Float#NaN} to leave unchanged
+ * @param centerY the screen-relative Y coordinate around which to
+ * center and scale, or {@link Float#NaN} to leave unchanged
+ * @param isScaleTransient {@code true} if the scale is for a short time and potentially changed
+ * soon. {@code false} otherwise.
+ * @param animate {@code true} to animate the transition, {@code false}
+ * to transition immediately
+ * @param id the ID of the service requesting the change
+ * @return {@code true} if the magnification spec changed, {@code false} if
+ * the spec did not change
+ */
+ public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY,
+ boolean isScaleTransient, boolean animate, int id) {
+ return setScaleAndCenter(displayId, scale, centerX, centerY, isScaleTransient,
transformToStubCallback(animate), id);
}
@@ -1541,20 +1591,25 @@ public class FullScreenMagnificationController implements
* center and scale, or {@link Float#NaN} to leave unchanged
* @param centerY the screen-relative Y coordinate around which to
* center and scale, or {@link Float#NaN} to leave unchanged
+ * @param isScaleTransient {@code true} if the scale is for a short time and potentially changed
+ * soon. {@code false} otherwise.
* @param animationCallback Called when the animation result is valid.
* {@code null} to transition immediately
* @param id the ID of the service requesting the change
* @return {@code true} if the magnification spec changed, {@code false} if
* the spec did not change
*/
+ @SuppressWarnings("GuardedBy")
+ // errorprone cannot recognize an inner class guarded by an outer class member.
public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY,
- MagnificationAnimationCallback animationCallback, int id) {
+ boolean isScaleTransient, MagnificationAnimationCallback animationCallback, int id) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
if (display == null) {
return false;
}
- return display.setScaleAndCenter(scale, centerX, centerY, animationCallback, id);
+ return display.setScaleAndCenter(scale, centerX, centerY, isScaleTransient,
+ animationCallback, id);
}
}
@@ -1569,6 +1624,8 @@ public class FullScreenMagnificationController implements
* screen pixels.
* @param id the ID of the service requesting the change
*/
+ @SuppressWarnings("GuardedBy")
+ // errorprone cannot recognize an inner class guarded by an outer class member.
public void offsetMagnifiedRegion(int displayId, float offsetX, float offsetY, int id) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
@@ -1640,6 +1697,8 @@ public class FullScreenMagnificationController implements
*/
public void persistScale(int displayId) {
final float scale = getScale(displayId);
+ notifyScaleForInput(displayId, scale);
+
if (scale < MagnificationConstants.PERSISTED_SCALE_MIN_VALUE) {
return;
}
@@ -1665,6 +1724,8 @@ public class FullScreenMagnificationController implements
*
* @param displayId The logical display id.
*/
+ @SuppressWarnings("GuardedBy")
+ // errorprone cannot recognize an inner class guarded by an outer class member.
private void zoomOutFromService(int displayId) {
synchronized (mLock) {
final DisplayMagnification display = mDisplays.get(displayId);
@@ -1691,6 +1752,20 @@ public class FullScreenMagnificationController implements
}
/**
+ * Notifies input manager that magnification scale changed non-transiently
+ * so that pointer cursor is scaled as well.
+ *
+ * @param displayId The logical display id.
+ * @param scale The new scale factor.
+ */
+ public void notifyScaleForInput(int displayId, float scale) {
+ if (Flags.magnificationEnlargePointer()) {
+ mControllerCtx.getInputManager()
+ .setAccessibilityPointerIconScaleFactor(displayId, scale);
+ }
+ }
+
+ /**
* Resets all displays' magnification if last magnifying service is disabled.
*
* @param connectionId
@@ -2166,6 +2241,7 @@ public class FullScreenMagnificationController implements
private final Context mContext;
private final AccessibilityTraceManager mTrace;
private final WindowManagerInternal mWindowManager;
+ private final InputManagerInternal mInputManager;
private final Handler mHandler;
private final Long mAnimationDuration;
@@ -2175,11 +2251,13 @@ public class FullScreenMagnificationController implements
public ControllerContext(@NonNull Context context,
@NonNull AccessibilityTraceManager traceManager,
@NonNull WindowManagerInternal windowManager,
+ @NonNull InputManagerInternal inputManager,
@NonNull Handler handler,
long animationDuration) {
mContext = context;
mTrace = traceManager;
mWindowManager = windowManager;
+ mInputManager = inputManager;
mHandler = handler;
mAnimationDuration = animationDuration;
}
@@ -2209,6 +2287,14 @@ public class FullScreenMagnificationController implements
}
/**
+ * @return InputManagerInternal
+ */
+ @NonNull
+ public InputManagerInternal getInputManager() {
+ return mInputManager;
+ }
+
+ /**
* @return Handler for main looper
*/
@NonNull
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
index 963334b07ea6..c6a966f47952 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java
@@ -617,7 +617,8 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
}
if (DEBUG_PANNING_SCALING) Slog.i(mLogTag, "Scaled content to: " + scale + "x");
- mFullScreenMagnificationController.setScale(mDisplayId, scale, pivotX, pivotY, false,
+ mFullScreenMagnificationController.setScale(mDisplayId, scale, pivotX, pivotY,
+ /* isScaleTransient= */ true, /* animate= */ false,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
checkShouldDetectPassPersistedScale();
@@ -1974,6 +1975,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH
/* scale= */ scale,
/* centerX= */ mPivotEdge.x,
/* centerY= */ mPivotEdge.y,
+ /* isScaleTransient= */ true,
/* animate= */ true,
/* id= */ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
if (scale == 1.0f) {
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
index 1489d16c3764..d40e7476f7ec 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
@@ -176,7 +176,8 @@ public class MagnificationController implements MagnificationConnectionManager.C
public void onPerformScaleAction(int displayId, float scale, boolean updatePersistence) {
if (getFullScreenMagnificationController().isActivated(displayId)) {
getFullScreenMagnificationController().setScaleAndCenter(displayId, scale,
- Float.NaN, Float.NaN, false, MAGNIFICATION_GESTURE_HANDLER_ID);
+ Float.NaN, Float.NaN, /* isScaleTransient= */ !updatePersistence, false,
+ MAGNIFICATION_GESTURE_HANDLER_ID);
if (updatePersistence) {
getFullScreenMagnificationController().persistScale(displayId);
}
@@ -371,7 +372,7 @@ public class MagnificationController implements MagnificationConnectionManager.C
}
screenMagnificationController.setScaleAndCenter(displayId, targetScale,
magnificationCenter.x, magnificationCenter.y,
- magnificationAnimationCallback, id);
+ /* isScaleTransient= */ false, magnificationAnimationCallback, id);
} else {
if (screenMagnificationController.isRegistered(displayId)) {
screenMagnificationController.reset(displayId, false);
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 95281c81fc33..591107010431 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -715,11 +715,17 @@ public class CompanionDeviceManagerService extends SystemService {
@Override
public byte[] getBackupPayload(int userId) {
+ if (getCallingUid() != SYSTEM_UID) {
+ throw new SecurityException("Caller must be system");
+ }
return mBackupRestoreProcessor.getBackupPayload(userId);
}
@Override
public void applyRestoredPayload(byte[] payload, int userId) {
+ if (getCallingUid() != SYSTEM_UID) {
+ throw new SecurityException("Caller must be system");
+ }
mBackupRestoreProcessor.applyRestoredPayload(payload, userId);
}
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 39ac5150c7f1..363807d2aa8c 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -68,6 +68,7 @@ import android.telephony.CellSignalStrengthWcdma;
import android.telephony.DisconnectCause;
import android.telephony.LinkCapacityEstimate;
import android.telephony.LocationAccessPolicy;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneCapability;
import android.telephony.PhoneStateListener;
import android.telephony.PhysicalChannelConfig;
@@ -90,6 +91,7 @@ import android.telephony.ims.MediaQualityStatus;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.IntArray;
import android.util.LocalLog;
import android.util.Pair;
import android.util.SparseArray;
@@ -429,6 +431,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
private boolean[] mCarrierRoamingNtnMode = null;
private boolean[] mCarrierRoamingNtnEligible = null;
+ private List<IntArray> mCarrierRoamingNtnAvailableServices;
+
/**
* Per-phone map of precise data connection state. The key of the map is the pair of transport
* type and APN setting. This is the cache to prevent redundant callbacks to the listeners.
@@ -741,6 +745,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
cutListToSize(mCarrierServiceStates, mNumPhones);
cutListToSize(mCallStateLists, mNumPhones);
cutListToSize(mMediaQualityStatus, mNumPhones);
+ cutListToSize(mCarrierRoamingNtnAvailableServices, mNumPhones);
return;
}
@@ -789,6 +794,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mSCBMDuration[i] = 0;
mCarrierRoamingNtnMode[i] = false;
mCarrierRoamingNtnEligible[i] = false;
+ mCarrierRoamingNtnAvailableServices.add(i, new IntArray());
}
}
}
@@ -864,6 +870,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mSCBMDuration = new long[numPhones];
mCarrierRoamingNtnMode = new boolean[numPhones];
mCarrierRoamingNtnEligible = new boolean[numPhones];
+ mCarrierRoamingNtnAvailableServices = new ArrayList<>();
for (int i = 0; i < numPhones; i++) {
mCallState[i] = TelephonyManager.CALL_STATE_IDLE;
@@ -909,6 +916,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
mSCBMDuration[i] = 0;
mCarrierRoamingNtnMode[i] = false;
mCarrierRoamingNtnEligible[i] = false;
+ mCarrierRoamingNtnAvailableServices.add(i, new IntArray());
}
mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -1533,6 +1541,15 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
remove(r.binder);
}
}
+ if (events.contains(
+ TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_AVAILABLE_SERVICES_CHANGED)) {
+ try {
+ r.callback.onCarrierRoamingNtnAvailableServicesChanged(
+ mCarrierRoamingNtnAvailableServices.get(r.phoneId).toArray());
+ } catch (RemoteException ex) {
+ remove(r.binder);
+ }
+ }
}
}
}
@@ -3642,6 +3659,47 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
+ /**
+ * Notify external listeners that carrier roaming non-terrestrial available services changed.
+ * @param availableServices The list of the supported services.
+ */
+ public void notifyCarrierRoamingNtnAvailableServicesChanged(
+ int subId, @NetworkRegistrationInfo.ServiceType int[] availableServices) {
+ if (!checkNotifyPermission("notifyCarrierRoamingNtnEligibleStateChanged")) {
+ log("notifyCarrierRoamingNtnAvailableServicesChanged: caller does not have required "
+ + "permissions.");
+ return;
+ }
+
+ if (VDBG) {
+ log("notifyCarrierRoamingNtnAvailableServicesChanged: "
+ + "availableServices=" + Arrays.toString(availableServices));
+ }
+
+ synchronized (mRecords) {
+ int phoneId = getPhoneIdFromSubId(subId);
+ if (!validatePhoneId(phoneId)) {
+ loge("Invalid phone ID " + phoneId + " for " + subId);
+ return;
+ }
+ IntArray availableServicesIntArray = new IntArray(availableServices.length);
+ availableServicesIntArray.addAll(availableServices);
+ mCarrierRoamingNtnAvailableServices.set(phoneId, availableServicesIntArray);
+ for (Record r : mRecords) {
+ if (r.matchTelephonyCallbackEvent(
+ TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_AVAILABLE_SERVICES_CHANGED)
+ && idMatch(r, subId, phoneId)) {
+ try {
+ r.callback.onCarrierRoamingNtnAvailableServicesChanged(availableServices);
+ } catch (RemoteException ex) {
+ mRemoveList.add(r.binder);
+ }
+ }
+ }
+ handleRemoveListLocked();
+ }
+ }
+
@NeverCompile // Avoid size overhead of debugging code.
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
@@ -3706,6 +3764,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
Pair<String, Integer> carrierServiceState = mCarrierServiceStates.get(i);
pw.println("mCarrierServiceState=<package=" + pii(carrierServiceState.first)
+ ", uid=" + carrierServiceState.second + ">");
+ pw.println("mCarrierRoamingNtnAvailableServices="
+ + mCarrierRoamingNtnAvailableServices.get(i));
pw.decreaseIndent();
}
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 947f6b73d32a..51c768b80eff 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -75,6 +75,7 @@ import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
import android.util.LocalLog;
import android.util.Log;
import android.util.Slog;
@@ -82,7 +83,7 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
-import com.android.internal.util.IndentingPrintWriter;
+import com.android.net.module.util.BinderUtils;
import com.android.net.module.util.LocationPermissionChecker;
import com.android.net.module.util.PermissionUtils;
import com.android.server.vcn.TelephonySubscriptionTracker;
@@ -448,7 +449,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
final UserManager userManager = mContext.getSystemService(UserManager.class);
- Binder.withCleanCallingIdentity(
+ BinderUtils.withCleanCallingIdentity(
() -> {
if (!Objects.equals(userManager.getMainUser(), userHandle)) {
throw new SecurityException(
@@ -468,7 +469,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
// TODO (b/172619301): Check based on events propagated from CarrierPrivilegesTracker
final SubscriptionManager subMgr = mContext.getSystemService(SubscriptionManager.class);
final List<SubscriptionInfo> subscriptionInfos = new ArrayList<>();
- Binder.withCleanCallingIdentity(
+ BinderUtils.withCleanCallingIdentity(
() -> {
List<SubscriptionInfo> subsInGroup =
subMgr.getSubscriptionsInGroup(subscriptionGroup);
@@ -700,7 +701,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
@GuardedBy("mLock")
private void notifyAllPolicyListenersLocked() {
for (final PolicyListenerBinderDeath policyListener : mRegisteredPolicyListeners.values()) {
- Binder.withCleanCallingIdentity(() -> {
+ BinderUtils.withCleanCallingIdentity(() -> {
try {
policyListener.mListener.onPolicyChanged();
} catch (RemoteException e) {
@@ -715,7 +716,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
@NonNull ParcelUuid subGroup, @VcnStatusCode int statusCode) {
for (final VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
if (isCallbackPermissioned(cbInfo, subGroup)) {
- Binder.withCleanCallingIdentity(() -> {
+ BinderUtils.withCleanCallingIdentity(() -> {
try {
cbInfo.mCallback.onVcnStatusChanged(statusCode);
} catch (RemoteException e) {
@@ -795,7 +796,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
enforceManageTestNetworksForTestMode(config);
enforceCallingUserAndCarrierPrivilege(subscriptionGroup, opPkgName);
- Binder.withCleanCallingIdentity(() -> {
+ BinderUtils.withCleanCallingIdentity(() -> {
synchronized (mLock) {
mConfigs.put(subscriptionGroup, config);
startOrUpdateVcnLocked(subscriptionGroup, config);
@@ -853,7 +854,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
.checkPackage(mDeps.getBinderCallingUid(), opPkgName);
enforceCarrierPrivilegeOrProvisioningPackage(subscriptionGroup, opPkgName);
- Binder.withCleanCallingIdentity(() -> {
+ BinderUtils.withCleanCallingIdentity(() -> {
synchronized (mLock) {
stopAndClearVcnConfigInternalLocked(subscriptionGroup);
writeConfigsToDiskLocked();
@@ -991,7 +992,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
android.Manifest.permission.NETWORK_FACTORY,
android.Manifest.permission.MANAGE_TEST_NETWORKS);
- Binder.withCleanCallingIdentity(() -> {
+ BinderUtils.withCleanCallingIdentity(() -> {
PolicyListenerBinderDeath listenerBinderDeath = new PolicyListenerBinderDeath(listener);
synchronized (mLock) {
@@ -1018,7 +1019,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
android.Manifest.permission.NETWORK_FACTORY,
android.Manifest.permission.MANAGE_TEST_NETWORKS);
- Binder.withCleanCallingIdentity(() -> {
+ BinderUtils.withCleanCallingIdentity(() -> {
synchronized (mLock) {
PolicyListenerBinderDeath listenerBinderDeath =
mRegisteredPolicyListeners.remove(listener.asBinder());
@@ -1082,7 +1083,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
+ " MANAGE_TEST_NETWORKS");
}
- return Binder.withCleanCallingIdentity(() -> {
+ return BinderUtils.withCleanCallingIdentity(() -> {
// Defensive copy in case this call is in-process and the given NetworkCapabilities
// mutates
final NetworkCapabilities ncCopy = new NetworkCapabilities(networkCapabilities);
@@ -1521,7 +1522,7 @@ public class VcnManagementService extends IVcnManagementService.Stub {
// Notify all registered StatusCallbacks for this subGroup
for (VcnStatusCallbackInfo cbInfo : mRegisteredStatusCallbacks.values()) {
if (isCallbackPermissioned(cbInfo, mSubGroup)) {
- Binder.withCleanCallingIdentity(() -> {
+ BinderUtils.withCleanCallingIdentity(() -> {
try {
cbInfo.mCallback.onGatewayConnectionError(
gatewayConnectionName,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 217ef205a3e8..6ba851423219 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -60,6 +60,7 @@ import static android.app.ProcessMemoryState.HOSTING_COMPONENT_TYPE_BACKUP;
import static android.app.ProcessMemoryState.HOSTING_COMPONENT_TYPE_INSTRUMENTATION;
import static android.app.ProcessMemoryState.HOSTING_COMPONENT_TYPE_PERSISTENT;
import static android.app.ProcessMemoryState.HOSTING_COMPONENT_TYPE_SYSTEM;
+import static android.content.Intent.isPreventIntentRedirectEnabled;
import static android.content.pm.ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT;
import static android.content.pm.PackageManager.GET_SHARED_LIBRARY_FILES;
import static android.content.pm.PackageManager.MATCH_ALL;
@@ -130,7 +131,6 @@ import static android.os.Process.setThreadScheduler;
import static android.provider.Settings.Global.ALWAYS_FINISH_ACTIVITIES;
import static android.provider.Settings.Global.DEBUG_APP;
import static android.provider.Settings.Global.WAIT_FOR_DEBUGGER;
-import static android.security.Flags.preventIntentRedirect;
import static android.util.FeatureFlagUtils.SETTINGS_ENABLE_MONITOR_PHANTOM_PROCS;
import static android.view.Display.INVALID_DISPLAY;
@@ -19272,7 +19272,7 @@ public class ActivityManagerService extends IActivityManager.Stub
* @hide
*/
public void addCreatorToken(@Nullable Intent intent, String creatorPackage) {
- if (!preventIntentRedirect()) return;
+ if (!isPreventIntentRedirectEnabled()) return;
if (intent == null || intent.getExtraIntentKeys() == null) return;
for (String key : intent.getExtraIntentKeys()) {
@@ -19283,7 +19283,9 @@ public class ActivityManagerService extends IActivityManager.Stub
+ "} does not correspond to an intent in the extra bundle.");
continue;
}
- Slog.wtf(TAG, "A creator token is added to an intent.");
+ Slog.wtf(TAG,
+ "A creator token is added to an intent. creatorPackage: " + creatorPackage
+ + "; intent: " + intent);
IBinder creatorToken = createIntentCreatorToken(extraIntent, creatorPackage);
if (creatorToken != null) {
extraIntent.setCreatorToken(creatorToken);
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index c47cad955202..28b606c931fa 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -3178,12 +3178,15 @@ public final class BatteryStatsService extends IBatteryStats.Stub
mStats.collectPowerStatsSamples();
}
- BatteryUsageStats batteryUsageStats =
- mBatteryUsageStatsProvider.getBatteryUsageStats(mStats, query);
- if (proto) {
- batteryUsageStats.dumpToProto(fd);
- } else {
- batteryUsageStats.dump(pw, " ");
+ try (BatteryUsageStats batteryUsageStats =
+ mBatteryUsageStatsProvider.getBatteryUsageStats(mStats, query)) {
+ if (proto) {
+ batteryUsageStats.dumpToProto(fd);
+ } else {
+ batteryUsageStats.dump(pw, " ");
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "Cannot close BatteryUsageStats", e);
}
}
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index ba4b71cd7540..17fcbf47206f 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -22,7 +22,7 @@ import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ANR;
import static com.android.server.am.ActivityManagerService.MY_PID;
import static com.android.server.am.ProcessRecord.TAG;
-import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
+import static com.android.internal.os.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -58,7 +58,7 @@ import com.android.internal.util.FrameworkStatsLog;
import com.android.modules.expresslog.Counter;
import com.android.server.ResourcePressureUtil;
import com.android.server.criticalevents.CriticalEventLog;
-import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot;
+import com.android.internal.os.ProcfsMemoryUtil.MemorySnapshot;
import com.android.server.wm.WindowProcessController;
import java.io.File;
diff --git a/services/core/java/com/android/server/display/BrightnessRangeController.java b/services/core/java/com/android/server/display/BrightnessRangeController.java
index 1d68ee54d96c..83b0801ce87f 100644
--- a/services/core/java/com/android/server/display/BrightnessRangeController.java
+++ b/services/core/java/com/android/server/display/BrightnessRangeController.java
@@ -67,6 +67,10 @@ class BrightnessRangeController {
mNormalBrightnessModeController.resetNbmData(
displayDeviceConfig.getLuxThrottlingData());
}
+ if (flags.useNewHdrBrightnessModifier()) {
+ // HDR boost is handled by HdrBrightnessModifier and should be disabled in HbmController
+ mHbmController.disableHdrBoost();
+ }
updateHdrClamper(info, displayToken, displayDeviceConfig);
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 42a62f098b6a..5b61f006def6 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1503,7 +1503,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// use the current brightness setting scaled by the doze scale factor
rawBrightnessState = getDozeBrightnessForOffload();
brightnessState = clampScreenBrightness(rawBrightnessState);
- updateScreenBrightnessSetting = false;
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_MANUAL);
mTempBrightnessEvent.setFlags(
mTempBrightnessEvent.getFlags() | BrightnessEvent.FLAG_DOZE_SCALE);
@@ -1513,6 +1512,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
brightnessState = clampScreenBrightness(rawBrightnessState);
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT);
}
+ updateScreenBrightnessSetting = false;
}
if (!mFlags.isRefactorDisplayPowerControllerEnabled()) {
diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java
index 135cab6d0614..6be0c123d262 100644
--- a/services/core/java/com/android/server/display/HighBrightnessModeController.java
+++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java
@@ -38,6 +38,7 @@ import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.display.DisplayManagerService.Clock;
import com.android.server.display.config.HighBrightnessModeData;
+import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.utils.DebugUtils;
import java.io.PrintWriter;
@@ -119,6 +120,14 @@ class HighBrightnessModeController {
@Nullable
private HighBrightnessModeMetadata mHighBrightnessModeMetadata;
+ /**
+ * If {@link DisplayManagerFlags#useNewHdrBrightnessModifier()} is ON, hdr boost is handled by
+ * {@link com.android.server.display.brightness.clamper.HdrBrightnessModifier} and should be
+ * disabled in this class. After flag is cleaned up, this field together with HDR handling
+ * should be cleaned up from this class.
+ */
+ private boolean mHdrBoostDisabled = false;
+
HighBrightnessModeController(Handler handler, int width, int height, IBinder displayToken,
String displayUniqueId, float brightnessMin, float brightnessMax,
HighBrightnessModeData hbmData, HdrBrightnessDeviceConfig hdrBrightnessCfg,
@@ -323,6 +332,7 @@ class HighBrightnessModeController {
pw.println(" mIsTimeAvailable= " + mIsTimeAvailable);
pw.println(" mIsBlockedByLowPowerMode=" + mIsBlockedByLowPowerMode);
pw.println(" width*height=" + mWidth + "*" + mHeight);
+ pw.println(" mHdrBoostDisabled=" + mHdrBoostDisabled);
if (mHighBrightnessModeMetadata != null) {
pw.println(" mRunningStartTimeMillis="
@@ -373,6 +383,11 @@ class HighBrightnessModeController {
return mHbmData != null && mHighBrightnessModeMetadata != null;
}
+ void disableHdrBoost() {
+ mHdrBoostDisabled = true;
+ unregisterHdrListener();
+ }
+
private long calculateRemainingTime(long currentTime) {
if (!deviceSupportsHbm()) {
return 0;
@@ -583,6 +598,9 @@ class HighBrightnessModeController {
}
private void registerHdrListener(IBinder displayToken) {
+ if (mHdrBoostDisabled) {
+ return;
+ }
if (mRegisteredDisplayToken == displayToken) {
return;
}
diff --git a/services/core/java/com/android/server/input/InputManagerInternal.java b/services/core/java/com/android/server/input/InputManagerInternal.java
index 99f7f12567b4..c888eef7f5df 100644
--- a/services/core/java/com/android/server/input/InputManagerInternal.java
+++ b/services/core/java/com/android/server/input/InputManagerInternal.java
@@ -262,4 +262,12 @@ public abstract class InputManagerInternal {
*/
public abstract void handleKeyGestureInKeyGestureController(int deviceId, int[] keycodes,
int modifierState, @KeyGestureEvent.KeyGestureType int event);
+
+ /**
+ * Sets the magnification scale factor for pointer icons.
+ *
+ * @param displayId the ID of the display where the new scale factor is applied.
+ * @param scaleFactor the new scale factor to be applied for pointer icons.
+ */
+ public abstract void setAccessibilityPointerIconScaleFactor(int displayId, float scaleFactor);
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 8acf583e0765..98e5319cde30 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -3506,6 +3506,11 @@ public class InputManagerService extends IInputManager.Stub
int modifierState, @KeyGestureEvent.KeyGestureType int gestureType) {
mKeyGestureController.handleKeyGesture(deviceId, keycodes, modifierState, gestureType);
}
+
+ @Override
+ public void setAccessibilityPointerIconScaleFactor(int displayId, float scaleFactor) {
+ InputManagerService.this.setAccessibilityPointerIconScaleFactor(displayId, scaleFactor);
+ }
}
@Override
@@ -3688,6 +3693,10 @@ public class InputManagerService extends IInputManager.Stub
mPointerIconCache.setPointerScale(scale);
}
+ void setAccessibilityPointerIconScaleFactor(int displayId, float scaleFactor) {
+ mPointerIconCache.setAccessibilityScaleFactor(displayId, scaleFactor);
+ }
+
interface KeyboardBacklightControllerInterface {
default void incrementKeyboardBacklight(int deviceId) {}
default void decrementKeyboardBacklight(int deviceId) {}
diff --git a/services/core/java/com/android/server/input/KeyGestureController.java b/services/core/java/com/android/server/input/KeyGestureController.java
index b488db533d12..2f5236f51c48 100644
--- a/services/core/java/com/android/server/input/KeyGestureController.java
+++ b/services/core/java/com/android/server/input/KeyGestureController.java
@@ -23,6 +23,7 @@ import static android.view.WindowManagerPolicyConstants.FLAG_INTERACTIVE;
import static com.android.hardware.input.Flags.useKeyGestureEventHandler;
import static com.android.hardware.input.Flags.useKeyGestureEventHandlerMultiPressGestures;
import static com.android.server.flags.Flags.newBugreportKeyboardShortcut;
+import static com.android.window.flags.Flags.enableMoveToNextDisplayShortcut;
import android.annotation.BinderThread;
import android.annotation.MainThread;
@@ -654,6 +655,18 @@ final class KeyGestureController {
}
}
break;
+ case KeyEvent.KEYCODE_D:
+ if (enableMoveToNextDisplayShortcut()) {
+ if (firstDown && event.isMetaPressed() && event.isCtrlPressed()) {
+ return handleKeyGesture(deviceId, new int[]{keyCode},
+ KeyEvent.META_META_ON | KeyEvent.META_CTRL_ON,
+ KeyGestureEvent.KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY,
+ KeyGestureEvent.ACTION_GESTURE_COMPLETE,
+ displayId,
+ focusedToken, /* flags = */0);
+ }
+ }
+ break;
case KeyEvent.KEYCODE_SLASH:
if (firstDown && event.isMetaPressed()) {
return handleKeyGesture(deviceId, new int[]{keyCode}, KeyEvent.META_META_ON,
diff --git a/services/core/java/com/android/server/input/PointerIconCache.java b/services/core/java/com/android/server/input/PointerIconCache.java
index 297cd68d5d3d..e16031cb664a 100644
--- a/services/core/java/com/android/server/input/PointerIconCache.java
+++ b/services/core/java/com/android/server/input/PointerIconCache.java
@@ -27,6 +27,7 @@ import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseDoubleArray;
import android.util.SparseIntArray;
import android.view.ContextThemeWrapper;
import android.view.Display;
@@ -34,6 +35,7 @@ import android.view.DisplayInfo;
import android.view.PointerIcon;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.UiThread;
import java.util.Objects;
@@ -51,7 +53,7 @@ final class PointerIconCache {
private final NativeInputManagerService mNative;
// We use the UI thread for loading pointer icons.
- private final Handler mUiThreadHandler = UiThread.getHandler();
+ private final Handler mUiThreadHandler;
@GuardedBy("mLoadedPointerIconsByDisplayAndType")
private final SparseArray<SparseArray<PointerIcon>> mLoadedPointerIconsByDisplayAndType =
@@ -70,6 +72,9 @@ final class PointerIconCache {
POINTER_ICON_VECTOR_STYLE_STROKE_WHITE;
@GuardedBy("mLoadedPointerIconsByDisplayAndType")
private float mPointerIconScale = DEFAULT_POINTER_SCALE;
+ // Note that android doesn't have SparseFloatArray, so this falls back to use double instead.
+ @GuardedBy("mLoadedPointerIconsByDisplayAndType")
+ private final SparseDoubleArray mAccessibilityScaleFactorPerDisplay = new SparseDoubleArray();
private final DisplayManager.DisplayListener mDisplayListener =
new DisplayManager.DisplayListener() {
@@ -86,6 +91,7 @@ final class PointerIconCache {
mLoadedPointerIconsByDisplayAndType.remove(displayId);
mDisplayContexts.remove(displayId);
mDisplayDensities.delete(displayId);
+ mAccessibilityScaleFactorPerDisplay.delete(displayId);
}
}
@@ -96,8 +102,15 @@ final class PointerIconCache {
};
/* package */ PointerIconCache(Context context, NativeInputManagerService nativeService) {
+ this(context, nativeService, UiThread.getHandler());
+ }
+
+ @VisibleForTesting
+ /* package */ PointerIconCache(Context context, NativeInputManagerService nativeService,
+ Handler handler) {
mContext = context;
mNative = nativeService;
+ mUiThreadHandler = handler;
}
public void systemRunning() {
@@ -134,6 +147,11 @@ final class PointerIconCache {
mUiThreadHandler.post(() -> handleSetPointerScale(scale));
}
+ /** Set the scale for accessibility (magnification) for vector pointer icons. */
+ public void setAccessibilityScaleFactor(int displayId, float scaleFactor) {
+ mUiThreadHandler.post(() -> handleAccessibilityScaleFactor(displayId, scaleFactor));
+ }
+
/**
* Get a loaded system pointer icon. This will fetch the icon from the cache, or load it if
* it isn't already cached.
@@ -155,8 +173,10 @@ final class PointerIconCache {
/* force= */ true);
theme.applyStyle(PointerIcon.vectorStrokeStyleToResource(mPointerIconStrokeStyle),
/* force= */ true);
+ final float scale = mPointerIconScale
+ * (float) mAccessibilityScaleFactorPerDisplay.get(displayId, 1f);
icon = PointerIcon.getLoadedSystemIcon(new ContextThemeWrapper(context, theme),
- type, mUseLargePointerIcons, mPointerIconScale);
+ type, mUseLargePointerIcons, scale);
iconsByType.put(type, icon);
}
return Objects.requireNonNull(icon);
@@ -261,6 +281,19 @@ final class PointerIconCache {
mNative.reloadPointerIcons();
}
+ @android.annotation.UiThread
+ private void handleAccessibilityScaleFactor(int displayId, float scale) {
+ synchronized (mLoadedPointerIconsByDisplayAndType) {
+ if (mAccessibilityScaleFactorPerDisplay.get(displayId, 1f) == scale) {
+ return;
+ }
+ mAccessibilityScaleFactorPerDisplay.put(displayId, scale);
+ // Clear cached icons on the display.
+ mLoadedPointerIconsByDisplayAndType.remove(displayId);
+ }
+ mNative.reloadPointerIcons();
+ }
+
// Updates the cached display density for the given displayId, and returns true if
// the cached density changed.
@GuardedBy("mLoadedPointerIconsByDisplayAndType")
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index d1576c5cca4f..509fa3e1c9ba 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -127,42 +127,18 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
@BinderThread
public void updateRuleSet(
String version, ParceledListSlice<Rule> rules, IntentSender statusReceiver) {
- String ruleProvider = getCallerPackageNameOrThrow(Binder.getCallingUid());
- if (DEBUG_INTEGRITY_COMPONENT) {
- Slog.i(TAG, String.format("Calling rule provider name is: %s.", ruleProvider));
+ Intent intent = new Intent();
+ intent.putExtra(EXTRA_STATUS, STATUS_SUCCESS);
+ try {
+ statusReceiver.sendIntent(
+ mContext,
+ /* code= */ 0,
+ intent,
+ /* onFinished= */ null,
+ /* handler= */ null);
+ } catch (Exception e) {
+ Slog.e(TAG, "Error sending status feedback.", e);
}
-
- mHandler.post(
- () -> {
- boolean success = true;
- try {
- mIntegrityFileManager.writeRules(version, ruleProvider, rules.getList());
- } catch (Exception e) {
- Slog.e(TAG, "Error writing rules.", e);
- success = false;
- }
-
- if (DEBUG_INTEGRITY_COMPONENT) {
- Slog.i(
- TAG,
- String.format(
- "Successfully pushed rule set to version '%s' from '%s'",
- version, ruleProvider));
- }
-
- Intent intent = new Intent();
- intent.putExtra(EXTRA_STATUS, success ? STATUS_SUCCESS : STATUS_FAILURE);
- try {
- statusReceiver.sendIntent(
- mContext,
- /* code= */ 0,
- intent,
- /* onFinished= */ null,
- /* handler= */ null);
- } catch (Exception e) {
- Slog.e(TAG, "Error sending status feedback.", e);
- }
- });
}
@Override
@@ -209,21 +185,6 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
verificationId, PackageManagerInternal.INTEGRITY_VERIFICATION_ALLOW);
}
- /** We will use the SHA256 digest of a package name if it is more than 32 bytes long. */
- private String getPackageNameNormalized(String packageName) {
- if (packageName.length() <= 32) {
- return packageName;
- }
-
- try {
- MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
- byte[] hashBytes = messageDigest.digest(packageName.getBytes(StandardCharsets.UTF_8));
- return getHexDigest(hashBytes);
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException("SHA-256 algorithm not found", e);
- }
- }
-
private String getCallerPackageNameOrThrow(int callingUid) {
String callerPackageName = getCallingRulePusherPackageName(callingUid);
if (callerPackageName == null) {
diff --git a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
index ea4a6db7a1e8..25741bc326e8 100644
--- a/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
+++ b/services/core/java/com/android/server/notification/NotificationAttentionHelper.java
@@ -81,6 +81,7 @@ import com.android.server.lights.LogicalLight;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -152,6 +153,8 @@ public final class NotificationAttentionHelper {
@interface MuteReason {}
private final Context mContext;
+ //This is NMS.mNotificationLock.
+ private final Object mLock;
private final PackageManager mPackageManager;
private final TelephonyManager mTelephonyManager;
private final UserManager mUm;
@@ -165,6 +168,7 @@ public final class NotificationAttentionHelper {
private VibratorHelper mVibratorHelper;
// The last key in this list owns the hardware.
+ @GuardedBy("mLock")
ArrayList<String> mLights = new ArrayList<>();
private LogicalLight mNotificationLight;
private LogicalLight mAttentionLight;
@@ -183,8 +187,10 @@ public final class NotificationAttentionHelper {
private String mVibrateNotificationKey;
private boolean mSystemReady;
private boolean mInCallStateOffHook = false;
+ @GuardedBy("mLock")
private boolean mScreenOn = true;
private boolean mUserPresent = false;
+ @GuardedBy("mLock")
private boolean mNotificationPulseEnabled;
private final Uri mInCallNotificationUri;
private final AudioAttributes mInCallNotificationAudioAttributes;
@@ -200,12 +206,13 @@ public final class NotificationAttentionHelper {
private final PolitenessStrategy mStrategy;
private int mCurrentWorkProfileId = UserHandle.USER_NULL;
- public NotificationAttentionHelper(Context context, LightsManager lightsManager,
+ public NotificationAttentionHelper(Context context, Object lock, LightsManager lightsManager,
AccessibilityManager accessibilityManager, PackageManager packageManager,
UserManager userManager, NotificationUsageStats usageStats,
NotificationManagerPrivate notificationManagerPrivate,
ZenModeHelper zenModeHelper, SystemUiSystemPropertiesFlags.FlagResolver flagResolver) {
mContext = context;
+ mLock = lock;
mPackageManager = packageManager;
mTelephonyManager = context.getSystemService(TelephonyManager.class);
mAccessibilityManager = accessibilityManager;
@@ -368,9 +375,11 @@ public final class NotificationAttentionHelper {
private void loadUserSettings() {
boolean pulseEnabled = Settings.System.getIntForUser(mContext.getContentResolver(),
Settings.System.NOTIFICATION_LIGHT_PULSE, 0, UserHandle.USER_CURRENT) != 0;
- if (mNotificationPulseEnabled != pulseEnabled) {
- mNotificationPulseEnabled = pulseEnabled;
- updateLightsLocked();
+ synchronized (mLock) {
+ if (mNotificationPulseEnabled != pulseEnabled) {
+ mNotificationPulseEnabled = pulseEnabled;
+ updateLightsLocked();
+ }
}
if (Flags.politeNotifications()) {
@@ -1148,7 +1157,8 @@ public final class NotificationAttentionHelper {
}
}
- public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) {
+ public void dumpLocked(PrintWriter pw, String prefix,
+ NotificationManagerService.DumpFilter filter) {
pw.println("\n Notification attention state:");
pw.print(prefix);
pw.println(" mSoundNotificationKey=" + mSoundNotificationKey);
@@ -1684,16 +1694,22 @@ public final class NotificationAttentionHelper {
if (action.equals(Intent.ACTION_SCREEN_ON)) {
// Keep track of screen on/off state, but do not turn off the notification light
// until user passes through the lock screen or views the notification.
- mScreenOn = true;
- updateLightsLocked();
+ synchronized (mLock) {
+ mScreenOn = true;
+ updateLightsLocked();
+ }
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
- mScreenOn = false;
- mUserPresent = false;
- updateLightsLocked();
+ synchronized (mLock) {
+ mScreenOn = false;
+ mUserPresent = false;
+ updateLightsLocked();
+ }
} else if (action.equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
mInCallStateOffHook = TelephonyManager.EXTRA_STATE_OFFHOOK
.equals(intent.getStringExtra(TelephonyManager.EXTRA_STATE));
- updateLightsLocked();
+ synchronized (mLock) {
+ updateLightsLocked();
+ }
} else if (action.equals(Intent.ACTION_USER_PRESENT)) {
mUserPresent = true;
// turn off LED when user passes through lock screen
@@ -1755,9 +1771,11 @@ public final class NotificationAttentionHelper {
Settings.System.NOTIFICATION_LIGHT_PULSE, 0,
UserHandle.USER_CURRENT)
!= 0;
- if (mNotificationPulseEnabled != pulseEnabled) {
- mNotificationPulseEnabled = pulseEnabled;
- updateLightsLocked();
+ synchronized (mLock) {
+ if (mNotificationPulseEnabled != pulseEnabled) {
+ mNotificationPulseEnabled = pulseEnabled;
+ updateLightsLocked();
+ }
}
}
if (Flags.politeNotifications()) {
@@ -1840,7 +1858,9 @@ public final class NotificationAttentionHelper {
@VisibleForTesting
void setScreenOn(boolean on) {
- mScreenOn = on;
+ synchronized (mLock) {
+ mScreenOn = on;
+ }
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e48c8ee718e3..48cc03221124 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2640,9 +2640,9 @@ public class NotificationManagerService extends SystemService {
mToastRateLimiter = toastRateLimiter;
- mAttentionHelper = new NotificationAttentionHelper(getContext(), lightsManager,
- mAccessibilityManager, mPackageManagerClient, userManager, usageStats,
- mNotificationManagerPrivate, mZenModeHelper, flagResolver);
+ mAttentionHelper = new NotificationAttentionHelper(getContext(), mNotificationLock,
+ lightsManager, mAccessibilityManager, mPackageManagerClient, userManager,
+ usageStats, mNotificationManagerPrivate, mZenModeHelper, flagResolver);
// register for various Intents.
// If this is called within a test, make sure to unregister the intent receivers by
@@ -7331,7 +7331,7 @@ public class NotificationManagerService extends SystemService {
pw.println(" mMaxPackageEnqueueRate=" + mMaxPackageEnqueueRate);
pw.println(" hideSilentStatusBar="
+ mPreferencesHelper.shouldHideSilentStatusIcons());
- mAttentionHelper.dump(pw, " ", filter);
+ mAttentionHelper.dumpLocked(pw, " ", filter);
}
pw.println(" mArchive=" + mArchive.toString());
mArchive.dumpImpl(pw, filter);
diff --git a/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java b/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java
index a221152222ee..d1d6ed0f1f99 100644
--- a/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java
+++ b/services/core/java/com/android/server/pm/BackgroundUserSoundNotifier.java
@@ -34,16 +34,19 @@ import android.media.AudioFocusInfo;
import android.media.AudioManager;
import android.media.AudioPlaybackConfiguration;
import android.media.audiopolicy.AudioPolicy;
+import android.multiuser.Flags;
import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.ArraySet;
import android.util.Log;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import java.util.List;
+import java.util.Set;
public class BackgroundUserSoundNotifier {
@@ -65,6 +68,10 @@ public class BackgroundUserSoundNotifier {
*/
@VisibleForTesting
int mNotificationClientUid = -1;
+ /**
+ * UIDs of audio focus infos with active notifications.
+ */
+ Set<Integer> mNotificationClientUids = new ArraySet<>();
@VisibleForTesting
AudioPolicy mFocusControlAudioPolicy;
@VisibleForTesting
@@ -149,26 +156,42 @@ public class BackgroundUserSoundNotifier {
@SuppressLint("MissingPermission")
@Override
public void onReceive(Context context, Intent intent) {
- if (mNotificationClientUid == -1) {
- return;
+ if (Flags.multipleAlarmNotificationsSupport()) {
+ if (!intent.hasExtra(EXTRA_NOTIFICATION_CLIENT_UID)) {
+ return;
+ }
+ } else {
+ if (mNotificationClientUid == -1) {
+ return;
+ }
}
- dismissNotification(mNotificationClientUid);
+
+ int clientUid;
+ if (Flags.multipleAlarmNotificationsSupport()) {
+ clientUid = intent.getIntExtra(EXTRA_NOTIFICATION_CLIENT_UID, -1);
+ } else {
+ clientUid = mNotificationClientUid;
+ }
+ dismissNotification(clientUid);
if (DEBUG) {
final int actionIndex = intent.getAction().lastIndexOf(".") + 1;
final String action = intent.getAction().substring(actionIndex);
Log.d(LOG_TAG, "Action requested: " + action + ", by userId "
+ ActivityManager.getCurrentUser() + " for alarm on user "
- + UserHandle.getUserHandleForUid(mNotificationClientUid));
+ + UserHandle.getUserHandleForUid(clientUid));
}
if (ACTION_MUTE_SOUND.equals(intent.getAction())) {
- muteAlarmSounds(mNotificationClientUid);
+ muteAlarmSounds(clientUid);
} else if (ACTION_SWITCH_USER.equals(intent.getAction())) {
- activityManager.switchUser(UserHandle.getUserId(mNotificationClientUid));
+ activityManager.switchUser(UserHandle.getUserId(clientUid));
+ }
+ if (Flags.multipleAlarmNotificationsSupport()) {
+ mNotificationClientUids.remove(clientUid);
+ } else {
+ mNotificationClientUid = -1;
}
-
- mNotificationClientUid = -1;
}
};
@@ -215,10 +238,11 @@ public class BackgroundUserSoundNotifier {
final int userId = UserHandle.getUserId(afi.getClientUid());
final int usage = afi.getAttributes().getUsage();
UserInfo userInfo = mUserManager.getUserInfo(userId);
+
// Only show notification if the sound is coming from background user and the notification
- // is not already shown.
+ // for this UID is not already shown.
if (userInfo != null && userId != foregroundContext.getUserId()
- && mNotificationClientUid == -1) {
+ && !isNotificationShown(afi.getClientUid())) {
//TODO: b/349138482 - Add handling of cases when usage == USAGE_NOTIFICATION_RINGTONE
if (usage == USAGE_ALARM) {
if (DEBUG) {
@@ -226,8 +250,11 @@ public class BackgroundUserSoundNotifier {
+ ", displaying notification for current user "
+ foregroundContext.getUserId());
}
-
- mNotificationClientUid = afi.getClientUid();
+ if (Flags.multipleAlarmNotificationsSupport()) {
+ mNotificationClientUids.add(afi.getClientUid());
+ } else {
+ mNotificationClientUid = afi.getClientUid();
+ }
mNotificationManager.notifyAsUser(LOG_TAG, afi.getClientUid(),
createNotification(userInfo.name, foregroundContext, afi.getClientUid()),
@@ -243,15 +270,21 @@ public class BackgroundUserSoundNotifier {
*/
@VisibleForTesting
void dismissNotificationIfNecessary(int notificationClientUid) {
+
if (getAudioFocusInfoForNotification(notificationClientUid) == null
- && mNotificationClientUid >= 0) {
+ && isNotificationShown(notificationClientUid)) {
if (DEBUG) {
Log.d(LOG_TAG, "Alarm ringing on background user "
+ UserHandle.getUserHandleForUid(notificationClientUid).getIdentifier()
+ " left focus stack, dismissing notification");
}
dismissNotification(notificationClientUid);
- mNotificationClientUid = -1;
+
+ if (Flags.multipleAlarmNotificationsSupport()) {
+ mNotificationClientUids.remove(notificationClientUid);
+ } else {
+ mNotificationClientUid = -1;
+ }
}
}
@@ -331,4 +364,12 @@ public class BackgroundUserSoundNotifier {
return notificationBuilder.build();
}
+
+ private boolean isNotificationShown(int notificationClientUid) {
+ if (Flags.multipleAlarmNotificationsSupport()) {
+ return mNotificationClientUids.contains(notificationClientUid);
+ } else {
+ return mNotificationClientUid != -1;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/power/PowerManagerShellCommand.java b/services/core/java/com/android/server/power/PowerManagerShellCommand.java
index f69a017fc45a..35a69a29d16a 100644
--- a/services/core/java/com/android/server/power/PowerManagerShellCommand.java
+++ b/services/core/java/com/android/server/power/PowerManagerShellCommand.java
@@ -22,6 +22,8 @@ import android.app.IAlarmListener;
import android.app.IAlarmManager;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManagerInternal;
+import android.os.Binder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.PowerManagerInternal;
@@ -32,6 +34,9 @@ import android.os.SystemClock;
import android.util.SparseArray;
import android.view.Display;
+import com.android.server.LocalServices;
+import com.android.server.pm.pkg.AndroidPackage;
+
import java.io.PrintWriter;
import java.util.List;
@@ -266,11 +271,18 @@ class PowerManagerShellCommand extends ShellCommand {
ServiceManager.getService(Context.ALARM_SERVICE));
}
try {
- // This command is called by the shell, which has "com.android.shell" as package
- // name.
- pw.println("Schedule an alarm to wakeup in "
- + delayMillis + " ms, on behalf of shell.");
- mAlarmManager.set("com.android.shell",
+ PackageManagerInternal packageManagerInternal =
+ LocalServices.getService(PackageManagerInternal.class);
+ AndroidPackage callingPackage =
+ packageManagerInternal.getPackage(Binder.getCallingUid());
+ if (callingPackage == null) {
+ pw.println("Calling uid " + Binder.getCallingUid() + " is not an android"
+ + " package. Cannot schedule a delayed wakeup on behalf of it.");
+ return -1;
+ }
+ pw.println("Schedule an alarm to wakeup in " + delayMillis +
+ " ms, on behalf of " + callingPackage.getPackageName());
+ mAlarmManager.set(callingPackage.getPackageName(),
AlarmManager.RTC_WAKEUP, wakeUpTime,
0, 0, AlarmManager.FLAG_PRIORITIZE,
null, mAlarmListener, "PowerManagerShellCommand", null, null);
diff --git a/services/core/java/com/android/server/power/stats/AccumulatedBatteryUsageStatsSection.java b/services/core/java/com/android/server/power/stats/AccumulatedBatteryUsageStatsSection.java
index dd6d5dbf753c..c0a06fcfdeaa 100644
--- a/services/core/java/com/android/server/power/stats/AccumulatedBatteryUsageStatsSection.java
+++ b/services/core/java/com/android/server/power/stats/AccumulatedBatteryUsageStatsSection.java
@@ -51,6 +51,11 @@ class AccumulatedBatteryUsageStatsSection extends PowerStatsSpan.Section {
mBatteryUsageStats.build().dump(ipw, "");
}
+ @Override
+ public void close() {
+ mBatteryUsageStats.discard();
+ }
+
static class Reader implements PowerStatsSpan.SectionReader {
@Override
public String getType() {
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index c04158fe5243..48174a6bad11 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -11509,9 +11509,6 @@ public class BatteryStatsImpl extends BatteryStats {
mOnBatteryTimeBase);
}
- mPerDisplayBatteryStats = new DisplayBatteryStats[1];
- mPerDisplayBatteryStats[0] = new DisplayBatteryStats(mClock, mOnBatteryTimeBase);
-
mInteractiveTimer = new StopwatchTimer(mClock, null, -10, null, mOnBatteryTimeBase);
mPowerSaveModeEnabledTimer = new StopwatchTimer(mClock, null, -2, null,
mOnBatteryTimeBase);
diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
index 265f1dfce90f..b996c43d3dd5 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsProvider.java
@@ -295,7 +295,8 @@ public class BatteryUsageStatsProvider {
stats.builder = ((AccumulatedBatteryUsageStatsSection) section)
.getBatteryUsageStatsBuilder();
stats.startWallClockTime = powerStatsSpan.getMetadata().getStartTime();
- stats.startMonotonicTime = powerStatsSpan.getMetadata().getStartMonotonicTime();
+ stats.startMonotonicTime =
+ powerStatsSpan.getMetadata().getStartMonotonicTime();
stats.endMonotonicTime = powerStatsSpan.getMetadata().getEndMonotonicTime();
break;
}
@@ -484,29 +485,30 @@ public class BatteryUsageStatsProvider {
continue;
}
- PowerStatsSpan powerStatsSpan = mPowerStatsStore.loadPowerStatsSpan(
- spanMetadata.getId(), BatteryUsageStatsSection.TYPE);
- if (powerStatsSpan == null) {
- continue;
- }
-
- for (PowerStatsSpan.Section section : powerStatsSpan.getSections()) {
- BatteryUsageStats snapshot =
- ((BatteryUsageStatsSection) section).getBatteryUsageStats();
- if (!Arrays.equals(snapshot.getCustomPowerComponentNames(),
- customEnergyConsumerNames)) {
- Log.w(TAG, "Ignoring older BatteryUsageStats snapshot, which has different "
- + "custom power components: "
- + Arrays.toString(snapshot.getCustomPowerComponentNames()));
+ try (PowerStatsSpan powerStatsSpan = mPowerStatsStore.loadPowerStatsSpan(
+ spanMetadata.getId(), BatteryUsageStatsSection.TYPE)) {
+ if (powerStatsSpan == null) {
continue;
}
- if (includeProcessStateData && !snapshot.isProcessStateDataIncluded()) {
- Log.w(TAG, "Ignoring older BatteryUsageStats snapshot, which "
- + " does not include process state data");
- continue;
+ for (PowerStatsSpan.Section section : powerStatsSpan.getSections()) {
+ BatteryUsageStats snapshot =
+ ((BatteryUsageStatsSection) section).getBatteryUsageStats();
+ if (!Arrays.equals(snapshot.getCustomPowerComponentNames(),
+ customEnergyConsumerNames)) {
+ Log.w(TAG, "Ignoring older BatteryUsageStats snapshot, which has different "
+ + "custom power components: "
+ + Arrays.toString(snapshot.getCustomPowerComponentNames()));
+ continue;
+ }
+
+ if (includeProcessStateData && !snapshot.isProcessStateDataIncluded()) {
+ Log.w(TAG, "Ignoring older BatteryUsageStats snapshot, which "
+ + " does not include process state data");
+ continue;
+ }
+ builder.add(snapshot);
}
- builder.add(snapshot);
}
}
return builder.build();
diff --git a/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java b/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java
index af3652475376..eb896e9d4eee 100644
--- a/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java
+++ b/services/core/java/com/android/server/power/stats/BatteryUsageStatsSection.java
@@ -18,6 +18,7 @@ package com.android.server.power.stats;
import android.os.BatteryUsageStats;
import android.util.IndentingPrintWriter;
+import android.util.Slog;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
@@ -28,6 +29,7 @@ import java.io.IOException;
class BatteryUsageStatsSection extends PowerStatsSpan.Section {
public static final String TYPE = "battery-usage-stats";
+ private static final String TAG = "BatteryUsageStatsSection";
private final BatteryUsageStats mBatteryUsageStats;
@@ -50,6 +52,15 @@ class BatteryUsageStatsSection extends PowerStatsSpan.Section {
mBatteryUsageStats.dump(ipw, "");
}
+ @Override
+ public void close() {
+ try {
+ mBatteryUsageStats.close();
+ } catch (IOException e) {
+ Slog.e(TAG, "Closing BatteryUsageStats", e);
+ }
+ }
+
static class Reader implements PowerStatsSpan.SectionReader {
@Override
public String getType() {
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsSpan.java b/services/core/java/com/android/server/power/stats/PowerStatsSpan.java
index 5105272e6980..4f560cf68f8e 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsSpan.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsSpan.java
@@ -51,7 +51,7 @@ import java.util.Set;
/**
* Contains power stats of various kinds, aggregated over a time span.
*/
-public class PowerStatsSpan {
+public class PowerStatsSpan implements AutoCloseable {
private static final String TAG = "PowerStatsStore";
/**
@@ -321,6 +321,13 @@ public class PowerStatsSpan {
public void dump(IndentingPrintWriter ipw) {
ipw.println(mType);
}
+
+ /**
+ * Closes the section, releasing any resources it held. Once closed, the Section
+ * should not be used.
+ */
+ public void close() {
+ }
}
/**
@@ -484,4 +491,10 @@ public class PowerStatsSpan {
ipw.decreaseIndent();
}
}
+ @Override
+ public void close() {
+ for (int i = 0; i < mSections.size(); i++) {
+ mSections.get(i).close();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/power/stats/PowerStatsStore.java b/services/core/java/com/android/server/power/stats/PowerStatsStore.java
index 3673617f6104..d83d355fce31 100644
--- a/services/core/java/com/android/server/power/stats/PowerStatsStore.java
+++ b/services/core/java/com/android/server/power/stats/PowerStatsStore.java
@@ -331,9 +331,10 @@ public class PowerStatsStore {
ipw.increaseIndent();
List<PowerStatsSpan.Metadata> contents = getTableOfContents();
for (PowerStatsSpan.Metadata metadata : contents) {
- PowerStatsSpan span = loadPowerStatsSpan(metadata.getId());
- if (span != null) {
- span.dump(ipw);
+ try (PowerStatsSpan span = loadPowerStatsSpan(metadata.getId())) {
+ if (span != null) {
+ span.dump(ipw);
+ }
}
}
ipw.decreaseIndent();
diff --git a/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java
index 32dfdf915bca..5f93bdf07f47 100644
--- a/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/AmbientDisplayPowerStatsProcessor.java
@@ -50,12 +50,14 @@ class AmbientDisplayPowerStatsProcessor extends PowerStatsProcessor {
return;
}
- if (mScreenPowerStatsDescriptor == null) {
- mScreenPowerStatsDescriptor = screenStats.getPowerStatsDescriptor();
- if (mScreenPowerStatsDescriptor == null) {
- return;
- }
+ PowerStats.Descriptor screenDescriptor = screenStats.getPowerStatsDescriptor();
+ if (screenDescriptor == null) {
+ return;
+ }
+ if (mScreenPowerStatsDescriptor == null
+ || !mScreenPowerStatsDescriptor.equals(screenDescriptor)) {
+ mScreenPowerStatsDescriptor = screenDescriptor;
mScreenPowerStatsLayout = new ScreenPowerStatsLayout(mScreenPowerStatsDescriptor);
mTmpScreenStats = new long[mScreenPowerStatsDescriptor.statsArrayLength];
}
diff --git a/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java b/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java
index c8170a1982bb..b2442c81b2e5 100644
--- a/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java
+++ b/services/core/java/com/android/server/power/stats/processor/PowerStatsExporter.java
@@ -105,19 +105,19 @@ class PowerStatsExporter {
maxEndTime = spanMaxTime;
}
- PowerStatsSpan span = mPowerStatsStore.loadPowerStatsSpan(metadata.getId(),
- AggregatedPowerStatsSection.TYPE);
- if (span == null) {
- Slog.e(TAG, "Could not read PowerStatsStore section " + metadata);
- continue;
- }
- List<PowerStatsSpan.Section> sections = span.getSections();
- for (int k = 0; k < sections.size(); k++) {
- hasStoredSpans = true;
- PowerStatsSpan.Section section = sections.get(k);
- populateBatteryUsageStatsBuilder(batteryUsageStatsBuilder,
- ((AggregatedPowerStatsSection) section).getAggregatedPowerStats());
- // TODO(b/371614748): close the builder
+ try (PowerStatsSpan span = mPowerStatsStore.loadPowerStatsSpan(metadata.getId(),
+ AggregatedPowerStatsSection.TYPE)) {
+ if (span == null) {
+ Slog.e(TAG, "Could not read PowerStatsStore section " + metadata);
+ continue;
+ }
+ List<PowerStatsSpan.Section> sections = span.getSections();
+ for (int k = 0; k < sections.size(); k++) {
+ hasStoredSpans = true;
+ PowerStatsSpan.Section section = sections.get(k);
+ populateBatteryUsageStatsBuilder(batteryUsageStatsBuilder,
+ ((AggregatedPowerStatsSection) section).getAggregatedPowerStats());
+ }
}
}
diff --git a/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java b/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
index b295e309d4fb..8e7498f38fcb 100644
--- a/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
+++ b/services/core/java/com/android/server/power/stats/processor/ScreenPowerStatsProcessor.java
@@ -89,14 +89,15 @@ class ScreenPowerStatsProcessor extends PowerStatsProcessor {
return true;
}
- mLastUsedDescriptor = descriptor;
- mStatsLayout = new ScreenPowerStatsLayout(descriptor);
- if (mStatsLayout.getDisplayCount() != mDisplayCount) {
- Slog.e(TAG, "Incompatible number of displays: " + mStatsLayout.getDisplayCount()
+ ScreenPowerStatsLayout statsLayout = new ScreenPowerStatsLayout(descriptor);
+ if (statsLayout.getDisplayCount() != mDisplayCount) {
+ Slog.e(TAG, "Incompatible number of displays: " + statsLayout.getDisplayCount()
+ ", expected: " + mDisplayCount);
return false;
}
+ mLastUsedDescriptor = descriptor;
+ mStatsLayout = statsLayout;
mTmpDeviceStatsArray = new long[descriptor.statsArrayLength];
mTmpUidStatsArray = new long[descriptor.uidStatsArrayLength];
return true;
diff --git a/services/core/java/com/android/server/security/forensic/BackupTransportConnection.java b/services/core/java/com/android/server/security/forensic/BackupTransportConnection.java
new file mode 100644
index 000000000000..caca011b6549
--- /dev/null
+++ b/services/core/java/com/android/server/security/forensic/BackupTransportConnection.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.security.forensic;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.security.forensic.ForensicEvent;
+import android.security.forensic.IBackupTransport;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import com.android.internal.infra.AndroidFuture;
+
+import java.util.List;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public class BackupTransportConnection implements ServiceConnection {
+ private static final String TAG = "BackupTransportConnection";
+ private static final long FUTURE_TIMEOUT_MILLIS = 60 * 1000; // 1 mins
+ private final Context mContext;
+ private String mForensicBackupTransportConfig;
+ volatile IBackupTransport mService;
+
+ public BackupTransportConnection(Context context) {
+ mContext = context;
+ mService = null;
+ }
+
+ /**
+ * Initialize the BackupTransport binder service.
+ * @return Whether the initialization succeed.
+ */
+ public boolean initialize() {
+ if (!bindService()) {
+ return false;
+ }
+ AndroidFuture<Integer> resultFuture = new AndroidFuture<>();
+ try {
+ mService.initialize(resultFuture);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote Exception", e);
+ unbindService();
+ return false;
+ }
+ Integer result = getFutureResult(resultFuture);
+ if (result != null && result == 0) {
+ return true;
+ } else {
+ unbindService();
+ return false;
+ }
+ }
+
+ /**
+ * Add data to the BackupTransport binder service.
+ * @param data List of ForensicEvent.
+ * @return Whether the data is added to the binder service.
+ */
+ public boolean addData(List<ForensicEvent> data) {
+ AndroidFuture<Integer> resultFuture = new AndroidFuture<>();
+ try {
+ mService.addData(data, resultFuture);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote Exception", e);
+ return false;
+ }
+ Integer result = getFutureResult(resultFuture);
+ return result != null && result == 0;
+ }
+
+ /**
+ * Release the BackupTransport binder service.
+ */
+ public void release() {
+ AndroidFuture<Integer> resultFuture = new AndroidFuture<>();
+ try {
+ mService.release(resultFuture);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote Exception", e);
+ } finally {
+ unbindService();
+ }
+ }
+
+ private <T> T getFutureResult(AndroidFuture<T> future) {
+ try {
+ return future.get(FUTURE_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException
+ | CancellationException e) {
+ Slog.w(TAG, "Failed to get result from transport:", e);
+ return null;
+ }
+ }
+
+ private boolean bindService() {
+ mForensicBackupTransportConfig = mContext.getString(
+ com.android.internal.R.string.config_forensicBackupTransport);
+ if (TextUtils.isEmpty(mForensicBackupTransportConfig)) {
+ return false;
+ }
+
+ ComponentName serviceComponent =
+ ComponentName.unflattenFromString(mForensicBackupTransportConfig);
+ if (serviceComponent == null) {
+ return false;
+ }
+
+ Intent intent = new Intent().setComponent(serviceComponent);
+ boolean result = mContext.bindServiceAsUser(
+ intent, this, Context.BIND_AUTO_CREATE, UserHandle.SYSTEM);
+ if (!result) {
+ unbindService();
+ }
+ return result;
+ }
+
+ private void unbindService() {
+ mContext.unbindService(this);
+ mService = null;
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mService = IBackupTransport.Stub.asInterface(service);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ mService = null;
+ }
+}
diff --git a/services/core/java/com/android/server/security/forensic/ForensicService.java b/services/core/java/com/android/server/security/forensic/ForensicService.java
index 07639d1a3945..20c648eb61c2 100644
--- a/services/core/java/com/android/server/security/forensic/ForensicService.java
+++ b/services/core/java/com/android/server/security/forensic/ForensicService.java
@@ -63,6 +63,7 @@ public class ForensicService extends SystemService {
private final Context mContext;
private final Handler mHandler;
+ private final BackupTransportConnection mBackupTransportConnection;
private final BinderService mBinderService;
private final ArrayList<IForensicServiceStateCallback> mStateMonitors = new ArrayList<>();
@@ -77,6 +78,7 @@ public class ForensicService extends SystemService {
super(injector.getContext());
mContext = injector.getContext();
mHandler = new EventHandler(injector.getLooper(), this);
+ mBackupTransportConnection = injector.getBackupTransportConnection();
mBinderService = new BinderService(this);
}
@@ -221,6 +223,10 @@ public class ForensicService extends SystemService {
private void enable(IForensicServiceCommandCallback callback) throws RemoteException {
switch (mState) {
case STATE_VISIBLE:
+ if (!mBackupTransportConnection.initialize()) {
+ callback.onFailure(ERROR_BACKUP_TRANSPORT_UNAVAILABLE);
+ break;
+ }
mState = STATE_ENABLED;
notifyStateMonitors();
callback.onSuccess();
@@ -236,6 +242,7 @@ public class ForensicService extends SystemService {
private void disable(IForensicServiceCommandCallback callback) throws RemoteException {
switch (mState) {
case STATE_ENABLED:
+ mBackupTransportConnection.release();
mState = STATE_VISIBLE;
notifyStateMonitors();
callback.onSuccess();
@@ -266,6 +273,8 @@ public class ForensicService extends SystemService {
Context getContext();
Looper getLooper();
+
+ BackupTransportConnection getBackupTransportConnection();
}
private static final class InjectorImpl implements Injector {
@@ -289,6 +298,11 @@ public class ForensicService extends SystemService {
serviceThread.start();
return serviceThread.getLooper();
}
+
+ @Override
+ public BackupTransportConnection getBackupTransportConnection() {
+ return new BackupTransportConnection(mContext);
+ }
}
}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index e7735d8480f8..54e4f8e9a110 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -48,6 +48,9 @@ import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
import static android.util.MathUtils.constrain;
import static android.view.Display.HdrCapabilities.HDR_TYPE_INVALID;
+import static com.android.internal.os.ProcfsMemoryUtil.getProcessCmdlines;
+import static com.android.internal.os.ProcfsMemoryUtil.readCmdlineFromProcfs;
+import static com.android.internal.os.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
import static com.android.internal.util.ConcurrentUtils.DIRECT_EXECUTOR;
import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS__GESTURE_SHORTCUT_TYPE__TRIPLE_TAP;
import static com.android.internal.util.FrameworkStatsLog.ACCESSIBILITY_SHORTCUT_STATS__HARDWARE_SHORTCUT_TYPE__VOLUME_KEY;
@@ -68,9 +71,6 @@ import static com.android.server.stats.Flags.addMobileBytesTransferByProcStatePu
import static com.android.server.stats.Flags.applyNetworkStatsPollRateLimit;
import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
-import static com.android.server.stats.pull.ProcfsMemoryUtil.getProcessCmdlines;
-import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs;
-import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
import static com.android.server.stats.pull.netstats.NetworkStatsUtils.fromPublicNetworkStats;
import static com.android.server.stats.pull.netstats.NetworkStatsUtils.isAddEntriesSupported;
@@ -209,6 +209,8 @@ import com.android.internal.os.KernelSingleProcessCpuThreadReader.ProcessCpuUsag
import com.android.internal.os.LooperStats;
import com.android.internal.os.PowerProfile;
import com.android.internal.os.ProcessCpuTracker;
+import com.android.internal.os.ProcfsMemoryUtil;
+import com.android.internal.os.ProcfsMemoryUtil.MemorySnapshot;
import com.android.internal.os.SelectedProcessCpuThreadReader;
import com.android.internal.os.StoragedUidIoStatsReader;
import com.android.internal.util.CollectionUtils;
@@ -229,7 +231,6 @@ import com.android.server.power.stats.KernelWakelockReader;
import com.android.server.power.stats.KernelWakelockStats;
import com.android.server.power.stats.SystemServerCpuThreadReader.SystemServiceCpuThreadTimes;
import com.android.server.stats.pull.IonMemoryUtil.IonAllocations;
-import com.android.server.stats.pull.ProcfsMemoryUtil.MemorySnapshot;
import com.android.server.stats.pull.netstats.NetworkStatsAccumulator;
import com.android.server.stats.pull.netstats.NetworkStatsExt;
import com.android.server.stats.pull.netstats.SubInfo;
diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
index 1e82b8999834..baf84cf4aa8b 100644
--- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
+++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -40,11 +40,11 @@ import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
-import com.android.internal.util.IndentingPrintWriter;
import com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
import java.util.ArrayList;
diff --git a/services/core/java/com/android/server/vcn/Vcn.java b/services/core/java/com/android/server/vcn/Vcn.java
index 5bc2c2dface9..1fba29779f0f 100644
--- a/services/core/java/com/android/server/vcn/Vcn.java
+++ b/services/core/java/com/android/server/vcn/Vcn.java
@@ -47,11 +47,11 @@ import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
-import com.android.internal.util.IndentingPrintWriter;
import com.android.server.VcnManagementService.VcnCallback;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import com.android.server.vcn.util.LogUtils;
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index a81ad22ddf4a..189b6089186e 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -90,11 +90,11 @@ import android.os.SystemClock;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
-import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
import com.android.internal.util.WakeupMessage;
diff --git a/services/core/java/com/android/server/vcn/VcnNetworkProvider.java b/services/core/java/com/android/server/vcn/VcnNetworkProvider.java
index 31ee2477fa64..78ff432f5423 100644
--- a/services/core/java/com/android/server/vcn/VcnNetworkProvider.java
+++ b/services/core/java/com/android/server/vcn/VcnNetworkProvider.java
@@ -36,11 +36,11 @@ import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
-import com.android.internal.util.IndentingPrintWriter;
import java.util.Objects;
import java.util.Set;
diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
index ad5bc7294f85..0b9b677df16a 100644
--- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
+++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
@@ -46,11 +46,11 @@ import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
-import com.android.internal.util.IndentingPrintWriter;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import com.android.server.vcn.VcnContext;
import com.android.server.vcn.routeselection.UnderlyingNetworkEvaluator.NetworkEvaluatorCallback;
diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java
index 53b0751d196e..448a7ebfffd8 100644
--- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java
+++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkEvaluator.java
@@ -29,11 +29,11 @@ import android.net.vcn.VcnManager;
import android.net.vcn.VcnUnderlyingNetworkTemplate;
import android.os.Handler;
import android.os.ParcelUuid;
+import android.util.IndentingPrintWriter;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
-import com.android.internal.util.IndentingPrintWriter;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import com.android.server.vcn.VcnContext;
diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
index 7ab8e552722a..1945052b92df 100644
--- a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
+++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
@@ -22,10 +22,10 @@ import android.annotation.Nullable;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
+import android.util.IndentingPrintWriter;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting.Visibility;
-import com.android.internal.util.IndentingPrintWriter;
import java.util.Objects;
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index c1f5a27b81e7..a2c2dfc0a5be 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -478,10 +478,10 @@ public class ActivityStartController {
intentGrants.merge(creatorIntentGrants);
}
} catch (SecurityException securityException) {
- ActivityStarter.logForIntentRedirect(
+ ActivityStarter.logAndThrowExceptionForIntentRedirect(
"Creator URI Grant Caused Exception.", intent, creatorUid,
- creatorPackage, filterCallingUid, callingPackage);
- // TODO b/368559093 - rethrow the securityException.
+ creatorPackage, filterCallingUid, callingPackage,
+ securityException);
}
}
if ((aInfo.applicationInfo.privateFlags
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 5d3ae54f0934..2c4179fb6d88 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -54,6 +54,7 @@ import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
import static android.content.pm.ActivityInfo.launchModeToString;
import static android.os.Process.INVALID_UID;
+import static android.security.Flags.preventIntentRedirectAbortOrThrowException;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_OPEN;
@@ -100,9 +101,11 @@ import android.app.PendingIntent;
import android.app.ProfilerInfo;
import android.app.WaitResult;
import android.app.WindowConfiguration;
+import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.Disabled;
import android.compat.annotation.EnabledSince;
+import android.compat.annotation.Overridable;
import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
@@ -188,6 +191,10 @@ class ActivityStarter {
@Disabled
static final long ASM_RESTRICTIONS = 230590090L;
+ @ChangeId
+ @Overridable
+ private static final long ENABLE_PREVENT_INTENT_REDIRECT_TAKE_ACTION = 29623414L;
+
private final ActivityTaskManagerService mService;
private final RootWindowContainer mRootWindowContainer;
private final ActivityTaskSupervisor mSupervisor;
@@ -608,11 +615,10 @@ class ActivityStarter {
// Check if the Intent was redirected
if ((intent.getExtendedFlags() & Intent.EXTENDED_FLAG_MISSING_CREATOR_OR_INVALID_TOKEN)
!= 0) {
- ActivityStarter.logForIntentRedirect(
+ ActivityStarter.logAndThrowExceptionForIntentRedirect(
"Unparceled intent does not have a creator token set.", intent,
- intentCreatorUid,
- intentCreatorPackage, resolvedCallingUid, resolvedCallingPackage);
- // TODO b/368559093 - eventually ramp up to throw SecurityException
+ intentCreatorUid, intentCreatorPackage, resolvedCallingUid,
+ resolvedCallingPackage, null);
}
if (IntentCreatorToken.isValid(intent)) {
IntentCreatorToken creatorToken = (IntentCreatorToken) intent.getCreatorToken();
@@ -645,11 +651,10 @@ class ActivityStarter {
intentGrants.merge(creatorIntentGrants);
}
} catch (SecurityException securityException) {
- ActivityStarter.logForIntentRedirect(
+ ActivityStarter.logAndThrowExceptionForIntentRedirect(
"Creator URI Grant Caused Exception.", intent, intentCreatorUid,
intentCreatorPackage, resolvedCallingUid,
- resolvedCallingPackage);
- // TODO b/368559093 - rethrow the securityException.
+ resolvedCallingPackage, securityException);
}
}
} else {
@@ -670,11 +675,10 @@ class ActivityStarter {
intentGrants.merge(creatorIntentGrants);
}
} catch (SecurityException securityException) {
- ActivityStarter.logForIntentRedirect(
+ ActivityStarter.logAndThrowExceptionForIntentRedirect(
"Creator URI Grant Caused Exception.", intent, intentCreatorUid,
intentCreatorPackage, resolvedCallingUid,
- resolvedCallingPackage);
- // TODO b/368559093 - rethrow the securityException.
+ resolvedCallingPackage, securityException);
}
}
}
@@ -1045,7 +1049,7 @@ class ActivityStarter {
int callingUid = request.callingUid;
int intentCreatorUid = request.intentCreatorUid;
String intentCreatorPackage = request.intentCreatorPackage;
- String intentCallingPackage = request.callingPackage;
+ String callingPackage = request.callingPackage;
String callingFeatureId = request.callingFeatureId;
final int realCallingPid = request.realCallingPid;
final int realCallingUid = request.realCallingUid;
@@ -1130,7 +1134,7 @@ class ActivityStarter {
// launched in the app flow to redirect to an activity picked by the user, where
// we want the final activity to consider it to have been launched by the
// previous app activity.
- intentCallingPackage = sourceRecord.launchedFromPackage;
+ callingPackage = sourceRecord.launchedFromPackage;
callingFeatureId = sourceRecord.launchedFromFeatureId;
}
}
@@ -1152,7 +1156,7 @@ class ActivityStarter {
if (packageArchiver.isIntentResolvedToArchivedApp(intent, mRequest.userId)) {
err = packageArchiver
.requestUnarchiveOnActivityStart(
- intent, intentCallingPackage, mRequest.userId, realCallingUid);
+ intent, callingPackage, mRequest.userId, realCallingUid);
}
}
}
@@ -1211,7 +1215,7 @@ class ActivityStarter {
boolean abort;
try {
abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
- requestCode, callingPid, callingUid, intentCallingPackage, callingFeatureId,
+ requestCode, callingPid, callingUid, callingPackage, callingFeatureId,
request.ignoreTargetSecurity, inTask != null, callerApp, resultRecord,
resultRootTask);
} catch (SecurityException e) {
@@ -1239,7 +1243,7 @@ class ActivityStarter {
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
callingPid, resolvedType, aInfo.applicationInfo);
abort |= !mService.getPermissionPolicyInternal().checkStartActivity(intent, callingUid,
- intentCallingPackage);
+ callingPackage);
if (intentCreatorUid != Request.DEFAULT_INTENT_CREATOR_UID) {
try {
@@ -1247,36 +1251,29 @@ class ActivityStarter {
requestCode, 0, intentCreatorUid, intentCreatorPackage, "",
request.ignoreTargetSecurity, inTask != null, null, resultRecord,
resultRootTask)) {
- logForIntentRedirect("Creator checkStartAnyActivityPermission Caused abortion.",
+ abort = logAndAbortForIntentRedirect(
+ "Creator checkStartAnyActivityPermission Caused abortion.",
intent, intentCreatorUid, intentCreatorPackage, callingUid,
- intentCallingPackage);
- // TODO b/368559093 - set abort to true.
- // abort = true;
+ callingPackage);
}
} catch (SecurityException e) {
- logForIntentRedirect("Creator checkStartAnyActivityPermission Caused Exception.",
- intent, intentCreatorUid, intentCreatorPackage, callingUid,
- intentCallingPackage);
- // TODO b/368559093 - rethrow the exception.
- //throw e;
- }
- if (!mService.mIntentFirewall.checkStartActivity(intent, intentCreatorUid, 0,
- resolvedType, aInfo.applicationInfo)) {
- logForIntentRedirect("Creator IntentFirewall.checkStartActivity Caused abortion.",
- intent, intentCreatorUid, intentCreatorPackage, callingUid,
- intentCallingPackage);
- // TODO b/368559093 - set abort to true.
- // abort = true;
- }
-
- if (!mService.getPermissionPolicyInternal().checkStartActivity(intent, intentCreatorUid,
- intentCreatorPackage)) {
- logForIntentRedirect(
+ logAndThrowExceptionForIntentRedirect(
+ "Creator checkStartAnyActivityPermission Caused Exception.",
+ intent, intentCreatorUid, intentCreatorPackage, callingUid, callingPackage,
+ e);
+ }
+ if (!mService.mIntentFirewall.checkStartActivity(intent, intentCreatorUid,
+ 0, resolvedType, aInfo.applicationInfo)) {
+ abort = logAndAbortForIntentRedirect(
+ "Creator IntentFirewall.checkStartActivity Caused abortion.",
+ intent, intentCreatorUid, intentCreatorPackage, callingUid, callingPackage);
+ }
+
+ if (!mService.getPermissionPolicyInternal().checkStartActivity(intent,
+ intentCreatorUid, intentCreatorPackage)) {
+ abort = logAndAbortForIntentRedirect(
"Creator PermissionPolicyService.checkStartActivity Caused abortion.",
- intent, intentCreatorUid, intentCreatorPackage, callingUid,
- intentCallingPackage);
- // TODO b/368559093 - set abort to true.
- // abort = true;
+ intent, intentCreatorUid, intentCreatorPackage, callingUid, callingPackage);
}
intent.removeCreatorTokenInfo();
}
@@ -1296,7 +1293,7 @@ class ActivityStarter {
balController.checkBackgroundActivityStart(
callingUid,
callingPid,
- intentCallingPackage,
+ callingPackage,
realCallingUid,
realCallingPid,
callerApp,
@@ -1317,7 +1314,7 @@ class ActivityStarter {
if (request.allowPendingRemoteAnimationRegistryLookup) {
checkedOptions = mService.getActivityStartController()
.getPendingRemoteAnimationRegistry()
- .overrideOptionsIfNeeded(intentCallingPackage, checkedOptions);
+ .overrideOptionsIfNeeded(callingPackage, checkedOptions);
}
if (mService.mController != null) {
try {
@@ -1334,7 +1331,7 @@ class ActivityStarter {
final TaskDisplayArea suggestedLaunchDisplayArea =
computeSuggestedLaunchDisplayArea(inTask, sourceRecord, checkedOptions);
mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags,
- intentCallingPackage,
+ callingPackage,
callingFeatureId);
if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, inTaskFragment,
callingPid, callingUid, checkedOptions, suggestedLaunchDisplayArea)) {
@@ -1372,7 +1369,7 @@ class ActivityStarter {
if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
aInfo.packageName, userId)) {
final IIntentSender target = mService.getIntentSenderLocked(
- ActivityManager.INTENT_SENDER_ACTIVITY, intentCallingPackage,
+ ActivityManager.INTENT_SENDER_ACTIVITY, callingPackage,
callingFeatureId,
callingUid, userId, null, null, 0, new Intent[]{intent},
new String[]{resolvedType}, PendingIntent.FLAG_CANCEL_CURRENT
@@ -1436,7 +1433,7 @@ class ActivityStarter {
// app [on install success].
if (rInfo != null && rInfo.auxiliaryInfo != null) {
intent = createLaunchIntent(rInfo.auxiliaryInfo, request.ephemeralIntent,
- intentCallingPackage, callingFeatureId, verificationBundle, resolvedType,
+ callingPackage, callingFeatureId, verificationBundle, resolvedType,
userId);
resolvedType = null;
callingUid = realCallingUid;
@@ -1460,7 +1457,7 @@ class ActivityStarter {
.setCaller(callerApp)
.setLaunchedFromPid(callingPid)
.setLaunchedFromUid(callingUid)
- .setLaunchedFromPackage(intentCallingPackage)
+ .setLaunchedFromPackage(callingPackage)
.setLaunchedFromFeature(callingFeatureId)
.setIntent(intent)
.setResolvedType(resolvedType)
@@ -3588,16 +3585,32 @@ class ActivityStarter {
pw.println(mInTaskFragment);
}
- static void logForIntentRedirect(String message, Intent intent, int intentCreatorUid,
- String intentCreatorPackage, int callingUid, String callingPackage) {
+ static void logAndThrowExceptionForIntentRedirect(@NonNull String message,
+ @NonNull Intent intent, int intentCreatorUid, @Nullable String intentCreatorPackage,
+ int callingUid, @Nullable String callingPackage,
+ @Nullable SecurityException originalException) {
+ String msg = getIntentRedirectPreventedLogMessage(message, intent, intentCreatorUid,
+ intentCreatorPackage, callingUid, callingPackage);
+ Slog.wtf(TAG, msg);
+ if (preventIntentRedirectAbortOrThrowException() && CompatChanges.isChangeEnabled(
+ ENABLE_PREVENT_INTENT_REDIRECT_TAKE_ACTION, callingUid)) {
+ throw new SecurityException(msg, originalException);
+ }
+ }
+
+ private static boolean logAndAbortForIntentRedirect(@NonNull String message,
+ @NonNull Intent intent, int intentCreatorUid, @Nullable String intentCreatorPackage,
+ int callingUid, @Nullable String callingPackage) {
String msg = getIntentRedirectPreventedLogMessage(message, intent, intentCreatorUid,
intentCreatorPackage, callingUid, callingPackage);
Slog.wtf(TAG, msg);
+ return preventIntentRedirectAbortOrThrowException() && CompatChanges.isChangeEnabled(
+ ENABLE_PREVENT_INTENT_REDIRECT_TAKE_ACTION, callingUid);
}
- private static String getIntentRedirectPreventedLogMessage(String message, Intent intent,
- int intentCreatorUid, String intentCreatorPackage, int callingUid,
- String callingPackage) {
+ private static String getIntentRedirectPreventedLogMessage(@NonNull String message,
+ @NonNull Intent intent, int intentCreatorUid, @Nullable String intentCreatorPackage,
+ int callingUid, @Nullable String callingPackage) {
return "[IntentRedirect]" + message + " intentCreatorUid: " + intentCreatorUid
+ "; intentCreatorPackage: " + intentCreatorPackage + "; callingUid: " + callingUid
+ "; callingPackage: " + callingPackage + "; intent: " + intent;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 4f71719006f5..567eca2f639a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -2572,14 +2572,21 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
wpc.computeProcessActivityState();
}
- void computeProcessActivityStateBatch() {
+ boolean computeProcessActivityStateBatch() {
if (mActivityStateChangedProcs.isEmpty()) {
- return;
+ return false;
}
+ boolean changed = false;
for (int i = mActivityStateChangedProcs.size() - 1; i >= 0; i--) {
- mActivityStateChangedProcs.get(i).computeProcessActivityState();
+ final WindowProcessController wpc = mActivityStateChangedProcs.get(i);
+ final int prevState = wpc.getActivityStateFlags();
+ wpc.computeProcessActivityState();
+ if (!changed && prevState != wpc.getActivityStateFlags()) {
+ changed = true;
+ }
}
mActivityStateChangedProcs.clear();
+ return changed;
}
/**
diff --git a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java
index d59046f44129..f1dd41e7d74a 100644
--- a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java
+++ b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java
@@ -39,6 +39,7 @@ import static com.android.server.wm.AppCompatConfiguration.MIN_FIXED_ORIENTATION
import static com.android.server.wm.AppCompatUtils.isChangeEnabled;
import android.annotation.NonNull;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -126,18 +127,18 @@ class AppCompatAspectRatioOverrides {
return false;
}
- mUserAspectRatioState.mUserAspectRatio = getUserMinAspectRatioOverrideCode();
+ final int aspectRatio = getUserMinAspectRatioOverrideCode();
- return mUserAspectRatioState.mUserAspectRatio != USER_MIN_ASPECT_RATIO_UNSET
- && mUserAspectRatioState.mUserAspectRatio != USER_MIN_ASPECT_RATIO_APP_DEFAULT
- && mUserAspectRatioState.mUserAspectRatio != USER_MIN_ASPECT_RATIO_FULLSCREEN;
+ return aspectRatio != USER_MIN_ASPECT_RATIO_UNSET
+ && aspectRatio != USER_MIN_ASPECT_RATIO_APP_DEFAULT
+ && aspectRatio != USER_MIN_ASPECT_RATIO_FULLSCREEN;
}
boolean shouldApplyUserFullscreenOverride() {
if (isUserFullscreenOverrideEnabled()) {
- mUserAspectRatioState.mUserAspectRatio = getUserMinAspectRatioOverrideCode();
+ final int aspectRatio = getUserMinAspectRatioOverrideCode();
- return mUserAspectRatioState.mUserAspectRatio == USER_MIN_ASPECT_RATIO_FULLSCREEN;
+ return aspectRatio == USER_MIN_ASPECT_RATIO_FULLSCREEN;
}
return false;
@@ -153,10 +154,12 @@ class AppCompatAspectRatioOverrides {
}
boolean isSystemOverrideToFullscreenEnabled() {
+ final int aspectRatio = getUserMinAspectRatioOverrideCode();
+
return isChangeEnabled(mActivityRecord, OVERRIDE_ANY_ORIENTATION_TO_USER)
&& !mAllowOrientationOverrideOptProp.isFalse()
- && (mUserAspectRatioState.mUserAspectRatio == USER_MIN_ASPECT_RATIO_UNSET
- || mUserAspectRatioState.mUserAspectRatio == USER_MIN_ASPECT_RATIO_FULLSCREEN);
+ && (aspectRatio == USER_MIN_ASPECT_RATIO_UNSET
+ || aspectRatio == USER_MIN_ASPECT_RATIO_FULLSCREEN);
}
/**
@@ -173,12 +176,11 @@ class AppCompatAspectRatioOverrides {
}
boolean hasFullscreenOverride() {
- // `mUserAspectRatio` is always initialized first in `shouldApplyUserFullscreenOverride()`.
return shouldApplyUserFullscreenOverride() || isSystemOverrideToFullscreenEnabled();
}
float getUserMinAspectRatio() {
- switch (mUserAspectRatioState.mUserAspectRatio) {
+ switch (getUserMinAspectRatioOverrideCode()) {
case USER_MIN_ASPECT_RATIO_DISPLAY_SIZE:
return getDisplaySizeMinAspectRatio();
case USER_MIN_ASPECT_RATIO_SPLIT_SCREEN:
@@ -269,13 +271,7 @@ class AppCompatAspectRatioOverrides {
}
int getUserMinAspectRatioOverrideCode() {
- try {
- return mActivityRecord.mAtmService.getPackageManager()
- .getUserMinAspectRatio(mActivityRecord.packageName, mActivityRecord.mUserId);
- } catch (RemoteException e) {
- Slog.w(TAG, "Exception thrown retrieving aspect ratio user override " + this, e);
- }
- return mUserAspectRatioState.mUserAspectRatio;
+ return mUserAspectRatioState.getUserAspectRatio(mActivityRecord);
}
private float getDefaultMinAspectRatioForUnresizableApps() {
@@ -300,10 +296,30 @@ class AppCompatAspectRatioOverrides {
}
private static class UserAspectRatioState {
- // TODO(b/315140179): Make mUserAspectRatio final
- // The min aspect ratio override set by user
+ // The min aspect ratio override set by the user.
@PackageManager.UserMinAspectRatio
private int mUserAspectRatio = USER_MIN_ASPECT_RATIO_UNSET;
+ private boolean mHasBeenSet = false;
+
+ @PackageManager.UserMinAspectRatio
+ private int getUserAspectRatio(@NonNull ActivityRecord activityRecord) {
+ // Package manager can be null at construction time, so access should be on demand.
+ if (!mHasBeenSet) {
+ try {
+ final IPackageManager pm = activityRecord.mAtmService.getPackageManager();
+ if (pm != null) {
+ mUserAspectRatio = pm.getUserMinAspectRatio(activityRecord.packageName,
+ activityRecord.mUserId);
+ mHasBeenSet = true;
+ }
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Exception thrown retrieving aspect ratio user override "
+ + this, e);
+ }
+ }
+
+ return mUserAspectRatio;
+ }
}
private Resources getResources() {
diff --git a/services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java b/services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java
index f5d58eac1113..e3a9d672c17f 100644
--- a/services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java
+++ b/services/core/java/com/android/server/wm/AppCompatOrientationPolicy.java
@@ -56,11 +56,11 @@ class AppCompatOrientationPolicy {
final DisplayContent displayContent = mActivityRecord.mDisplayContent;
final boolean isIgnoreOrientationRequestEnabled = displayContent != null
&& displayContent.getIgnoreOrientationRequest();
- final boolean shouldApplyUserFullscreenOverride = mAppCompatOverrides
- .getAppCompatAspectRatioOverrides().shouldApplyUserFullscreenOverride();
+ final boolean hasFullscreenOverride = mAppCompatOverrides
+ .getAppCompatAspectRatioOverrides().hasFullscreenOverride();
final boolean shouldCameraCompatControlOrientation =
AppCompatCameraPolicy.shouldCameraCompatControlOrientation(mActivityRecord);
- if (shouldApplyUserFullscreenOverride && isIgnoreOrientationRequestEnabled
+ if (hasFullscreenOverride && isIgnoreOrientationRequestEnabled
// Do not override orientation to fullscreen for camera activities.
// Fixed-orientation activities are rarely tested in other orientations, and it
// often results in sideways or stretched previews. As the camera compat treatment
@@ -69,8 +69,7 @@ class AppCompatOrientationPolicy {
&& !shouldCameraCompatControlOrientation) {
Slog.v(TAG, "Requested orientation " + screenOrientationToString(candidate)
+ " for " + mActivityRecord + " is overridden to "
- + screenOrientationToString(SCREEN_ORIENTATION_USER)
- + " by user aspect ratio settings.");
+ + screenOrientationToString(SCREEN_ORIENTATION_USER));
return SCREEN_ORIENTATION_USER;
}
@@ -101,24 +100,6 @@ class AppCompatOrientationPolicy {
return candidate;
}
- // mUserAspectRatio is always initialized first in shouldApplyUserFullscreenOverride(),
- // which will always come first before this check as user override > device
- // manufacturer override.
- final boolean isSystemOverrideToFullscreenEnabled = mAppCompatOverrides
- .getAppCompatAspectRatioOverrides().isSystemOverrideToFullscreenEnabled();
- if (isSystemOverrideToFullscreenEnabled && isIgnoreOrientationRequestEnabled
- // Do not override orientation to fullscreen for camera activities.
- // Fixed-orientation activities are rarely tested in other orientations, and it
- // often results in sideways or stretched previews. As the camera compat treatment
- // targets fixed-orientation activities, overriding the orientation disables the
- // treatment.
- && !shouldCameraCompatControlOrientation) {
- Slog.v(TAG, "Requested orientation " + screenOrientationToString(candidate)
- + " for " + mActivityRecord + " is overridden to "
- + screenOrientationToString(SCREEN_ORIENTATION_USER));
- return SCREEN_ORIENTATION_USER;
- }
-
final AppCompatOrientationOverrides.OrientationOverridesState capabilityState =
mAppCompatOverrides.getAppCompatOrientationOverrides()
.mOrientationOverridesState;
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index ccd59969cec8..6cc4b1e6ede9 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -994,7 +994,9 @@ class BackNavigationController {
// Ensure the final animation targets which hidden by transition could be visible.
for (int i = 0; i < targets.size(); i++) {
final WindowContainer wc = targets.get(i).mContainer;
- wc.prepareSurfaces();
+ if (wc.mSurfaceControl != null) {
+ wc.prepareSurfaces();
+ }
}
// The pending builder could be cleared due to prepareSurfaces
@@ -1328,16 +1330,13 @@ class BackNavigationController {
if (!allWindowDrawn) {
return;
}
- final SurfaceControl startingSurface = mOpenAnimAdaptor.mStartingSurface;
- if (startingSurface != null && startingSurface.isValid()) {
- startTransaction.addTransactionCommittedListener(Runnable::run, () -> {
- synchronized (mWindowManagerService.mGlobalLock) {
- if (mOpenAnimAdaptor != null) {
- mOpenAnimAdaptor.cleanUpWindowlessSurface(true);
- }
+ startTransaction.addTransactionCommittedListener(Runnable::run, () -> {
+ synchronized (mWindowManagerService.mGlobalLock) {
+ if (mOpenAnimAdaptor != null) {
+ mOpenAnimAdaptor.cleanUpWindowlessSurface(true);
}
- });
- }
+ }
+ });
}
void clearBackAnimateTarget(boolean cancel) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 41a580438776..6707a27d83c8 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -105,6 +105,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.UserProperties;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.graphics.Region;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.power.Mode;
@@ -153,6 +154,7 @@ import com.android.server.pm.UserManagerInternal;
import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.utils.Slogf;
+import com.android.server.wm.utils.RegionUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -270,6 +272,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
private boolean mTaskLayersChanged = true;
private int mTmpTaskLayerRank;
private final RankTaskLayersRunnable mRankTaskLayersRunnable = new RankTaskLayersRunnable();
+ private Region mTmpOccludingRegion;
+ private Region mTmpTaskRegion;
private String mDestroyAllActivitiesReason;
private final Runnable mDestroyAllActivitiesRunnable = new Runnable() {
@@ -2921,6 +2925,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
});
}
+ void invalidateTaskLayersAndUpdateOomAdjIfNeeded() {
+ mRankTaskLayersRunnable.mCheckUpdateOomAdj = true;
+ invalidateTaskLayers();
+ }
+
void invalidateTaskLayers() {
if (!mTaskLayersChanged) {
mTaskLayersChanged = true;
@@ -2938,13 +2947,18 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
// Only rank for leaf tasks because the score of activity is based on immediate parent.
forAllLeafTasks(task -> {
final int oldRank = task.mLayerRank;
- final ActivityRecord r = task.topRunningActivityLocked();
- if (r != null && r.isVisibleRequested()) {
+ final int oldRatio = task.mNonOccludedFreeformAreaRatio;
+ task.mNonOccludedFreeformAreaRatio = 0;
+ if (task.isVisibleRequested()) {
task.mLayerRank = ++mTmpTaskLayerRank;
+ if (task.inFreeformWindowingMode()) {
+ computeNonOccludedFreeformAreaRatio(task);
+ }
} else {
task.mLayerRank = Task.LAYER_RANK_INVISIBLE;
}
- if (task.mLayerRank != oldRank) {
+ if (task.mLayerRank != oldRank
+ || task.mNonOccludedFreeformAreaRatio != oldRatio) {
task.forAllActivities(activity -> {
if (activity.hasProcess()) {
mTaskSupervisor.onProcessActivityStateChanged(activity.app,
@@ -2953,12 +2967,42 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
});
}
}, true /* traverseTopToBottom */);
-
+ if (mTmpOccludingRegion != null) {
+ mTmpOccludingRegion.setEmpty();
+ }
+ boolean changed = false;
if (!mTaskSupervisor.inActivityVisibilityUpdate()) {
- mTaskSupervisor.computeProcessActivityStateBatch();
+ changed = mTaskSupervisor.computeProcessActivityStateBatch();
+ }
+ if (mRankTaskLayersRunnable.mCheckUpdateOomAdj) {
+ mRankTaskLayersRunnable.mCheckUpdateOomAdj = false;
+ if (changed) {
+ mService.updateOomAdj();
+ }
}
}
+ /** This method is called for visible freeform task from top to bottom. */
+ private void computeNonOccludedFreeformAreaRatio(@NonNull Task task) {
+ if (!com.android.window.flags.Flags.processPriorityPolicyForMultiWindowMode()) {
+ return;
+ }
+ if (mTmpOccludingRegion == null) {
+ mTmpOccludingRegion = new Region();
+ mTmpTaskRegion = new Region();
+ }
+ final Rect taskBounds = task.getBounds();
+ mTmpTaskRegion.set(taskBounds);
+ // Exclude the area outside the display.
+ mTmpTaskRegion.op(task.mDisplayContent.getBounds(), Region.Op.INTERSECT);
+ // Exclude the area covered by the above tasks.
+ mTmpTaskRegion.op(mTmpOccludingRegion, Region.Op.DIFFERENCE);
+ task.mNonOccludedFreeformAreaRatio = 100 * RegionUtils.getAreaSize(mTmpTaskRegion)
+ / (taskBounds.width() * taskBounds.height());
+ // Accumulate the occluding region for other visible tasks behind.
+ mTmpOccludingRegion.op(taskBounds, Region.Op.UNION);
+ }
+
void clearOtherAppTimeTrackers(AppTimeTracker except) {
forAllActivities(r -> {
if (r.appTimeTracker != except) {
@@ -3862,6 +3906,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
}
private class RankTaskLayersRunnable implements Runnable {
+ boolean mCheckUpdateOomAdj;
+
@Override
public void run() {
synchronized (mService.mGlobalLock) {
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 4861341f830a..8a624b3945b6 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -432,6 +432,9 @@ class Task extends TaskFragment {
// This number will be assigned when we evaluate OOM scores for all visible tasks.
int mLayerRank = LAYER_RANK_INVISIBLE;
+ /** A 0~100 ratio to indicate the percentage of visible area on screen of a freeform task. */
+ int mNonOccludedFreeformAreaRatio;
+
/* Unique identifier for this task. */
final int mTaskId;
/* User for which this task was created. */
@@ -1207,6 +1210,28 @@ class Task extends TaskFragment {
}
@Override
+ void onResize() {
+ super.onResize();
+ updateTaskLayerForFreeform();
+ }
+
+ @Override
+ void onMovedByResize() {
+ super.onMovedByResize();
+ updateTaskLayerForFreeform();
+ }
+
+ private void updateTaskLayerForFreeform() {
+ if (!com.android.window.flags.Flags.processPriorityPolicyForMultiWindowMode()) {
+ return;
+ }
+ if (!isVisibleRequested() || !inFreeformWindowingMode()) {
+ return;
+ }
+ mRootWindowContainer.invalidateTaskLayersAndUpdateOomAdjIfNeeded();
+ }
+
+ @Override
@Nullable
ActivityRecord getTopResumedActivity() {
if (!isLeafTask()) {
@@ -3410,6 +3435,36 @@ class Task extends TaskFragment {
info.requestedVisibleTypes = (windowState != null && Flags.enableFullyImmersiveInDesktop())
? windowState.getRequestedVisibleTypes() : WindowInsets.Type.defaultVisible();
AppCompatUtils.fillAppCompatTaskInfo(this, info, top);
+ info.topActivityMainWindowFrame = calculateTopActivityMainWindowFrameForTaskInfo(top);
+ }
+
+ /**
+ * Returns the top activity's main window frame if it doesn't match
+ * {@link ActivityRecord#getBounds() the top activity bounds}, or {@code null}, otherwise.
+ *
+ * @param top The top running activity of the task
+ */
+ @Nullable
+ private static Rect calculateTopActivityMainWindowFrameForTaskInfo(
+ @Nullable ActivityRecord top) {
+ if (!Flags.betterSupportNonMatchParentActivity()) {
+ return null;
+ }
+ if (top == null) {
+ return null;
+ }
+ final WindowState mainWindow = top.findMainWindow();
+ if (mainWindow == null) {
+ return null;
+ }
+ if (!mainWindow.mHaveFrame) {
+ return null;
+ }
+ final Rect windowFrame = mainWindow.getFrame();
+ if (top.getBounds().equals(windowFrame)) {
+ return null;
+ }
+ return windowFrame;
}
/**
@@ -5919,6 +5974,10 @@ class Task extends TaskFragment {
pw.print(prefix); pw.print(" mLastNonFullscreenBounds=");
pw.println(mLastNonFullscreenBounds);
}
+ if (mNonOccludedFreeformAreaRatio != 0) {
+ pw.print(prefix); pw.print(" mNonOccludedFreeformAreaRatio=");
+ pw.println(mNonOccludedFreeformAreaRatio);
+ }
if (isLeafTask()) {
pw.println(prefix + " isSleeping=" + shouldSleepActivities());
printThisActivity(pw, getTopPausingActivity(), dumpPackage, false,
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 3ffeacfd5006..d6ba3123eb97 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -3027,7 +3027,11 @@ class TaskFragment extends WindowContainer<WindowContainer> {
// The task order may be changed by finishIfPossible() for adjusting focus if there are
// nested tasks, so add all activities into a list to avoid missed removals.
final ArrayList<ActivityRecord> removingActivities = new ArrayList<>();
- forAllActivities((Consumer<ActivityRecord>) removingActivities::add);
+ forAllActivities((r) -> {
+ if (!r.finishing) {
+ removingActivities.add(r);
+ }
+ });
for (int i = removingActivities.size() - 1; i >= 0; --i) {
final ActivityRecord r = removingActivities.get(i);
if (withTransition && r.isVisible()) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 1a107c24a16a..7f0c33657144 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -121,6 +121,11 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
*/
private static final int MAX_NUM_PERCEPTIBLE_FREEFORM =
SystemProperties.getInt("persist.wm.max_num_perceptible_freeform", 1);
+ /**
+ * If the visible area percentage of a resumed freeform task is greater than or equal to this
+ * ratio, its process will have a higher priority.
+ */
+ private static final int PERCEPTIBLE_FREEFORM_VISIBLE_RATIO = 90;
private static final int MAX_RAPID_ACTIVITY_LAUNCH_COUNT = 200;
private static final long RAPID_ACTIVITY_LAUNCH_MS = 500;
@@ -1234,6 +1239,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
boolean hasResumedFreeform = false;
int minTaskLayer = Integer.MAX_VALUE;
int stateFlags = 0;
+ int nonOccludedRatio = 0;
final boolean wasResumed = hasResumedActivity();
final boolean wasAnyVisible = (mActivityStateFlags
& (ACTIVITY_STATE_FLAG_IS_VISIBLE | ACTIVITY_STATE_FLAG_IS_WINDOW_VISIBLE)) != 0;
@@ -1261,6 +1267,8 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
stateFlags |= ACTIVITY_STATE_FLAG_RESUMED_SPLIT_SCREEN;
} else if (windowingMode == WINDOWING_MODE_FREEFORM) {
hasResumedFreeform = true;
+ nonOccludedRatio =
+ Math.max(task.mNonOccludedFreeformAreaRatio, nonOccludedRatio);
}
}
if (minTaskLayer > 0) {
@@ -1298,7 +1306,8 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
&& com.android.window.flags.Flags.processPriorityPolicyForMultiWindowMode()
// Exclude task layer 1 because it is already the top most.
&& minTaskLayer > 1) {
- if (minTaskLayer <= 1 + MAX_NUM_PERCEPTIBLE_FREEFORM) {
+ if (minTaskLayer <= 1 + MAX_NUM_PERCEPTIBLE_FREEFORM
+ || nonOccludedRatio >= PERCEPTIBLE_FREEFORM_VISIBLE_RATIO) {
stateFlags |= ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM;
} else {
stateFlags |= ACTIVITY_STATE_FLAG_VISIBLE_MULTI_WINDOW_MODE;
diff --git a/services/core/java/com/android/server/wm/utils/RegionUtils.java b/services/core/java/com/android/server/wm/utils/RegionUtils.java
index ce7776f270fd..ff23145fc6b9 100644
--- a/services/core/java/com/android/server/wm/utils/RegionUtils.java
+++ b/services/core/java/com/android/server/wm/utils/RegionUtils.java
@@ -81,4 +81,15 @@ public class RegionUtils {
Collections.reverse(rects);
rects.forEach(rectConsumer);
}
+
+ /** Returns the area size of the region. */
+ public static int getAreaSize(Region region) {
+ final RegionIterator regionIterator = new RegionIterator(region);
+ int area = 0;
+ final Rect rect = new Rect();
+ while (regionIterator.next(rect)) {
+ area += rect.width() * rect.height();
+ }
+ return area;
+ }
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0b7ce75136bb..2461c1ce3b0e 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -106,6 +106,7 @@ import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.os.ApplicationSharedMemory;
import com.android.internal.os.BinderInternal;
import com.android.internal.os.RuntimeInit;
+import com.android.internal.pm.RoSystemFeatures;
import com.android.internal.policy.AttributeCache;
import com.android.internal.protolog.ProtoLog;
import com.android.internal.protolog.ProtoLogConfigurationServiceImpl;
@@ -1495,8 +1496,7 @@ public final class SystemServer implements Dumpable {
boolean disableCameraService = SystemProperties.getBoolean("config.disable_cameraservice",
false);
- boolean isWatch = context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_WATCH);
+ boolean isWatch = RoSystemFeatures.hasFeatureWatch(context);
boolean isArc = context.getPackageManager().hasSystemFeature(
"org.chromium.arc");
@@ -1504,6 +1504,8 @@ public final class SystemServer implements Dumpable {
boolean isTv = context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_LEANBACK);
+ boolean isAutomotive = RoSystemFeatures.hasFeatureAutomotive(context);
+
boolean enableVrService = context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_VR_MODE_HIGH_PERFORMANCE);
@@ -1760,7 +1762,8 @@ public final class SystemServer implements Dumpable {
t.traceEnd();
}
- if (android.security.Flags.aapmApi()) {
+ if (!isWatch && !isTv && !isAutomotive
+ && android.security.Flags.aapmApi()) {
t.traceBegin("StartAdvancedProtectionService");
mSystemServiceManager.startService(AdvancedProtectionService.Lifecycle.class);
t.traceEnd();
@@ -2758,7 +2761,7 @@ public final class SystemServer implements Dumpable {
t.traceEnd();
}
- if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_EMBEDDED)) {
+ if (RoSystemFeatures.hasFeatureEmbedded(context)) {
t.traceBegin("StartIoTSystemService");
mSystemServiceManager.startService(IOT_SERVICE_CLASS);
t.traceEnd();
@@ -3137,8 +3140,6 @@ public final class SystemServer implements Dumpable {
}, WEBVIEW_PREPARATION);
}
- boolean isAutomotive = mPackageManager
- .hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
if (isAutomotive) {
t.traceBegin("StartCarServiceHelperService");
final SystemService cshs = mSystemServiceManager
diff --git a/services/tests/PackageManagerServiceTests/appenumeration/Android.bp b/services/tests/PackageManagerServiceTests/appenumeration/Android.bp
index f15e533fee2b..2f00a1bb3c8c 100644
--- a/services/tests/PackageManagerServiceTests/appenumeration/Android.bp
+++ b/services/tests/PackageManagerServiceTests/appenumeration/Android.bp
@@ -32,6 +32,7 @@ android_test {
"androidx.test.runner",
"truth",
"Harrier",
+ "bedstead-multiuser",
],
platform_apis: true,
certificate: "platform",
diff --git a/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java
index 70a2d4847ce7..48cebd7dcb04 100644
--- a/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java
+++ b/services/tests/PackageManagerServiceTests/appenumeration/src/com/android/server/pm/test/appenumeration/CrossUserPackageVisibilityTests.java
@@ -22,6 +22,7 @@ import static android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS;
import static android.Manifest.permission.MOVE_PACKAGE;
import static android.content.pm.PackageManager.MOVE_FAILED_DOESNT_EXIST;
+import static com.android.bedstead.multiuser.MultiUserDeviceStateExtensionsKt.secondaryUser;
import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
import static com.google.common.truth.Truth.assertThat;
@@ -112,9 +113,9 @@ public class CrossUserPackageVisibilityTests {
final UserReference primaryUser = sDeviceState.primaryUser();
if (primaryUser.id() == UserHandle.myUserId()) {
mCurrentUser = primaryUser;
- mOtherUser = sDeviceState.secondaryUser();
+ mOtherUser = secondaryUser(sDeviceState);
} else {
- mCurrentUser = sDeviceState.secondaryUser();
+ mCurrentUser = secondaryUser(sDeviceState);
mOtherUser = primaryUser;
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
index fdf6b809fa85..9189c2f20d66 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -2224,6 +2224,8 @@ public final class DisplayPowerControllerTest {
verify(mHolder.animator).animateTo(eq(DEFAULT_DOZE_BRIGHTNESS),
/* linearSecondTarget= */ anyFloat(), eq(BRIGHTNESS_RAMP_RATE_FAST_INCREASE),
eq(false));
+ // This brightness shouldn't be stored in the setting
+ verify(mHolder.brightnessSetting, never()).setBrightness(DEFAULT_DOZE_BRIGHTNESS);
// The display device changes and the default doze brightness changes
setUpDisplay(DISPLAY_ID, "new_unique_id", mHolder.display, mock(DisplayDevice.class),
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index 5c718d982476..b2fe138e3342 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -1726,6 +1726,8 @@ public class QuotaControllerTest {
}
// Top-started job
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS);
+ // Top-stared jobs are out of quota enforcement.
setProcessState(ActivityManager.PROCESS_STATE_TOP);
synchronized (mQuotaController.mLock) {
trackJobs(job, jobDefIWF, jobHigh);
@@ -1755,6 +1757,38 @@ public class QuotaControllerTest {
assertEquals(timeUntilQuotaConsumedMs,
mQuotaController.getMaxJobExecutionTimeMsLocked(jobHigh));
}
+
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS);
+ // Quota is enforced for top-started job after the process leaves TOP/BTOP state.
+ setProcessState(ActivityManager.PROCESS_STATE_TOP);
+ synchronized (mQuotaController.mLock) {
+ trackJobs(job, jobDefIWF, jobHigh);
+ mQuotaController.prepareForExecutionLocked(job);
+ mQuotaController.prepareForExecutionLocked(jobDefIWF);
+ mQuotaController.prepareForExecutionLocked(jobHigh);
+ }
+ setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+ synchronized (mQuotaController.mLock) {
+ assertEquals(timeUntilQuotaConsumedMs,
+ mQuotaController.getMaxJobExecutionTimeMsLocked((job)));
+ assertEquals(timeUntilQuotaConsumedMs,
+ mQuotaController.getMaxJobExecutionTimeMsLocked((jobDefIWF)));
+ assertEquals(timeUntilQuotaConsumedMs,
+ mQuotaController.getMaxJobExecutionTimeMsLocked((jobHigh)));
+ mQuotaController.maybeStopTrackingJobLocked(job, null);
+ mQuotaController.maybeStopTrackingJobLocked(jobDefIWF, null);
+ mQuotaController.maybeStopTrackingJobLocked(jobHigh, null);
+ }
+
+ setProcessState(ActivityManager.PROCESS_STATE_RECEIVER);
+ synchronized (mQuotaController.mLock) {
+ assertEquals(timeUntilQuotaConsumedMs,
+ mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+ assertEquals(timeUntilQuotaConsumedMs,
+ mQuotaController.getMaxJobExecutionTimeMsLocked(jobDefIWF));
+ assertEquals(timeUntilQuotaConsumedMs,
+ mQuotaController.getMaxJobExecutionTimeMsLocked(jobHigh));
+ }
}
@Test
@@ -1824,6 +1858,7 @@ public class QuotaControllerTest {
mQuotaController.getMaxJobExecutionTimeMsLocked(job));
}
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS);
// Top-started job
setProcessState(ActivityManager.PROCESS_STATE_TOP);
synchronized (mQuotaController.mLock) {
@@ -1831,6 +1866,7 @@ public class QuotaControllerTest {
}
setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
synchronized (mQuotaController.mLock) {
+ // Top-started job is out of quota enforcement.
assertEquals(mQcConstants.EJ_LIMIT_ACTIVE_MS / 2,
mQuotaController.getMaxJobExecutionTimeMsLocked(job));
mQuotaController.maybeStopTrackingJobLocked(job, null);
@@ -1842,6 +1878,28 @@ public class QuotaControllerTest {
mQuotaController.getMaxJobExecutionTimeMsLocked(job));
}
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS);
+ // Top-started job
+ setProcessState(ActivityManager.PROCESS_STATE_TOP);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(job);
+ }
+ setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+ synchronized (mQuotaController.mLock) {
+ // Top-started job is enforced by quota policy after the app leaves the TOP state.
+ // The max execution time should be the total EJ session limit of the RARE bucket
+ // minus the time has been used.
+ assertEquals(mQcConstants.EJ_LIMIT_RARE_MS - timeUsedMs,
+ mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+ mQuotaController.maybeStopTrackingJobLocked(job, null);
+ }
+
+ setProcessState(ActivityManager.PROCESS_STATE_RECEIVER);
+ synchronized (mQuotaController.mLock) {
+ assertEquals(mQcConstants.EJ_LIMIT_RARE_MS - timeUsedMs,
+ mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+ }
+
// Test used quota rolling out of window.
synchronized (mQuotaController.mLock) {
mQuotaController.clearAppStatsLocked(SOURCE_USER_ID, SOURCE_PACKAGE);
@@ -1856,6 +1914,7 @@ public class QuotaControllerTest {
mQuotaController.getMaxJobExecutionTimeMsLocked(job));
}
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS);
// Top-started job
setProcessState(ActivityManager.PROCESS_STATE_TOP);
synchronized (mQuotaController.mLock) {
@@ -1864,6 +1923,7 @@ public class QuotaControllerTest {
}
setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
synchronized (mQuotaController.mLock) {
+ // Top-started job is out of quota enforcement.
assertEquals(mQcConstants.EJ_LIMIT_ACTIVE_MS / 2,
mQuotaController.getMaxJobExecutionTimeMsLocked(job));
mQuotaController.maybeStopTrackingJobLocked(job, null);
@@ -1874,6 +1934,28 @@ public class QuotaControllerTest {
assertEquals(mQcConstants.EJ_LIMIT_RARE_MS,
mQuotaController.getMaxJobExecutionTimeMsLocked(job));
}
+
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS);
+ // Top-started job
+ setProcessState(ActivityManager.PROCESS_STATE_TOP);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStartTrackingJobLocked(job, null);
+ mQuotaController.prepareForExecutionLocked(job);
+ }
+ setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+ synchronized (mQuotaController.mLock) {
+ // Top-started job is enforced by quota policy after the app leaves the TOP state.
+ // The max execution time should be the total EJ session limit of the RARE bucket.
+ assertEquals(mQcConstants.EJ_LIMIT_RARE_MS,
+ mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+ mQuotaController.maybeStopTrackingJobLocked(job, null);
+ }
+
+ setProcessState(ActivityManager.PROCESS_STATE_RECEIVER);
+ synchronized (mQuotaController.mLock) {
+ assertEquals(mQcConstants.EJ_LIMIT_RARE_MS,
+ mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+ }
}
@Test
@@ -1902,6 +1984,7 @@ public class QuotaControllerTest {
mQuotaController.getMaxJobExecutionTimeMsLocked(job));
}
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS);
// Top-started job
setProcessState(ActivityManager.PROCESS_STATE_TOP);
synchronized (mQuotaController.mLock) {
@@ -1909,6 +1992,7 @@ public class QuotaControllerTest {
}
setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
synchronized (mQuotaController.mLock) {
+ // Top-started job is out of quota enforcement.
assertEquals(mQcConstants.EJ_LIMIT_ACTIVE_MS / 2,
mQuotaController.getMaxJobExecutionTimeMsLocked(job));
mQuotaController.maybeStopTrackingJobLocked(job, null);
@@ -1920,6 +2004,27 @@ public class QuotaControllerTest {
mQuotaController.getMaxJobExecutionTimeMsLocked(job));
}
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS);
+ // Top-started job
+ setProcessState(ActivityManager.PROCESS_STATE_TOP);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(job);
+ }
+ setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+ synchronized (mQuotaController.mLock) {
+ // Top-started job is enforced by quota policy after the app leaves the TOP state.
+ // The max execution time should be the total EJ session limit of the RARE bucket.
+ assertEquals(mQcConstants.EJ_LIMIT_RARE_MS - timeUsedMs,
+ mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+ mQuotaController.maybeStopTrackingJobLocked(job, null);
+ }
+
+ setProcessState(ActivityManager.PROCESS_STATE_RECEIVER);
+ synchronized (mQuotaController.mLock) {
+ assertEquals(mQcConstants.EJ_LIMIT_RARE_MS - timeUsedMs,
+ mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+ }
+
// Test used quota rolling out of window.
synchronized (mQuotaController.mLock) {
mQuotaController.clearAppStatsLocked(SOURCE_USER_ID, SOURCE_PACKAGE);
@@ -1935,6 +2040,7 @@ public class QuotaControllerTest {
mQuotaController.getMaxJobExecutionTimeMsLocked(job));
}
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS);
// Top-started job
setProcessState(ActivityManager.PROCESS_STATE_TOP);
synchronized (mQuotaController.mLock) {
@@ -1943,6 +2049,7 @@ public class QuotaControllerTest {
}
setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
synchronized (mQuotaController.mLock) {
+ // Top-started job is out of quota enforcement.
assertEquals(mQcConstants.EJ_LIMIT_ACTIVE_MS / 2,
mQuotaController.getMaxJobExecutionTimeMsLocked(job));
mQuotaController.maybeStopTrackingJobLocked(job, null);
@@ -1953,6 +2060,28 @@ public class QuotaControllerTest {
assertEquals(mQcConstants.EJ_LIMIT_RARE_MS,
mQuotaController.getMaxJobExecutionTimeMsLocked(job));
}
+
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS);
+ // Top-started job
+ setProcessState(ActivityManager.PROCESS_STATE_TOP);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStartTrackingJobLocked(job, null);
+ mQuotaController.prepareForExecutionLocked(job);
+ }
+ setProcessState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+ synchronized (mQuotaController.mLock) {
+ // Top-started job is enforced by quota policy after the app leaves the TOP state.
+ // The max execution time should be the total EJ session limit of the RARE bucket.
+ assertEquals(mQcConstants.EJ_LIMIT_RARE_MS,
+ mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+ mQuotaController.maybeStopTrackingJobLocked(job, null);
+ }
+
+ setProcessState(ActivityManager.PROCESS_STATE_RECEIVER);
+ synchronized (mQuotaController.mLock) {
+ assertEquals(mQcConstants.EJ_LIMIT_RARE_MS,
+ mQuotaController.getMaxJobExecutionTimeMsLocked(job));
+ }
}
/**
@@ -4608,6 +4737,7 @@ public class QuotaControllerTest {
assertEquals(expected, mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
advanceElapsedClock(SECOND_IN_MILLIS);
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS);
// Bg job starts while inactive, spans an entire active session, and ends after the
// active session.
@@ -4686,8 +4816,66 @@ public class QuotaControllerTest {
mQuotaController.maybeStopTrackingJobLocked(jobBg2, null);
mQuotaController.maybeStopTrackingJobLocked(jobFg1, null);
}
+ // jobBg2 and jobFg1 are counted, jobTop is not counted.
expected.add(createTimingSession(start, 20 * SECOND_IN_MILLIS, 2));
assertEquals(expected, mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ advanceElapsedClock(SECOND_IN_MILLIS);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS);
+
+ // Bg job 1 starts, then top job starts. Bg job 1 job ends. Then app goes to
+ // foreground_service and a new job starts. Shortly after, uid goes
+ // "inactive" and then bg job 2 starts. Then top job ends, followed by bg and fg jobs.
+ // This should result in two TimingSessions:
+ // * The first should have a count of 1
+ // * The second should have a count of 2, which accounts for the bg2 and fg and top jobs.
+ // Top started jobs are not quota free any more if the process leaves TOP/BTOP state.
+ start = JobSchedulerService.sElapsedRealtimeClock.millis();
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStartTrackingJobLocked(jobBg1, null);
+ mQuotaController.maybeStartTrackingJobLocked(jobBg2, null);
+ mQuotaController.maybeStartTrackingJobLocked(jobFg1, null);
+ mQuotaController.maybeStartTrackingJobLocked(jobTop, null);
+ }
+ setProcessState(ActivityManager.PROCESS_STATE_LAST_ACTIVITY);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(jobBg1);
+ }
+ advanceElapsedClock(10 * SECOND_IN_MILLIS);
+ expected.add(createTimingSession(start, 10 * SECOND_IN_MILLIS, 1));
+ setProcessState(ActivityManager.PROCESS_STATE_TOP);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(jobTop);
+ }
+ advanceElapsedClock(10 * SECOND_IN_MILLIS);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStopTrackingJobLocked(jobBg1, jobBg1);
+ }
+ advanceElapsedClock(5 * SECOND_IN_MILLIS);
+ setProcessState(getProcessStateQuotaFreeThreshold());
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(jobFg1);
+ }
+ advanceElapsedClock(5 * SECOND_IN_MILLIS);
+ setProcessState(ActivityManager.PROCESS_STATE_TOP);
+ advanceElapsedClock(10 * SECOND_IN_MILLIS); // UID "inactive" now
+ start = JobSchedulerService.sElapsedRealtimeClock.millis();
+ setProcessState(ActivityManager.PROCESS_STATE_TOP_SLEEPING);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(jobBg2);
+ }
+ advanceElapsedClock(10 * SECOND_IN_MILLIS);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStopTrackingJobLocked(jobTop, null);
+ }
+ advanceElapsedClock(10 * SECOND_IN_MILLIS);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStopTrackingJobLocked(jobBg2, null);
+ mQuotaController.maybeStopTrackingJobLocked(jobFg1, null);
+ }
+ // jobBg2, jobFg1 and jobTop are counted.
+ expected.add(createTimingSession(start, 20 * SECOND_IN_MILLIS, 3));
+ assertEquals(expected, mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
}
/**
@@ -4807,7 +4995,8 @@ public class QuotaControllerTest {
* Tests that TOP jobs aren't stopped when an app runs out of quota.
*/
@Test
- public void testTracking_OutOfQuota_ForegroundAndBackground() {
+ @DisableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS)
+ public void testTracking_OutOfQuota_ForegroundAndBackground_DisableTopStartedJobsThrottling() {
setDischarging();
JobStatus jobBg = createJobStatus("testTracking_OutOfQuota_ForegroundAndBackground", 1);
@@ -4851,6 +5040,7 @@ public class QuotaControllerTest {
// Go to a background state.
setProcessState(ActivityManager.PROCESS_STATE_TOP_SLEEPING);
advanceElapsedClock(remainingTimeMs / 2 + 1);
+ // Only Bg job will be changed from in-quota to out-of-quota.
inOrder.verify(mJobSchedulerService,
timeout(remainingTimeMs / 2 + 2 * SECOND_IN_MILLIS).times(1))
.onControllerStateChanged(argThat(jobs -> jobs.size() == 1));
@@ -4897,6 +5087,105 @@ public class QuotaControllerTest {
}
/**
+ * Tests that TOP jobs are stopped when an app runs out of quota.
+ */
+ @Test
+ @EnableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS)
+ public void testTracking_OutOfQuota_ForegroundAndBackground_EnableTopStartedJobsThrottling() {
+ setDischarging();
+
+ JobStatus jobBg = createJobStatus("testTracking_OutOfQuota_ForegroundAndBackground", 1);
+ JobStatus jobTop = createJobStatus("testTracking_OutOfQuota_ForegroundAndBackground", 2);
+ trackJobs(jobBg, jobTop);
+ setStandbyBucket(WORKING_INDEX, jobTop, jobBg); // 2 hour window
+ // Now the package only has 20 seconds to run.
+ final long remainingTimeMs = 20 * SECOND_IN_MILLIS;
+ mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
+ createTimingSession(
+ JobSchedulerService.sElapsedRealtimeClock.millis() - HOUR_IN_MILLIS,
+ 10 * MINUTE_IN_MILLIS - remainingTimeMs, 1), false);
+
+ InOrder inOrder = inOrder(mJobSchedulerService);
+
+ // UID starts out inactive.
+ setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
+ // Start the job.
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(jobBg);
+ }
+ advanceElapsedClock(remainingTimeMs / 2);
+ // New job starts after UID is in the foreground. Since the app is now in the foreground, it
+ // should continue to have remainingTimeMs / 2 time remaining.
+ setProcessState(ActivityManager.PROCESS_STATE_TOP);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(jobTop);
+ }
+ advanceElapsedClock(remainingTimeMs);
+
+ // Wait for some extra time to allow for job processing.
+ inOrder.verify(mJobSchedulerService,
+ timeout(remainingTimeMs + 2 * SECOND_IN_MILLIS).times(0))
+ .onControllerStateChanged(argThat(jobs -> jobs.size() > 0));
+ synchronized (mQuotaController.mLock) {
+ assertEquals(remainingTimeMs / 2,
+ mQuotaController.getRemainingExecutionTimeLocked(jobBg));
+ assertEquals(remainingTimeMs / 2,
+ mQuotaController.getRemainingExecutionTimeLocked(jobTop));
+ }
+ // Go to a background state.
+ setProcessState(ActivityManager.PROCESS_STATE_TOP_SLEEPING);
+ advanceElapsedClock(remainingTimeMs / 2 + 1);
+ // Both Bg and Top jobs should be changed from in-quota to out-of-quota
+ inOrder.verify(mJobSchedulerService,
+ timeout(remainingTimeMs / 2 + 2 * SECOND_IN_MILLIS).times(1))
+ .onControllerStateChanged(argThat(jobs -> jobs.size() == 2));
+ // Top job should NOT be allowed to run.
+ assertFalse(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+ assertFalse(jobTop.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+
+ // New jobs to run.
+ JobStatus jobBg2 = createJobStatus("testTracking_OutOfQuota_ForegroundAndBackground", 3);
+ JobStatus jobTop2 = createJobStatus("testTracking_OutOfQuota_ForegroundAndBackground", 4);
+ JobStatus jobFg = createJobStatus("testTracking_OutOfQuota_ForegroundAndBackground", 5);
+ setStandbyBucket(WORKING_INDEX, jobBg2, jobTop2, jobFg);
+
+ advanceElapsedClock(20 * SECOND_IN_MILLIS);
+ setProcessState(ActivityManager.PROCESS_STATE_TOP);
+ // Both Bg and Top jobs should be changed from out-of-quota to in-quota.
+ inOrder.verify(mJobSchedulerService, timeout(SECOND_IN_MILLIS).times(1))
+ .onControllerStateChanged(argThat(jobs -> jobs.size() == 2));
+ trackJobs(jobFg, jobTop);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(jobTop);
+ }
+ assertTrue(jobTop.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+ assertTrue(jobFg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+ assertTrue(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+
+ // App still in foreground so everything should be in quota.
+ advanceElapsedClock(20 * SECOND_IN_MILLIS);
+ setProcessState(getProcessStateQuotaFreeThreshold());
+ assertTrue(jobTop.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+ assertTrue(jobFg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+ assertTrue(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+
+ advanceElapsedClock(20 * SECOND_IN_MILLIS);
+ // App is in background so everything should be out of quota.
+ setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
+ // Bg, Fg and Top jobs should be changed from in-quota to out-of-quota.
+ inOrder.verify(mJobSchedulerService, timeout(SECOND_IN_MILLIS).times(1))
+ .onControllerStateChanged(argThat(jobs -> jobs.size() == 3));
+ // App is now in background and out of quota. Fg should now change to out of quota
+ // since it wasn't started. Top should now changed to out of quota even it started
+ // when the app was in TOP.
+ assertFalse(jobTop.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+ assertFalse(jobFg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+ assertFalse(jobBg.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+ trackJobs(jobBg2);
+ assertFalse(jobBg2.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+ }
+
+ /**
* Tests that a job is properly updated and JobSchedulerService is notified when a job reaches
* its quota.
*/
@@ -6280,6 +6569,7 @@ public class QuotaControllerTest {
mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
advanceElapsedClock(SECOND_IN_MILLIS);
+ mSetFlagsRule.disableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS);
// Bg job 1 starts, then top job starts. Bg job 1 job ends. Then app goes to
// foreground_service and a new job starts. Shortly after, uid goes
@@ -6333,6 +6623,63 @@ public class QuotaControllerTest {
expected.add(createTimingSession(start, 20 * SECOND_IN_MILLIS, 2));
assertEquals(expected,
mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
+
+ advanceElapsedClock(SECOND_IN_MILLIS);
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS);
+
+ // Bg job 1 starts, then top job starts. Bg job 1 job ends. Then app goes to
+ // foreground_service and a new job starts. Shortly after, uid goes
+ // "inactive" and then bg job 2 starts. Then top job ends, followed by bg and fg jobs.
+ // This should result in two TimingSessions:
+ // * The first should have a count of 1
+ // * The second should have a count of 3, which accounts for the bg2, fg and top jobs.
+ // Top started jobs are not quota free any more if the process leaves TOP/BTOP state.
+ start = JobSchedulerService.sElapsedRealtimeClock.millis();
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStartTrackingJobLocked(jobBg1, null);
+ mQuotaController.maybeStartTrackingJobLocked(jobBg2, null);
+ mQuotaController.maybeStartTrackingJobLocked(jobFg1, null);
+ mQuotaController.maybeStartTrackingJobLocked(jobTop, null);
+ }
+ setProcessState(ActivityManager.PROCESS_STATE_LAST_ACTIVITY);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(jobBg1);
+ }
+ advanceElapsedClock(10 * SECOND_IN_MILLIS);
+ expected.add(createTimingSession(start, 10 * SECOND_IN_MILLIS, 1));
+ setProcessState(ActivityManager.PROCESS_STATE_TOP);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(jobTop);
+ }
+ advanceElapsedClock(10 * SECOND_IN_MILLIS);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStopTrackingJobLocked(jobBg1, jobBg1);
+ }
+ advanceElapsedClock(5 * SECOND_IN_MILLIS);
+ setProcessState(getProcessStateQuotaFreeThreshold());
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(jobFg1);
+ }
+ advanceElapsedClock(5 * SECOND_IN_MILLIS);
+ setProcessState(ActivityManager.PROCESS_STATE_TOP);
+ advanceElapsedClock(10 * SECOND_IN_MILLIS); // UID "inactive" now
+ start = JobSchedulerService.sElapsedRealtimeClock.millis();
+ setProcessState(ActivityManager.PROCESS_STATE_TOP_SLEEPING);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(jobBg2);
+ }
+ advanceElapsedClock(10 * SECOND_IN_MILLIS);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStopTrackingJobLocked(jobTop, null);
+ }
+ advanceElapsedClock(10 * SECOND_IN_MILLIS);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.maybeStopTrackingJobLocked(jobBg2, null);
+ mQuotaController.maybeStopTrackingJobLocked(jobFg1, null);
+ }
+ expected.add(createTimingSession(start, 20 * SECOND_IN_MILLIS, 3));
+ assertEquals(expected,
+ mQuotaController.getEJTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
}
/**
@@ -6701,7 +7048,8 @@ public class QuotaControllerTest {
* Tests that expedited jobs aren't stopped when an app runs out of quota.
*/
@Test
- public void testEJTracking_OutOfQuota_ForegroundAndBackground() {
+ @DisableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS)
+ public void testEJTracking_OutOfQuota_ForegroundAndBackground_DisableTopStartedJobsThrottling() {
setDischarging();
setDeviceConfigLong(QcConstants.KEY_EJ_GRACE_PERIOD_TOP_APP_MS, 0);
@@ -6813,6 +7161,129 @@ public class QuotaControllerTest {
}
/**
+ * Tests that expedited jobs are stopped when an app runs out of quota.
+ */
+ @Test
+ @EnableFlags(Flags.FLAG_ENFORCE_QUOTA_POLICY_TO_TOP_STARTED_JOBS)
+ public void testEJTracking_OutOfQuota_ForegroundAndBackground_EnableTopStartedJobsThrottling() {
+ setDischarging();
+ setDeviceConfigLong(QcConstants.KEY_EJ_GRACE_PERIOD_TOP_APP_MS, 0);
+
+ JobStatus jobBg =
+ createExpeditedJobStatus("testEJTracking_OutOfQuota_ForegroundAndBackground", 1);
+ JobStatus jobTop =
+ createExpeditedJobStatus("testEJTracking_OutOfQuota_ForegroundAndBackground", 2);
+ JobStatus jobUnstarted =
+ createExpeditedJobStatus("testEJTracking_OutOfQuota_ForegroundAndBackground", 3);
+ trackJobs(jobBg, jobTop, jobUnstarted);
+ setStandbyBucket(WORKING_INDEX, jobTop, jobBg, jobUnstarted);
+ // Now the package only has 20 seconds to run.
+ final long remainingTimeMs = 20 * SECOND_IN_MILLIS;
+ mQuotaController.saveTimingSession(SOURCE_USER_ID, SOURCE_PACKAGE,
+ createTimingSession(
+ JobSchedulerService.sElapsedRealtimeClock.millis() - HOUR_IN_MILLIS,
+ mQcConstants.EJ_LIMIT_WORKING_MS - remainingTimeMs, 1), true);
+
+ InOrder inOrder = inOrder(mJobSchedulerService);
+
+ // UID starts out inactive.
+ setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
+ // Start the job.
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(jobBg);
+ }
+ advanceElapsedClock(remainingTimeMs / 2);
+ // New job starts after UID is in the foreground. Since the app is now in the foreground, it
+ // should continue to have remainingTimeMs / 2 time remaining.
+ setProcessState(ActivityManager.PROCESS_STATE_TOP);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(jobTop);
+ }
+ advanceElapsedClock(remainingTimeMs);
+
+ // Wait for some extra time to allow for job processing.
+ inOrder.verify(mJobSchedulerService,
+ timeout(remainingTimeMs + 2 * SECOND_IN_MILLIS).times(0))
+ .onControllerStateChanged(argThat(jobs -> jobs.size() > 0));
+ synchronized (mQuotaController.mLock) {
+ assertEquals(remainingTimeMs / 2,
+ mQuotaController.getRemainingEJExecutionTimeLocked(
+ SOURCE_USER_ID, SOURCE_PACKAGE));
+ }
+ // Go to a background state.
+ setProcessState(ActivityManager.PROCESS_STATE_TOP_SLEEPING);
+ advanceElapsedClock(remainingTimeMs / 2 + 1);
+ // Bg, Top and jobUnstarted should be changed from in-quota to out-of-quota.
+ inOrder.verify(mJobSchedulerService,
+ timeout(remainingTimeMs / 2 + 2 * SECOND_IN_MILLIS).times(1))
+ .onControllerStateChanged(argThat(jobs -> jobs.size() == 3));
+ // Top should still NOT be "in quota" even it started before the app
+ // ran on top out of quota.
+ assertFalse(jobBg.isExpeditedQuotaApproved());
+ assertFalse(jobTop.isExpeditedQuotaApproved());
+ assertFalse(jobUnstarted.isExpeditedQuotaApproved());
+ synchronized (mQuotaController.mLock) {
+ assertTrue(
+ 0 >= mQuotaController
+ .getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+ }
+
+ // New jobs to run.
+ JobStatus jobBg2 =
+ createExpeditedJobStatus("testEJTracking_OutOfQuota_ForegroundAndBackground", 4);
+ JobStatus jobTop2 =
+ createExpeditedJobStatus("testEJTracking_OutOfQuota_ForegroundAndBackground", 5);
+ JobStatus jobFg =
+ createExpeditedJobStatus("testEJTracking_OutOfQuota_ForegroundAndBackground", 6);
+ setStandbyBucket(WORKING_INDEX, jobBg2, jobTop2, jobFg);
+
+ advanceElapsedClock(20 * SECOND_IN_MILLIS);
+ setProcessState(ActivityManager.PROCESS_STATE_TOP);
+ // Confirm QC recognizes that jobUnstarted has changed from out-of-quota to in-quota.
+ // jobBg, jobFg and jobUnstarted are changed from out-of-quota to in-quota.
+ inOrder.verify(mJobSchedulerService, timeout(SECOND_IN_MILLIS).times(1))
+ .onControllerStateChanged(argThat(jobs -> jobs.size() == 3));
+ trackJobs(jobTop2, jobFg);
+ synchronized (mQuotaController.mLock) {
+ mQuotaController.prepareForExecutionLocked(jobTop2);
+ }
+ assertTrue(jobTop.isExpeditedQuotaApproved());
+ assertTrue(jobTop2.isExpeditedQuotaApproved());
+ assertTrue(jobFg.isExpeditedQuotaApproved());
+ assertTrue(jobBg.isExpeditedQuotaApproved());
+ assertTrue(jobUnstarted.isExpeditedQuotaApproved());
+
+ // App still in foreground so everything should be in quota.
+ advanceElapsedClock(20 * SECOND_IN_MILLIS);
+ setProcessState(getProcessStateQuotaFreeThreshold());
+ assertTrue(jobTop.isExpeditedQuotaApproved());
+ assertTrue(jobTop2.isExpeditedQuotaApproved());
+ assertTrue(jobFg.isExpeditedQuotaApproved());
+ assertTrue(jobBg.isExpeditedQuotaApproved());
+ assertTrue(jobUnstarted.isExpeditedQuotaApproved());
+
+ advanceElapsedClock(20 * SECOND_IN_MILLIS);
+ setProcessState(ActivityManager.PROCESS_STATE_SERVICE);
+ // Bg, Fg, Top, Top2 and jobUnstarted should be changed from in-quota to out-of-quota
+ inOrder.verify(mJobSchedulerService, timeout(SECOND_IN_MILLIS).times(1))
+ .onControllerStateChanged(argThat(jobs -> jobs.size() == 5));
+ // App is now in background and out of quota. Fg should now change to out of quota since it
+ // wasn't started. Top should change to out of quota as the app leaves TOP state.
+ assertFalse(jobTop.isExpeditedQuotaApproved());
+ assertFalse(jobTop2.isExpeditedQuotaApproved());
+ assertFalse(jobFg.isExpeditedQuotaApproved());
+ assertFalse(jobBg.isExpeditedQuotaApproved());
+ trackJobs(jobBg2);
+ assertFalse(jobBg2.isExpeditedQuotaApproved());
+ assertFalse(jobUnstarted.isExpeditedQuotaApproved());
+ synchronized (mQuotaController.mLock) {
+ assertTrue(
+ 0 >= mQuotaController
+ .getRemainingEJExecutionTimeLocked(SOURCE_USER_ID, SOURCE_PACKAGE));
+ }
+ }
+
+ /**
* Tests that Timers properly track overlapping top and background jobs.
*/
@Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundUserSoundNotifierTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundUserSoundNotifierTest.java
index 625dbe6e16f9..bf946a1258fd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundUserSoundNotifierTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundUserSoundNotifierTest.java
@@ -41,14 +41,19 @@ import android.media.AudioManager;
import android.media.AudioPlaybackConfiguration;
import android.media.PlayerProxy;
import android.media.audiopolicy.AudioPolicy;
+import android.multiuser.Flags;
import android.os.Build;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.util.ArraySet;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -60,7 +65,6 @@ import java.util.List;
import java.util.Stack;
@RunWith(JUnit4.class)
-
public class BackgroundUserSoundNotifierTest {
private final Context mRealContext = androidx.test.InstrumentationRegistry.getInstrumentation()
.getTargetContext();
@@ -72,6 +76,10 @@ public class BackgroundUserSoundNotifierTest {
@Mock
private NotificationManager mNotificationManager;
+
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -142,8 +150,11 @@ public class BackgroundUserSoundNotifierTest {
final int fgUserId = mSpiedContext.getUserId();
int bgUserId = fgUserId + 1;
int bgUserUid = bgUserId * 100000;
- mBackgroundUserSoundNotifier.mNotificationClientUid = bgUserUid;
-
+ if (Flags.multipleAlarmNotificationsSupport()) {
+ mBackgroundUserSoundNotifier.mNotificationClientUids.add(bgUserUid);
+ } else {
+ mBackgroundUserSoundNotifier.mNotificationClientUid = bgUserUid;
+ }
AudioManager mockAudioManager = mock(AudioManager.class);
when(mSpiedContext.getSystemService(AudioManager.class)).thenReturn(mockAudioManager);
@@ -243,6 +254,72 @@ public class BackgroundUserSoundNotifierTest {
notification.actions[0].title);
}
+ @RequiresFlagsEnabled({Flags.FLAG_MULTIPLE_ALARM_NOTIFICATIONS_SUPPORT})
+ @Test
+ public void testMultipleAlarmsSameUid_OneNotificationCreated() throws RemoteException {
+ assumeTrue(UserManager.supportsMultipleUsers());
+ UserInfo user = createUser("User", UserManager.USER_TYPE_FULL_SECONDARY, 0);
+ final int fgUserId = mSpiedContext.getUserId();
+ final int bgUserUid = user.id * 100000;
+ doReturn(UserHandle.of(fgUserId)).when(mSpiedContext).getUser();
+
+ AudioAttributes aa = new AudioAttributes.Builder().setUsage(USAGE_ALARM).build();
+ AudioFocusInfo afi1 = new AudioFocusInfo(aa, bgUserUid, "",
+ /* packageName= */ "com.android.car.audio", AudioManager.AUDIOFOCUS_GAIN,
+ AudioManager.AUDIOFOCUS_NONE, /* flags= */ 0, Build.VERSION.SDK_INT);
+
+ mBackgroundUserSoundNotifier.notifyForegroundUserAboutSoundIfNecessary(afi1);
+ verify(mNotificationManager)
+ .notifyAsUser(eq(BackgroundUserSoundNotifier.class.getSimpleName()),
+ eq(afi1.getClientUid()), any(Notification.class),
+ eq(UserHandle.of(fgUserId)));
+
+ AudioFocusInfo afi2 = new AudioFocusInfo(aa, bgUserUid, "",
+ /* packageName= */ "com.android.car.audio", AudioManager.AUDIOFOCUS_GAIN,
+ AudioManager.AUDIOFOCUS_NONE, /* flags= */ 0, Build.VERSION.SDK_INT);
+ clearInvocations(mNotificationManager);
+ mBackgroundUserSoundNotifier.notifyForegroundUserAboutSoundIfNecessary(afi2);
+ verify(mNotificationManager, never())
+ .notifyAsUser(eq(BackgroundUserSoundNotifier.class.getSimpleName()),
+ eq(afi2.getClientUid()), any(Notification.class),
+ eq(UserHandle.of(fgUserId)));
+ }
+
+ @RequiresFlagsEnabled({Flags.FLAG_MULTIPLE_ALARM_NOTIFICATIONS_SUPPORT})
+ @Test
+ public void testMultipleAlarmsDifferentUsers_multipleNotificationsCreated()
+ throws RemoteException {
+ assumeTrue(UserManager.supportsMultipleUsers());
+ UserInfo user1 = createUser("User1", UserManager.USER_TYPE_FULL_SECONDARY, 0);
+ UserInfo user2 = createUser("User2", UserManager.USER_TYPE_FULL_SECONDARY, 0);
+ final int fgUserId = mSpiedContext.getUserId();
+ final int bgUserUid1 = user1.id * 100000;
+ final int bgUserUid2 = user2.id * 100000;
+ doReturn(UserHandle.of(fgUserId)).when(mSpiedContext).getUser();
+
+ AudioAttributes aa = new AudioAttributes.Builder().setUsage(USAGE_ALARM).build();
+ AudioFocusInfo afi1 = new AudioFocusInfo(aa, bgUserUid1, "",
+ /* packageName= */ "com.android.car.audio", AudioManager.AUDIOFOCUS_GAIN,
+ AudioManager.AUDIOFOCUS_NONE, /* flags= */ 0, Build.VERSION.SDK_INT);
+
+ mBackgroundUserSoundNotifier.notifyForegroundUserAboutSoundIfNecessary(afi1);
+ verify(mNotificationManager)
+ .notifyAsUser(eq(BackgroundUserSoundNotifier.class.getSimpleName()),
+ eq(afi1.getClientUid()), any(Notification.class),
+ eq(UserHandle.of(fgUserId)));
+
+ AudioFocusInfo afi2 = new AudioFocusInfo(aa, bgUserUid2, "",
+ /* packageName= */ "com.android.car.audio", AudioManager.AUDIOFOCUS_GAIN,
+ AudioManager.AUDIOFOCUS_NONE, /* flags= */ 0, Build.VERSION.SDK_INT);
+ clearInvocations(mNotificationManager);
+ mBackgroundUserSoundNotifier.notifyForegroundUserAboutSoundIfNecessary(afi2);
+ verify(mNotificationManager)
+ .notifyAsUser(eq(BackgroundUserSoundNotifier.class.getSimpleName()),
+ eq(afi2.getClientUid()), any(Notification.class),
+ eq(UserHandle.of(fgUserId)));
+ }
+
+
private UserInfo createUser(String name, String userType, int flags) {
UserInfo user = mUserManager.createUser(name, userType, flags);
if (user != null) {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java
index 177f30a79ebc..0a1fc3184fca 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsImplTest.java
@@ -987,5 +987,7 @@ public class BatteryStatsImplTest {
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT))
.isEqualTo(60000);
+
+ span.close();
}
}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java
index 9a64ce19254b..94997b29cdd5 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryStatsManagerTest.java
@@ -41,7 +41,7 @@ public class BatteryStatsManagerTest {
public final RavenwoodRule mRavenwood = new RavenwoodRule();
@Test
- public void testBatteryUsageStatsDataConsistency() {
+ public void testBatteryUsageStatsDataConsistency() throws Exception {
BatteryStatsManager bsm = getContext().getSystemService(BatteryStatsManager.class);
BatteryUsageStats stats = bsm.getBatteryUsageStats(
new BatteryUsageStatsQuery.Builder().setMaxStatsAgeMs(
@@ -70,5 +70,7 @@ public class BatteryStatsManagerTest {
}
}
}
+
+ stats.close();
}
}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsAtomTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsAtomTest.java
index 7d2bc178b993..813dd841b2b9 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsAtomTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsAtomTest.java
@@ -64,7 +64,7 @@ public class BatteryUsageStatsAtomTest {
private static final int UID_3 = 4000;
@Test
- public void testAtom_BatteryUsageStatsPerUid() {
+ public void testAtom_BatteryUsageStatsPerUid() throws Exception {
final BatteryUsageStats bus = buildBatteryUsageStats();
BatteryStatsService.FrameworkStatsLogger statsLogger =
mock(BatteryStatsService.FrameworkStatsLogger.class);
@@ -72,6 +72,8 @@ public class BatteryUsageStatsAtomTest {
List<StatsEvent> actual = new ArrayList<>();
new BatteryStatsService.StatsPerUidLogger(statsLogger).logStats(bus, actual);
+ bus.close();
+
if (DEBUG) {
System.out.println(mockingDetails(statsLogger).printInvocations());
}
@@ -284,7 +286,7 @@ public class BatteryUsageStatsAtomTest {
}
@Test
- public void testAtom_BatteryUsageStatsAtomsProto() {
+ public void testAtom_BatteryUsageStatsAtomsProto() throws Exception {
final BatteryUsageStats bus = buildBatteryUsageStats();
final byte[] bytes = bus.getStatsProto();
BatteryUsageStatsAtomsProto proto;
@@ -347,6 +349,7 @@ public class BatteryUsageStatsAtomTest {
// UID_3 - Should be none, since no interesting data (done last for debugging convenience).
assertEquals(3, proto.uidBatteryConsumers.length);
+ bus.close();
}
private void assertSameBatteryConsumer(String message, BatteryConsumer consumer,
@@ -582,7 +585,7 @@ public class BatteryUsageStatsAtomTest {
}
@Test
- public void testLargeAtomTruncated() {
+ public void testLargeAtomTruncated() throws Exception {
final BatteryUsageStats.Builder builder =
new BatteryUsageStats.Builder(new String[0], true, false, false, false, 0);
// If not truncated, this BatteryUsageStats object would generate a proto buffer
@@ -618,6 +621,8 @@ public class BatteryUsageStatsAtomTest {
assertThat(bytes.length).isGreaterThan(20000);
assertThat(bytes.length).isLessThan(50000);
+ batteryUsageStats.close();
+
BatteryUsageStatsAtomsProto proto;
try {
proto = BatteryUsageStatsAtomsProto.parseFrom(bytes);
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
index e9d95fcbccea..87a26d0c68e7 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
@@ -94,7 +94,7 @@ public class BatteryUsageStatsProviderTest {
}
@Test
- public void test_getBatteryUsageStats() {
+ public void test_getBatteryUsageStats() throws IOException {
final BatteryUsageStats batteryUsageStats = prepareBatteryUsageStats(false);
final List<UidBatteryConsumer> uidBatteryConsumers =
@@ -121,24 +121,27 @@ public class BatteryUsageStatsProviderTest {
assertThat(batteryUsageStats.getStatsStartTimestamp()).isEqualTo(12345);
assertThat(batteryUsageStats.getStatsEndTimestamp()).isEqualTo(180 * MINUTE_IN_MS);
+ batteryUsageStats.close();
}
@Test
- public void batteryLevelInfo_charging() {
+ public void batteryLevelInfo_charging() throws IOException {
final BatteryUsageStats batteryUsageStats = prepareBatteryUsageStats(true);
assertThat(batteryUsageStats.getBatteryCapacity()).isEqualTo(4000.0);
assertThat(batteryUsageStats.getChargeTimeRemainingMs()).isEqualTo(1_200_000);
+ batteryUsageStats.close();
}
@Test
- public void batteryLevelInfo_onBattery() {
+ public void batteryLevelInfo_onBattery() throws IOException {
final BatteryUsageStats batteryUsageStats = prepareBatteryUsageStats(false);
assertThat(batteryUsageStats.getBatteryCapacity()).isEqualTo(4000.0);
assertThat(batteryUsageStats.getBatteryTimeRemainingMs()).isEqualTo(600_000);
+ batteryUsageStats.close();
}
@Test
- public void test_selectPowerComponents() {
+ public void test_selectPowerComponents() throws IOException {
BatteryStatsImpl batteryStats = prepareBatteryStats(false);
BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
@@ -163,6 +166,8 @@ public class BatteryUsageStatsProviderTest {
assertThat(
uidBatteryConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT))
.isEqualTo(0);
+
+ batteryUsageStats.close();
}
private BatteryStatsImpl prepareBatteryStats(boolean plugInAtTheEnd) {
@@ -274,7 +279,7 @@ public class BatteryUsageStatsProviderTest {
}
@Test
- public void testWriteAndReadHistory() {
+ public void testWriteAndReadHistory() throws IOException {
MockBatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
synchronized (batteryStats) {
batteryStats.setRecordAllHistoryLocked(true);
@@ -306,6 +311,8 @@ public class BatteryUsageStatsProviderTest {
Parcel in = Parcel.obtain();
batteryUsageStats.writeToParcel(in, 0);
+ batteryUsageStats.close();
+
final byte[] bytes = in.marshall();
Parcel out = Parcel.obtain();
@@ -349,10 +356,12 @@ public class BatteryUsageStatsProviderTest {
assertThat(iterator.hasNext()).isFalse();
assertThat(iterator.next()).isNull();
+
+ unparceled.close();
}
@Test
- public void testWriteAndReadHistoryTags() {
+ public void testWriteAndReadHistoryTags() throws IOException {
MockBatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
synchronized (batteryStats) {
batteryStats.setRecordAllHistoryLocked(true);
@@ -400,6 +409,8 @@ public class BatteryUsageStatsProviderTest {
assertThat(parcel.dataSize()).isAtMost(128_000);
}
+ batteryUsageStats.close();
+
parcel.setDataPosition(0);
BatteryUsageStats unparceled = parcel.readParcelable(getClass().getClassLoader(),
@@ -461,7 +472,7 @@ public class BatteryUsageStatsProviderTest {
}
@Test
- public void testAggregateBatteryStats() {
+ public void testAggregateBatteryStats() throws IOException {
BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
setTime(5 * MINUTE_IN_MS);
@@ -563,6 +574,8 @@ public class BatteryUsageStatsProviderTest {
.getConsumedPower(BatteryConsumer.POWER_COMPONENT_FLASHLIGHT))
.isWithin(0.1)
.of(180.0);
+
+ stats.close();
}
@Test
@@ -689,6 +702,8 @@ public class BatteryUsageStatsProviderTest {
.isEqualTo(60 * MINUTE_IN_MS);
assertThat(count[0]).isEqualTo(expectedNumberOfUpdates);
+
+ stats.close();
}
private void setTime(long timeMs) {
@@ -733,6 +748,7 @@ public class BatteryUsageStatsProviderTest {
.isWithin(PRECISION).of(8.33333);
assertThat(uid.getConsumedPower(componentId1))
.isWithin(PRECISION).of(8.33333);
+ stats.close();
return null;
}).when(powerStatsStore).storeBatteryUsageStatsAsync(anyLong(), any());
@@ -750,7 +766,7 @@ public class BatteryUsageStatsProviderTest {
}
@Test
- public void testAggregateBatteryStats_incompatibleSnapshot() {
+ public void testAggregateBatteryStats_incompatibleSnapshot() throws IOException {
MockBatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
batteryStats.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
@@ -776,6 +792,8 @@ public class BatteryUsageStatsProviderTest {
when(powerStatsStore.loadPowerStatsSpan(1, BatteryUsageStatsSection.TYPE))
.thenReturn(span1);
+ span1.close();
+
BatteryUsageStatsProvider provider = new BatteryUsageStatsProvider(mContext,
mock(PowerAttributor.class), mStatsRule.getPowerProfile(),
mStatsRule.getCpuScalingPolicies(), powerStatsStore, 0, mMockClock);
@@ -787,5 +805,7 @@ public class BatteryUsageStatsProviderTest {
assertThat(stats.getCustomPowerComponentNames())
.isEqualTo(batteryStats.getCustomEnergyConsumerNames());
assertThat(stats.getStatsDuration()).isEqualTo(1234);
+
+ stats.close();
}
}
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
index 52675f6f6cb7..383616eb59eb 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsRule.java
@@ -323,6 +323,7 @@ public class BatteryUsageStatsRule implements TestRule {
}
private void before() {
+ BatteryUsageStats.DEBUG_INSTANCE_COUNT = true;
HandlerThread bgThread = new HandlerThread("bg thread");
bgThread.setUncaughtExceptionHandler((thread, throwable)-> {
mThrowable = throwable;
@@ -338,6 +339,10 @@ public class BatteryUsageStatsRule implements TestRule {
private void after() throws Throwable {
waitForBackgroundThread();
+ if (mBatteryUsageStats != null) {
+ mBatteryUsageStats.close();
+ }
+ BatteryUsageStats.assertAllInstancesClosed();
}
public void waitForBackgroundThread() throws Throwable {
@@ -409,6 +414,14 @@ public class BatteryUsageStatsRule implements TestRule {
}
BatteryUsageStats apply(BatteryUsageStatsQuery query, PowerCalculator... calculators) {
+ if (mBatteryUsageStats != null) {
+ try {
+ mBatteryUsageStats.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ mBatteryUsageStats = null;
+ }
final String[] customPowerComponentNames = mBatteryStats.getCustomEnergyConsumerNames();
final boolean includePowerModels = (query.getFlags()
& BatteryUsageStatsQuery.FLAG_BATTERY_USAGE_STATS_INCLUDE_POWER_MODELS) != 0;
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java
index 88624f28a2e5..1b6b8c49461e 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/BatteryUsageStatsTest.java
@@ -76,22 +76,25 @@ public class BatteryUsageStatsTest {
private static final int APP_UID2 = 314;
@Test
- public void testBuilder() {
+ public void testBuilder() throws Exception {
BatteryUsageStats batteryUsageStats = buildBatteryUsageStats1(true).build();
assertBatteryUsageStats1(batteryUsageStats, true);
+ batteryUsageStats.close();
}
@Test
- public void testBuilder_noProcessStateData() {
+ public void testBuilder_noProcessStateData() throws Exception {
BatteryUsageStats batteryUsageStats = buildBatteryUsageStats1(false).build();
assertBatteryUsageStats1(batteryUsageStats, false);
+ batteryUsageStats.close();
}
@Test
- public void testParcelability_smallNumberOfUids() {
+ public void testParcelability_smallNumberOfUids() throws Exception {
final BatteryUsageStats outBatteryUsageStats = buildBatteryUsageStats1(true).build();
final Parcel parcel = Parcel.obtain();
parcel.writeParcelable(outBatteryUsageStats, 0);
+ outBatteryUsageStats.close();
assertThat(parcel.dataSize()).isLessThan(100000);
@@ -101,10 +104,11 @@ public class BatteryUsageStatsTest {
parcel.readParcelable(getClass().getClassLoader());
assertThat(inBatteryUsageStats).isNotNull();
assertBatteryUsageStats1(inBatteryUsageStats, true);
+ inBatteryUsageStats.close();
}
@Test
- public void testParcelability_largeNumberOfUids() {
+ public void testParcelability_largeNumberOfUids() throws Exception {
final BatteryUsageStats.Builder builder =
new BatteryUsageStats.Builder(new String[0]);
@@ -141,22 +145,27 @@ public class BatteryUsageStatsTest {
assertThat(uidBatteryConsumer).isNotNull();
assertThat(uidBatteryConsumer.getConsumedPower()).isEqualTo(i * 100);
}
+ inBatteryUsageStats.close();
+ outBatteryUsageStats.close();
}
@Test
- public void testDefaultSessionDuration() {
+ public void testDefaultSessionDuration() throws Exception {
final BatteryUsageStats stats =
buildBatteryUsageStats1(true).setStatsDuration(10000).build();
assertThat(stats.getStatsDuration()).isEqualTo(10000);
+ stats.close();
}
@Test
- public void testDump() {
+ public void testDump() throws Exception {
final BatteryUsageStats stats = buildBatteryUsageStats1(true).build();
final StringWriter out = new StringWriter();
try (PrintWriter pw = new PrintWriter(out)) {
stats.dump(pw, " ");
}
+ stats.close();
+
final String dump = out.toString();
assertThat(dump).contains("Capacity: 4000");
@@ -187,12 +196,14 @@ public class BatteryUsageStatsTest {
}
@Test
- public void testDumpNoScreenOrPowerState() {
+ public void testDumpNoScreenOrPowerState() throws Exception {
final BatteryUsageStats stats = buildBatteryUsageStats1(true, false, false).build();
final StringWriter out = new StringWriter();
try (PrintWriter pw = new PrintWriter(out)) {
stats.dump(pw, " ");
}
+ stats.close();
+
final String dump = out.toString();
assertThat(dump).contains("Capacity: 4000");
@@ -222,7 +233,7 @@ public class BatteryUsageStatsTest {
}
@Test
- public void testAdd() {
+ public void testAdd() throws Exception {
final BatteryUsageStats stats1 = buildBatteryUsageStats1(false).build();
final BatteryUsageStats stats2 = buildBatteryUsageStats2(new String[]{"FOO"}, true).build();
final BatteryUsageStats sum =
@@ -261,24 +272,31 @@ public class BatteryUsageStatsTest {
assertAggregateBatteryConsumer(sum,
BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE,
40211, 40422, 40633, 40844);
+ stats1.close();
+ stats2.close();
+ sum.close();
}
@Test
- public void testAdd_customComponentMismatch() {
+ public void testAdd_customComponentMismatch() throws Exception {
final BatteryUsageStats.Builder builder =
new BatteryUsageStats.Builder(new String[]{"FOO"}, true, true, true, true, 0);
final BatteryUsageStats stats = buildBatteryUsageStats2(new String[]{"BAR"}, false).build();
assertThrows(IllegalArgumentException.class, () -> builder.add(stats));
+ stats.close();
+ builder.discard();
}
@Test
- public void testAdd_processStateDataMismatch() {
+ public void testAdd_processStateDataMismatch() throws Exception {
final BatteryUsageStats.Builder builder =
new BatteryUsageStats.Builder(new String[]{"FOO"}, true, true, true, true, 0);
final BatteryUsageStats stats = buildBatteryUsageStats2(new String[]{"FOO"}, false).build();
assertThrows(IllegalArgumentException.class, () -> builder.add(stats));
+ stats.close();
+ builder.discard();
}
@Test
@@ -290,12 +308,14 @@ public class BatteryUsageStatsTest {
final BatteryUsageStats stats = buildBatteryUsageStats1(true).build();
stats.writeXml(serializer);
serializer.endDocument();
+ stats.close();
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
TypedXmlPullParser parser = Xml.newBinaryPullParser();
parser.setInput(in, StandardCharsets.UTF_8.name());
final BatteryUsageStats fromXml = BatteryUsageStats.createFromXml(parser);
assertBatteryUsageStats1(fromXml, true);
+ fromXml.close();
}
private BatteryUsageStats.Builder buildBatteryUsageStats1(boolean includeUserBatteryConsumer) {
diff --git a/services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java b/services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
index 1e4454c9a3f0..b374a3202fa2 100644
--- a/services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
+++ b/services/tests/powerstatstests/src/com/android/server/power/stats/MockBatteryStatsImpl.java
@@ -17,6 +17,7 @@
package com.android.server.power.stats;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.app.usage.NetworkStatsManager;
@@ -80,7 +81,7 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
Handler handler, PowerStatsUidResolver powerStatsUidResolver) {
super(config, clock, new MonotonicClock(0, clock), historyDirectory, handler,
mock(PlatformIdleStateCallback.class), mock(EnergyStatsRetriever.class),
- mock(UserInfoProvider.class), mock(PowerProfile.class),
+ mock(UserInfoProvider.class), mockPowerProfile(),
new CpuScalingPolicies(new SparseArray<>(), new SparseArray<>()),
powerStatsUidResolver, mock(FrameworkStatsLogger.class),
mock(BatteryStatsHistory.TraceDelegate.class),
@@ -96,6 +97,12 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
mKernelWakelockReader = null;
}
+ private static PowerProfile mockPowerProfile() {
+ PowerProfile powerProfile = mock(PowerProfile.class);
+ when(powerProfile.getNumDisplays()).thenReturn(1);
+ return powerProfile;
+ }
+
public void initMeasuredEnergyStats(String[] customBucketNames) {
final boolean[] supportedStandardBuckets =
new boolean[EnergyConsumerStats.NUMBER_STANDARD_POWER_BUCKETS];
diff --git a/services/tests/security/forensic/src/com/android/server/security/forensic/ForensicServiceTest.java b/services/tests/security/forensic/src/com/android/server/security/forensic/ForensicServiceTest.java
index 7aa2e0f609a7..2b55303bd89f 100644
--- a/services/tests/security/forensic/src/com/android/server/security/forensic/ForensicServiceTest.java
+++ b/services/tests/security/forensic/src/com/android/server/security/forensic/ForensicServiceTest.java
@@ -19,6 +19,9 @@ package com.android.server.security.forensic;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
import android.annotation.SuppressLint;
import android.content.Context;
@@ -50,7 +53,8 @@ public class ForensicServiceTest {
IForensicServiceCommandCallback.ErrorCode.DATA_SOURCE_UNAVAILABLE;
@Mock
- private Context mContextSpy;
+ private Context mContext;
+ private BackupTransportConnection mBackupTransportConnection;
private ForensicService mForensicService;
private TestLooper mTestLooper;
@@ -63,7 +67,7 @@ public class ForensicServiceTest {
mTestLooper = new TestLooper();
mLooper = mTestLooper.getLooper();
- mForensicService = new ForensicService(new MockInjector(mContextSpy));
+ mForensicService = new ForensicService(new MockInjector(mContext));
mForensicService.onStart();
}
@@ -253,6 +257,8 @@ public class ForensicServiceTest {
assertEquals(STATE_VISIBLE, scb1.mState);
assertEquals(STATE_VISIBLE, scb2.mState);
+ doReturn(true).when(mBackupTransportConnection).initialize();
+
CommandCallback ccb = new CommandCallback();
mForensicService.getBinderService().enable(ccb);
mTestLooper.dispatchAll();
@@ -262,6 +268,29 @@ public class ForensicServiceTest {
}
@Test
+ public void testEnable_FromVisible_TwoMonitors_BackupTransportUnavailable()
+ throws RemoteException {
+ mForensicService.setState(STATE_VISIBLE);
+ StateCallback scb1 = new StateCallback();
+ StateCallback scb2 = new StateCallback();
+ mForensicService.getBinderService().monitorState(scb1);
+ mForensicService.getBinderService().monitorState(scb2);
+ mTestLooper.dispatchAll();
+ assertEquals(STATE_VISIBLE, scb1.mState);
+ assertEquals(STATE_VISIBLE, scb2.mState);
+
+ doReturn(false).when(mBackupTransportConnection).initialize();
+
+ CommandCallback ccb = new CommandCallback();
+ mForensicService.getBinderService().enable(ccb);
+ mTestLooper.dispatchAll();
+ assertEquals(STATE_VISIBLE, scb1.mState);
+ assertEquals(STATE_VISIBLE, scb2.mState);
+ assertNotNull(ccb.mErrorCode);
+ assertEquals(ERROR_BACKUP_TRANSPORT_UNAVAILABLE, ccb.mErrorCode.intValue());
+ }
+
+ @Test
public void testEnable_FromEnabled_TwoMonitors() throws RemoteException {
mForensicService.setState(STATE_ENABLED);
StateCallback scb1 = new StateCallback();
@@ -330,6 +359,8 @@ public class ForensicServiceTest {
assertEquals(STATE_ENABLED, scb1.mState);
assertEquals(STATE_ENABLED, scb2.mState);
+ doNothing().when(mBackupTransportConnection).release();
+
CommandCallback ccb = new CommandCallback();
mForensicService.getBinderService().disable(ccb);
mTestLooper.dispatchAll();
@@ -356,6 +387,12 @@ public class ForensicServiceTest {
return mLooper;
}
+ @Override
+ public BackupTransportConnection getBackupTransportConnection() {
+ mBackupTransportConnection = spy(new BackupTransportConnection(mContext));
+ return mBackupTransportConnection;
+ }
+
}
private static class StateCallback extends IForensicServiceStateCallback.Stub {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
index 7829fcc4b44d..8df18a8c178b 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
@@ -480,7 +480,7 @@ public class MagnificationProcessorTest {
if (config.getMode() == MAGNIFICATION_MODE_FULLSCREEN) {
mFullScreenMagnificationControllerStub.resetAndStubMethods();
mMockFullScreenMagnificationController.setScaleAndCenter(displayId, config.getScale(),
- config.getCenterX(), config.getCenterY(), false, SERVICE_ID);
+ config.getCenterX(), config.getCenterY(), true, false, SERVICE_ID);
mMagnificationManagerStub.deactivateIfNeed();
} else if (config.getMode() == MAGNIFICATION_MODE_WINDOW) {
mMagnificationManagerStub.resetAndStubMethods();
@@ -531,6 +531,9 @@ public class MagnificationProcessorTest {
};
doAnswer(enableMagnificationStubAnswer).when(
mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY), anyFloat(),
+ anyFloat(), anyFloat(), anyBoolean(), anyBoolean(), eq(SERVICE_ID));
+ doAnswer(enableMagnificationStubAnswer).when(
+ mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY), anyFloat(),
anyFloat(), anyFloat(), anyBoolean(), eq(SERVICE_ID));
Answer disableMagnificationStubAnswer = invocation -> {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
index c4b4afd13a60..5985abc344a2 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationControllerTest.java
@@ -18,6 +18,7 @@ package com.android.server.accessibility.magnification;
import static android.accessibilityservice.MagnificationConfig.MAGNIFICATION_MODE_FULLSCREEN;
+import static com.android.server.accessibility.Flags.FLAG_MAGNIFICATION_ENLARGE_POINTER;
import static com.android.server.accessibility.magnification.FullScreenMagnificationController.MagnificationInfoChangedCallback;
import static com.android.server.accessibility.magnification.MockMagnificationConnection.TEST_DISPLAY;
import static com.android.window.flags.Flags.FLAG_ALWAYS_DRAW_MAGNIFICATION_FULLSCREEN_BORDER;
@@ -76,6 +77,7 @@ import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityTraceManager;
import com.android.server.accessibility.Flags;
import com.android.server.accessibility.test.MessageCapturingHandler;
+import com.android.server.input.InputManagerInternal;
import com.android.server.wm.WindowManagerInternal;
import com.android.server.wm.WindowManagerInternal.MagnificationCallbacks;
@@ -126,6 +128,7 @@ public class FullScreenMagnificationControllerTest {
final Resources mMockResources = mock(Resources.class);
final AccessibilityTraceManager mMockTraceManager = mock(AccessibilityTraceManager.class);
final WindowManagerInternal mMockWindowManager = mock(WindowManagerInternal.class);
+ final InputManagerInternal mMockInputManager = mock(InputManagerInternal.class);
private final MagnificationAnimationCallback mAnimationCallback = mock(
MagnificationAnimationCallback.class);
private final MagnificationInfoChangedCallback mRequestObserver = mock(
@@ -163,6 +166,7 @@ public class FullScreenMagnificationControllerTest {
when(mMockControllerCtx.getContext()).thenReturn(mMockContext);
when(mMockControllerCtx.getTraceManager()).thenReturn(mMockTraceManager);
when(mMockControllerCtx.getWindowManager()).thenReturn(mMockWindowManager);
+ when(mMockControllerCtx.getInputManager()).thenReturn(mMockInputManager);
when(mMockControllerCtx.getHandler()).thenReturn(mMessageCapturingHandler);
when(mMockControllerCtx.getAnimationDuration()).thenReturn(1000L);
mResolver = new MockContentResolver();
@@ -285,10 +289,11 @@ public class FullScreenMagnificationControllerTest {
mFullScreenMagnificationController.magnificationRegionContains(displayId, 100,
100));
assertFalse(mFullScreenMagnificationController.reset(displayId, true));
- assertFalse(mFullScreenMagnificationController.setScale(displayId, 2, 100, 100, true, 0));
+ assertFalse(
+ mFullScreenMagnificationController.setScale(displayId, 2, 100, 100, true, true, 0));
assertFalse(mFullScreenMagnificationController.setCenter(displayId, 100, 100, false, 1));
assertFalse(mFullScreenMagnificationController.setScaleAndCenter(displayId,
- 1.5f, 100, 100, false, 2));
+ 1.5f, 100, 100, true, false, 2));
assertTrue(mFullScreenMagnificationController.getIdOfLastServiceToMagnify(displayId) < 0);
mFullScreenMagnificationController.getMagnificationRegion(displayId, new Region());
@@ -313,7 +318,7 @@ public class FullScreenMagnificationControllerTest {
final float scale = 2.0f;
final PointF center = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
assertFalse(mFullScreenMagnificationController
- .setScale(TEST_DISPLAY, scale, center.x, center.y, false, SERVICE_ID_1));
+ .setScale(TEST_DISPLAY, scale, center.x, center.y, true, false, SERVICE_ID_1));
assertFalse(mFullScreenMagnificationController.isActivated(TEST_DISPLAY));
}
@@ -331,7 +336,7 @@ public class FullScreenMagnificationControllerTest {
final PointF center = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
final PointF offsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, center, scale);
assertTrue(mFullScreenMagnificationController
- .setScale(displayId, scale, center.x, center.y, false, SERVICE_ID_1));
+ .setScale(displayId, scale, center.x, center.y, true, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
final MagnificationSpec expectedSpec = getMagnificationSpec(scale, offsets);
@@ -357,7 +362,7 @@ public class FullScreenMagnificationControllerTest {
float scale = 2.0f;
PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
assertTrue(mFullScreenMagnificationController
- .setScale(displayId, scale, pivotPoint.x, pivotPoint.y, true, SERVICE_ID_1));
+ .setScale(displayId, scale, pivotPoint.x, pivotPoint.y, true, true, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
// New center should be halfway between original center and pivot
@@ -405,7 +410,7 @@ public class FullScreenMagnificationControllerTest {
float scale = 2.0f;
assertTrue(mFullScreenMagnificationController.setScale(displayId, scale,
INITIAL_MAGNIFICATION_BOUNDS.centerX(), INITIAL_MAGNIFICATION_BOUNDS.centerY(),
- false, SERVICE_ID_1));
+ true, false, SERVICE_ID_1));
Mockito.reset(mMockWindowManager);
PointF newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
@@ -440,7 +445,7 @@ public class FullScreenMagnificationControllerTest {
MagnificationSpec endSpec = getMagnificationSpec(scale, offsets);
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId, scale,
- newCenter.x, newCenter.y, mAnimationCallback, SERVICE_ID_1));
+ newCenter.x, newCenter.y, true, mAnimationCallback, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
assertEquals(newCenter.x, mFullScreenMagnificationController.getCenterX(displayId), 0.5);
@@ -486,11 +491,11 @@ public class FullScreenMagnificationControllerTest {
final PointF center = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
final float targetScale = 2.0f;
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId,
- targetScale, center.x, center.y, false, SERVICE_ID_1));
+ targetScale, center.x, center.y, true, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
assertFalse(mFullScreenMagnificationController.setScaleAndCenter(displayId,
- targetScale, center.x, center.y, mAnimationCallback, SERVICE_ID_1));
+ targetScale, center.x, center.y, true, mAnimationCallback, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
verify(mMockValueAnimator, never()).start();
@@ -516,7 +521,7 @@ public class FullScreenMagnificationControllerTest {
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId,
MagnificationScaleProvider.MAX_SCALE + 1.0f,
- newCenter.x, newCenter.y, false, SERVICE_ID_1));
+ newCenter.x, newCenter.y, true, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
assertEquals(newCenter.x, mFullScreenMagnificationController.getCenterX(displayId), 0.5);
@@ -527,7 +532,7 @@ public class FullScreenMagnificationControllerTest {
// Verify that we can't zoom below 1x
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId, 0.5f,
INITIAL_MAGNIFICATION_BOUNDS_CENTER.x, INITIAL_MAGNIFICATION_BOUNDS_CENTER.y,
- false, SERVICE_ID_1));
+ true, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
assertEquals(INITIAL_MAGNIFICATION_BOUNDS_CENTER.x,
@@ -551,7 +556,7 @@ public class FullScreenMagnificationControllerTest {
// Off the edge to the top and left
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId,
- scale, -100f, -200f, false, SERVICE_ID_1));
+ scale, -100f, -200f, true, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
PointF newCenter = INITIAL_BOUNDS_UPPER_LEFT_2X_CENTER;
@@ -565,7 +570,7 @@ public class FullScreenMagnificationControllerTest {
// Off the edge to the bottom and right
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId, scale,
INITIAL_MAGNIFICATION_BOUNDS.right + 1, INITIAL_MAGNIFICATION_BOUNDS.bottom + 1,
- false, SERVICE_ID_1));
+ true, false, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
newCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
newOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, newCenter, scale);
@@ -619,7 +624,7 @@ public class FullScreenMagnificationControllerTest {
PointF startOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, startCenter, scale);
// First zoom in
assertTrue(mFullScreenMagnificationController
- .setScaleAndCenter(displayId, scale, startCenter.x, startCenter.y, false,
+ .setScaleAndCenter(displayId, scale, startCenter.x, startCenter.y, true, false,
SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
Mockito.reset(mMockWindowManager);
@@ -673,7 +678,7 @@ public class FullScreenMagnificationControllerTest {
// Upper left edges
PointF ulCenter = INITIAL_BOUNDS_UPPER_LEFT_2X_CENTER;
assertTrue(mFullScreenMagnificationController
- .setScaleAndCenter(displayId, scale, ulCenter.x, ulCenter.y, false,
+ .setScaleAndCenter(displayId, scale, ulCenter.x, ulCenter.y, true, false,
SERVICE_ID_1));
Mockito.reset(mMockWindowManager);
MagnificationSpec ulSpec = getCurrentMagnificationSpec(displayId);
@@ -685,7 +690,7 @@ public class FullScreenMagnificationControllerTest {
// Lower right edges
PointF lrCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
assertTrue(mFullScreenMagnificationController
- .setScaleAndCenter(displayId, scale, lrCenter.x, lrCenter.y, false,
+ .setScaleAndCenter(displayId, scale, lrCenter.x, lrCenter.y, true, false,
SERVICE_ID_1));
Mockito.reset(mMockWindowManager);
MagnificationSpec lrSpec = getCurrentMagnificationSpec(displayId);
@@ -710,7 +715,7 @@ public class FullScreenMagnificationControllerTest {
float scale = 2.0f;
// First zoom in
assertTrue(mFullScreenMagnificationController
- .setScaleAndCenter(displayId, scale, startCenter.x, startCenter.y, false,
+ .setScaleAndCenter(displayId, scale, startCenter.x, startCenter.y, true, false,
SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
@@ -753,7 +758,7 @@ public class FullScreenMagnificationControllerTest {
PointF startOffsets = computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, startCenter, scale);
// First zoom in
assertTrue(mFullScreenMagnificationController
- .setScaleAndCenter(displayId, scale, startCenter.x, startCenter.y, false,
+ .setScaleAndCenter(displayId, scale, startCenter.x, startCenter.y, true, false,
SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
@@ -786,12 +791,12 @@ public class FullScreenMagnificationControllerTest {
register(displayId);
PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
assertTrue(mFullScreenMagnificationController
- .setScale(displayId, 2.0f, startCenter.x, startCenter.y, false,
+ .setScale(displayId, 2.0f, startCenter.x, startCenter.y, true, false,
SERVICE_ID_1));
assertEquals(SERVICE_ID_1,
mFullScreenMagnificationController.getIdOfLastServiceToMagnify(displayId));
assertTrue(mFullScreenMagnificationController
- .setScale(displayId, 1.5f, startCenter.x, startCenter.y, false,
+ .setScale(displayId, 1.5f, startCenter.x, startCenter.y, true, false,
SERVICE_ID_2));
assertEquals(SERVICE_ID_2,
mFullScreenMagnificationController.getIdOfLastServiceToMagnify(displayId));
@@ -809,10 +814,10 @@ public class FullScreenMagnificationControllerTest {
register(displayId);
PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
mFullScreenMagnificationController
- .setScale(displayId, 2.0f, startCenter.x, startCenter.y, false,
+ .setScale(displayId, 2.0f, startCenter.x, startCenter.y, true, false,
SERVICE_ID_1);
mFullScreenMagnificationController
- .setScale(displayId, 1.5f, startCenter.x, startCenter.y, false,
+ .setScale(displayId, 1.5f, startCenter.x, startCenter.y, true, false,
SERVICE_ID_2);
assertFalse(mFullScreenMagnificationController.resetIfNeeded(displayId, SERVICE_ID_1));
checkActivatedAndMagnifying(/* activated= */ true, /* magnifying= */ true, displayId);
@@ -873,7 +878,7 @@ public class FullScreenMagnificationControllerTest {
float scale = 2.5f;
PointF firstCenter = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId,
- scale, firstCenter.x, firstCenter.y, mAnimationCallback, SERVICE_ID_1));
+ scale, firstCenter.x, firstCenter.y, true, mAnimationCallback, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
Mockito.reset(mMockValueAnimator);
// Stubs the logic after the animation is started.
@@ -1076,7 +1081,7 @@ public class FullScreenMagnificationControllerTest {
float scale = 2.0f;
// setting animate parameter to true is differ from zoomIn2xToMiddle()
mFullScreenMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y,
- true, SERVICE_ID_1);
+ true, true, SERVICE_ID_1);
MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
MagnificationCallbacks callbacks = getMagnificationCallbacks(displayId);
Mockito.reset(mMockWindowManager);
@@ -1107,7 +1112,7 @@ public class FullScreenMagnificationControllerTest {
PointF startCenter = OTHER_BOUNDS_LOWER_RIGHT_2X_CENTER;
float scale = 2.0f;
mFullScreenMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y,
- false, SERVICE_ID_1);
+ true, false, SERVICE_ID_1);
mMessageCapturingHandler.sendAllMessages();
MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
verify(mMockWindowManager).setMagnificationSpec(eq(displayId), argThat(closeTo(startSpec)));
@@ -1148,7 +1153,7 @@ public class FullScreenMagnificationControllerTest {
PointF startCenter = OTHER_BOUNDS_LOWER_RIGHT_2X_CENTER;
float scale = 2.0f;
mFullScreenMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y,
- true, SERVICE_ID_1);
+ true, true, SERVICE_ID_1);
mMessageCapturingHandler.sendAllMessages();
MagnificationSpec startSpec = getCurrentMagnificationSpec(displayId);
when(mMockValueAnimator.isRunning()).thenReturn(true);
@@ -1335,7 +1340,7 @@ public class FullScreenMagnificationControllerTest {
scale, computeOffsets(INITIAL_MAGNIFICATION_BOUNDS, firstCenter, scale));
assertTrue(mFullScreenMagnificationController.setScaleAndCenter(displayId,
- scale, firstCenter.x, firstCenter.y, true, SERVICE_ID_1));
+ scale, firstCenter.x, firstCenter.y, true, true, SERVICE_ID_1));
mMessageCapturingHandler.sendAllMessages();
assertEquals(firstCenter.x, mFullScreenMagnificationController.getCenterX(displayId), 0.5);
@@ -1404,7 +1409,7 @@ public class FullScreenMagnificationControllerTest {
register(DISPLAY_0);
final float scale = 1.0f;
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, scale, Float.NaN, Float.NaN, true, SERVICE_ID_1);
+ DISPLAY_0, scale, Float.NaN, Float.NaN, true, true, SERVICE_ID_1);
checkActivatedAndMagnifying(/* activated= */ true, /* magnifying= */ false, DISPLAY_0);
verify(mMockWindowManager).setFullscreenMagnificationActivated(DISPLAY_0, true);
@@ -1449,7 +1454,7 @@ public class FullScreenMagnificationControllerTest {
PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
mFullScreenMagnificationController.setScale(TEST_DISPLAY, 1.0f, pivotPoint.x, pivotPoint.y,
- false, SERVICE_ID_1);
+ true, false, SERVICE_ID_1);
mFullScreenMagnificationController.persistScale(TEST_DISPLAY);
// persistScale may post a task to a background thread. Let's wait for it completes.
@@ -1464,10 +1469,10 @@ public class FullScreenMagnificationControllerTest {
register(DISPLAY_1);
final PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
mFullScreenMagnificationController.setScale(DISPLAY_0, 3.0f, pivotPoint.x, pivotPoint.y,
- false, SERVICE_ID_1);
+ true, false, SERVICE_ID_1);
mFullScreenMagnificationController.persistScale(DISPLAY_0);
mFullScreenMagnificationController.setScale(DISPLAY_1, 4.0f, pivotPoint.x, pivotPoint.y,
- false, SERVICE_ID_1);
+ true, false, SERVICE_ID_1);
mFullScreenMagnificationController.persistScale(DISPLAY_1);
// persistScale may post a task to a background thread. Let's wait for it completes.
@@ -1479,6 +1484,101 @@ public class FullScreenMagnificationControllerTest {
}
@Test
+ @RequiresFlagsEnabled(FLAG_MAGNIFICATION_ENLARGE_POINTER)
+ public void persistScale_setValue_notifyInput() {
+ register(TEST_DISPLAY);
+
+ PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+ mFullScreenMagnificationController.setScale(TEST_DISPLAY, 4.0f, pivotPoint.x, pivotPoint.y,
+ /* isScaleTransient= */ true, /* animate= */ false, SERVICE_ID_1);
+ verify(mMockInputManager, never()).setAccessibilityPointerIconScaleFactor(anyInt(),
+ anyFloat());
+
+ mFullScreenMagnificationController.persistScale(TEST_DISPLAY);
+
+ // persistScale may post a task to a background thread. Let's wait for it completes.
+ waitForBackgroundThread();
+ Assert.assertEquals(mFullScreenMagnificationController.getPersistedScale(TEST_DISPLAY),
+ 4.0f);
+ verify(mMockInputManager).setAccessibilityPointerIconScaleFactor(TEST_DISPLAY, 4.0f);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_MAGNIFICATION_ENLARGE_POINTER)
+ public void setScale_setNonTransientScale_notifyInput() {
+ register(TEST_DISPLAY);
+
+ PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+ mFullScreenMagnificationController.setScale(TEST_DISPLAY, 4.0f, pivotPoint.x, pivotPoint.y,
+ /* isScaleTransient= */ false, /* animate= */ false, SERVICE_ID_1);
+
+ verify(mMockInputManager).setAccessibilityPointerIconScaleFactor(TEST_DISPLAY, 4.0f);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_MAGNIFICATION_ENLARGE_POINTER)
+ public void setScaleAndCenter_setTransientScale_notNotifyInput() {
+ register(TEST_DISPLAY);
+
+ PointF point = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+ mFullScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY, 3.0f, point.x,
+ point.y, /* isScaleTransient= */ true, /* animate= */ false, SERVICE_ID_1);
+
+ verify(mRequestObserver).onFullScreenMagnificationChanged(anyInt(), any(Region.class),
+ any(MagnificationConfig.class));
+ verify(mMockInputManager, never()).setAccessibilityPointerIconScaleFactor(anyInt(),
+ anyFloat());
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_MAGNIFICATION_ENLARGE_POINTER)
+ public void setScaleAndCenter_setNonTransientScale_notifyInput() {
+ register(TEST_DISPLAY);
+
+ PointF point = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+ mFullScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY, 3.0f, point.x,
+ point.y, /* isScaleTransient= */ false, /* animate= */ false, SERVICE_ID_1);
+
+ verify(mMockInputManager).setAccessibilityPointerIconScaleFactor(TEST_DISPLAY, 3.0f);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_MAGNIFICATION_ENLARGE_POINTER)
+ public void setCenter_notNotifyInput() {
+ register(TEST_DISPLAY);
+
+ PointF point = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+ mFullScreenMagnificationController.setScale(TEST_DISPLAY, 2.0f, point.x, point.y,
+ /* isScaleTransient= */ true, /* animate= */ false, SERVICE_ID_1);
+ mFullScreenMagnificationController.setCenter(TEST_DISPLAY, point.x, point.y, false,
+ SERVICE_ID_1);
+
+ // Note that setCenter doesn't change scale, so it's not necessary to notify the input
+ // manager, but we currently do. The input manager skips redundant computation if the
+ // notified scale is the same as the previous call.
+ verify(mMockInputManager).setAccessibilityPointerIconScaleFactor(TEST_DISPLAY,
+ 2.0f);
+ }
+
+ @Test
+ @RequiresFlagsEnabled(FLAG_MAGNIFICATION_ENLARGE_POINTER)
+ public void offsetMagnifiedRegion_notNotifyInput() {
+ register(TEST_DISPLAY);
+
+ PointF point = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
+ mFullScreenMagnificationController.setScale(TEST_DISPLAY, 2.0f, point.x, point.y,
+ /* isScaleTransient= */ true, /* animate= */ false, SERVICE_ID_1);
+ mFullScreenMagnificationController.offsetMagnifiedRegion(TEST_DISPLAY, 100, 50,
+ SERVICE_ID_1);
+
+ // Note that setCenter doesn't change scale, so it's not necessary to notify the input
+ // manager, but we currently do. The input manager skips redundant computation if the
+ // notified scale is the same as the previous call.
+ verify(mMockInputManager).setAccessibilityPointerIconScaleFactor(TEST_DISPLAY,
+ 2.0f);
+ }
+
+ @Test
public void testOnContextChanged_alwaysOnFeatureDisabled_resetMagnification() {
setScaleToMagnifying();
@@ -1535,7 +1635,7 @@ public class FullScreenMagnificationControllerTest {
PointF pivotPoint = INITIAL_BOUNDS_LOWER_RIGHT_2X_CENTER;
mFullScreenMagnificationController.setScale(DISPLAY_0, scale, pivotPoint.x, pivotPoint.y,
- false, SERVICE_ID_1);
+ true, false, SERVICE_ID_1);
}
private void initMockWindowManager() {
@@ -1578,7 +1678,7 @@ public class FullScreenMagnificationControllerTest {
PointF startCenter = INITIAL_MAGNIFICATION_BOUNDS_CENTER;
float scale = 2.0f;
mFullScreenMagnificationController.setScale(displayId, scale, startCenter.x, startCenter.y,
- false, SERVICE_ID_1);
+ true, false, SERVICE_ID_1);
checkActivatedAndMagnifying(/* activated= */ true, /* magnifying= */ true, displayId);
}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
index e5831b326de5..9f5dd93054c3 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java
@@ -90,6 +90,7 @@ import com.android.server.accessibility.AccessibilityTraceManager;
import com.android.server.accessibility.EventStreamTransformation;
import com.android.server.accessibility.Flags;
import com.android.server.accessibility.magnification.FullScreenMagnificationController.MagnificationInfoChangedCallback;
+import com.android.server.input.InputManagerInternal;
import com.android.server.testutils.OffsettableClock;
import com.android.server.testutils.TestHandler;
import com.android.server.wm.WindowManagerInternal;
@@ -227,9 +228,11 @@ public class FullScreenMagnificationGestureHandlerTest {
final FullScreenMagnificationController.ControllerContext mockController =
mock(FullScreenMagnificationController.ControllerContext.class);
final WindowManagerInternal mockWindowManager = mock(WindowManagerInternal.class);
+ final InputManagerInternal mockInputManager = mock(InputManagerInternal.class);
when(mockController.getContext()).thenReturn(mContext);
when(mockController.getTraceManager()).thenReturn(mMockTraceManager);
when(mockController.getWindowManager()).thenReturn(mockWindowManager);
+ when(mockController.getInputManager()).thenReturn(mockInputManager);
when(mockController.getHandler()).thenReturn(new Handler(mContext.getMainLooper()));
when(mockController.newValueAnimator()).thenReturn(new ValueAnimator());
when(mockController.getAnimationDuration()).thenReturn(1000L);
@@ -1343,7 +1346,7 @@ public class FullScreenMagnificationGestureHandlerTest {
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, persistedScale,
UserHandle.USER_SYSTEM);
mFullScreenMagnificationController.setScale(DISPLAY_0, scale, DEFAULT_X,
- DEFAULT_Y, /* animate= */ false,
+ DEFAULT_Y, true, /* animate= */ false,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
mMgh.transitionTo(mMgh.mPanningScalingState);
@@ -1364,7 +1367,7 @@ public class FullScreenMagnificationGestureHandlerTest {
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_SCALE, persistedScale,
UserHandle.USER_SYSTEM);
mFullScreenMagnificationController.setScale(DISPLAY_0, scale, DEFAULT_X,
- DEFAULT_Y, /* animate= */ false,
+ DEFAULT_Y, true, /* animate= */ false,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
mMgh.transitionTo(mMgh.mPanningScalingState);
@@ -1401,7 +1404,7 @@ public class FullScreenMagnificationGestureHandlerTest {
mFullScreenMagnificationController.getPersistedScale(DISPLAY_0);
mFullScreenMagnificationController.setScale(DISPLAY_0, persistedScale, DEFAULT_X,
- DEFAULT_Y, /* animate= */ false,
+ DEFAULT_Y, true, /* animate= */ false,
AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
mMgh.transitionTo(mMgh.mPanningScalingState);
@@ -1438,7 +1441,7 @@ public class FullScreenMagnificationGestureHandlerTest {
(INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
float scale = 5.6f; // value is unimportant but unique among tests to increase coverage.
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ DISPLAY_0, centerX, centerY, scale, true, /* animate= */ false, 1);
centerX = mFullScreenMagnificationController.getCenterX(DISPLAY_0);
centerY = mFullScreenMagnificationController.getCenterY(DISPLAY_0);
@@ -1530,7 +1533,7 @@ public class FullScreenMagnificationGestureHandlerTest {
(INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
float scale = 6.2f; // value is unimportant but unique among tests to increase coverage.
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ DISPLAY_0, centerX, centerY, scale, true, /* animate= */ false, 1);
MotionEvent event = mouseEvent(centerX, centerY, ACTION_HOVER_MOVE);
send(event, InputDevice.SOURCE_MOUSE);
fastForward(20);
@@ -1571,7 +1574,7 @@ public class FullScreenMagnificationGestureHandlerTest {
(INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
float scale = 4.0f; // value is unimportant but unique among tests to increase coverage.
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ DISPLAY_0, centerX, centerY, scale, true, /* animate= */ false, 1);
// HOVER_MOVE should change magnifier viewport.
MotionEvent event = motionEvent(centerX + 20, centerY, ACTION_HOVER_MOVE);
@@ -1615,7 +1618,7 @@ public class FullScreenMagnificationGestureHandlerTest {
(INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
float scale = 5.3f; // value is unimportant but unique among tests to increase coverage.
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ DISPLAY_0, centerX, centerY, scale, true, /* animate= */ false, 1);
MotionEvent event = motionEvent(centerX, centerY, ACTION_HOVER_MOVE);
send(event, source);
fastForward(20);
@@ -1649,7 +1652,7 @@ public class FullScreenMagnificationGestureHandlerTest {
(INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
float scale = 2.7f; // value is unimportant but unique among tests to increase coverage.
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ DISPLAY_0, centerX, centerY, scale, true, /* animate= */ false, 1);
MotionEvent event = motionEvent(centerX, centerY, ACTION_HOVER_MOVE);
send(event, source);
fastForward(20);
@@ -1685,7 +1688,7 @@ public class FullScreenMagnificationGestureHandlerTest {
(INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
float scale = 3.8f; // value is unimportant but unique among tests to increase coverage.
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ DISPLAY_0, centerX, centerY, scale, true, /* animate= */ false, 1);
centerX = mFullScreenMagnificationController.getCenterX(DISPLAY_0);
centerY = mFullScreenMagnificationController.getCenterY(DISPLAY_0);
@@ -1722,7 +1725,7 @@ public class FullScreenMagnificationGestureHandlerTest {
(INITIAL_MAGNIFICATION_BOUNDS.top + INITIAL_MAGNIFICATION_BOUNDS.height()) / 2.0f;
float scale = 4.0f; // value is unimportant but unique among tests to increase coverage.
mFullScreenMagnificationController.setScaleAndCenter(
- DISPLAY_0, centerX, centerY, scale, /* animate= */ false, 1);
+ DISPLAY_0, centerX, centerY, scale, true, /* animate= */ false, 1);
centerX = mFullScreenMagnificationController.getCenterX(DISPLAY_0);
centerY = mFullScreenMagnificationController.getCenterY(DISPLAY_0);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
index 25281774cd95..8164ef9314d9 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
@@ -76,6 +76,7 @@ import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.accessibility.AccessibilityTraceManager;
import com.android.server.accessibility.test.MessageCapturingHandler;
+import com.android.server.input.InputManagerInternal;
import com.android.server.wm.WindowManagerInternal;
import com.android.window.flags.Flags;
@@ -154,6 +155,8 @@ public class MagnificationControllerTest {
private WindowManagerInternal mWindowManagerInternal;
@Mock
private WindowManagerInternal.AccessibilityControllerInternal mA11yController;
+ @Mock
+ private InputManagerInternal mInputManagerInternal;
@Mock
private DisplayManagerInternal mDisplayManagerInternal;
@@ -200,6 +203,7 @@ public class MagnificationControllerTest {
when(mControllerCtx.getContext()).thenReturn(mContext);
when(mControllerCtx.getTraceManager()).thenReturn(mTraceManager);
when(mControllerCtx.getWindowManager()).thenReturn(mWindowManagerInternal);
+ when(mControllerCtx.getInputManager()).thenReturn(mInputManagerInternal);
when(mControllerCtx.getHandler()).thenReturn(mMessageCapturingHandler);
when(mControllerCtx.getAnimationDuration()).thenReturn(1000L);
when(mControllerCtx.newValueAnimator()).thenReturn(mValueAnimator);
@@ -417,7 +421,7 @@ public class MagnificationControllerTest {
assertTrue(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY));
verify(mScreenMagnificationController, never()).setScaleAndCenter(TEST_DISPLAY,
DEFAULT_SCALE, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y,
- true, MAGNIFICATION_GESTURE_HANDLER_ID);
+ true, true, MAGNIFICATION_GESTURE_HANDLER_ID);
verify(mTransitionCallBack).onResult(TEST_DISPLAY, false);
}
@@ -467,7 +471,7 @@ public class MagnificationControllerTest {
assertFalse(mMagnificationConnectionManager.isWindowMagnifierEnabled(TEST_DISPLAY));
verify(mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY),
eq(DEFAULT_SCALE), eq(MAGNIFIED_CENTER_X), eq(MAGNIFIED_CENTER_Y),
- any(MagnificationAnimationCallback.class), eq(TEST_SERVICE_ID));
+ eq(false), any(MagnificationAnimationCallback.class), eq(TEST_SERVICE_ID));
}
@Test
@@ -484,7 +488,7 @@ public class MagnificationControllerTest {
verify(mScreenMagnificationController, never()).setScaleAndCenter(anyInt(),
anyFloat(), anyFloat(), anyFloat(),
- anyBoolean(), anyInt());
+ anyBoolean(), anyBoolean(), anyInt());
}
@Test
@@ -546,7 +550,7 @@ public class MagnificationControllerTest {
config, animate, TEST_SERVICE_ID);
verify(mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY),
/* scale= */ anyFloat(), /* centerX= */ anyFloat(), /* centerY= */ anyFloat(),
- mCallbackArgumentCaptor.capture(), /* id= */ anyInt());
+ anyBoolean(), mCallbackArgumentCaptor.capture(), /* id= */ anyInt());
mCallbackArgumentCaptor.getValue().onResult(true);
mMockConnection.invokeCallbacks();
@@ -616,7 +620,7 @@ public class MagnificationControllerTest {
@Test
public void magnifyThroughExternalRequest_showMagnificationButton() {
mScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY, DEFAULT_SCALE,
- MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y, false, TEST_SERVICE_ID);
+ MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y, true, false, TEST_SERVICE_ID);
// The first time is trigger when fullscreen mode is activated.
// The second time is triggered when magnification spec is changed.
@@ -638,7 +642,7 @@ public class MagnificationControllerTest {
mMagnificationController.onPerformScaleAction(TEST_DISPLAY, newScale, updatePersistence);
verify(mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY), eq(newScale),
- anyFloat(), anyFloat(), anyBoolean(), anyInt());
+ anyFloat(), anyFloat(), anyBoolean(), anyBoolean(), anyInt());
verify(mScreenMagnificationController).persistScale(eq(TEST_DISPLAY));
}
@@ -681,7 +685,7 @@ public class MagnificationControllerTest {
final MagnificationConfig config = obtainMagnificationConfig(MODE_FULLSCREEN);
mScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY,
config.getScale(), config.getCenterX(), config.getCenterY(),
- true, TEST_SERVICE_ID);
+ true, true, TEST_SERVICE_ID);
// The notify method is triggered when setting magnification enabled.
// The setScaleAndCenter call should not trigger notify method due to same scale and center.
@@ -930,7 +934,7 @@ public class MagnificationControllerTest {
public void onWindowModeActivated_fullScreenIsActivatedByExternal_fullScreenIsDisabled() {
mScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY,
DEFAULT_SCALE, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y,
- true, TEST_SERVICE_ID);
+ true, true, TEST_SERVICE_ID);
mMagnificationController.onWindowMagnificationActivationState(TEST_DISPLAY, true);
@@ -1317,7 +1321,8 @@ public class MagnificationControllerTest {
}
if (mode == MODE_FULLSCREEN) {
mScreenMagnificationController.setScaleAndCenter(displayId, DEFAULT_SCALE, centerX,
- centerY, true, AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+ centerY, true, true,
+ AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
} else {
mMagnificationConnectionManager.enableWindowMagnification(displayId, DEFAULT_SCALE,
centerX, centerY, null, TEST_SERVICE_ID);
diff --git a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
index 9c6412b81b34..a2e6d4c7bfed 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java
@@ -191,98 +191,6 @@ public class AppIntegrityManagerServiceImplTest {
}
@Test
- public void updateRuleSet_notAuthorized() throws Exception {
- makeUsSystemApp();
- Rule rule =
- new Rule(
- new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
- Rule.DENY);
- TestUtils.assertExpectException(
- SecurityException.class,
- "Only system packages specified in config_integrityRuleProviderPackages are"
- + " allowed to call this method.",
- () ->
- mService.updateRuleSet(
- VERSION,
- new ParceledListSlice<>(Arrays.asList(rule)),
- /* statusReceiver= */ null));
- }
-
- @Test
- public void updateRuleSet_notSystemApp() throws Exception {
- allowlistUsAsRuleProvider();
- makeUsSystemApp(false);
- Rule rule =
- new Rule(
- new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
- Rule.DENY);
- TestUtils.assertExpectException(
- SecurityException.class,
- "Only system packages specified in config_integrityRuleProviderPackages are"
- + " allowed to call this method.",
- () ->
- mService.updateRuleSet(
- VERSION,
- new ParceledListSlice<>(Arrays.asList(rule)),
- /* statusReceiver= */ null));
- }
-
- @Test
- public void updateRuleSet_authorized() throws Exception {
- allowlistUsAsRuleProvider();
- makeUsSystemApp();
- Rule rule =
- new Rule(
- new AtomicFormula.BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true),
- Rule.DENY);
-
- // no SecurityException
- mService.updateRuleSet(
- VERSION, new ParceledListSlice<>(Arrays.asList(rule)), mock(IntentSender.class));
- }
-
- @Test
- public void updateRuleSet_correctMethodCall() throws Exception {
- allowlistUsAsRuleProvider();
- makeUsSystemApp();
- IntentSender mockReceiver = mock(IntentSender.class);
- List<Rule> rules =
- Arrays.asList(
- new Rule(
- IntegrityFormula.Application.packageNameEquals(PACKAGE_NAME),
- Rule.DENY));
-
- mService.updateRuleSet(VERSION, new ParceledListSlice<>(rules), mockReceiver);
- runJobInHandler();
-
- verify(mIntegrityFileManager).writeRules(VERSION, TEST_FRAMEWORK_PACKAGE, rules);
- ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
- verify(mockReceiver).sendIntent(any(), anyInt(), intentCaptor.capture(), any(), any());
- assertEquals(STATUS_SUCCESS, intentCaptor.getValue().getIntExtra(EXTRA_STATUS, -1));
- }
-
- @Test
- public void updateRuleSet_fail() throws Exception {
- allowlistUsAsRuleProvider();
- makeUsSystemApp();
- doThrow(new IOException()).when(mIntegrityFileManager).writeRules(any(), any(), any());
- IntentSender mockReceiver = mock(IntentSender.class);
- List<Rule> rules =
- Arrays.asList(
- new Rule(
- IntegrityFormula.Application.packageNameEquals(PACKAGE_NAME),
- Rule.DENY));
-
- mService.updateRuleSet(VERSION, new ParceledListSlice<>(rules), mockReceiver);
- runJobInHandler();
-
- verify(mIntegrityFileManager).writeRules(VERSION, TEST_FRAMEWORK_PACKAGE, rules);
- ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
- verify(mockReceiver).sendIntent(any(), anyInt(), intentCaptor.capture(), any(), any());
- assertEquals(STATUS_FAILURE, intentCaptor.getValue().getIntExtra(EXTRA_STATUS, -1));
- }
-
- @Test
public void broadcastReceiverRegistration() throws Exception {
allowlistUsAsRuleProvider();
makeUsSystemApp();
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
index 592eec539ae6..bc01fc4f29c0 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationAttentionHelperTest.java
@@ -260,9 +260,10 @@ public class NotificationAttentionHelperTest extends UiServiceTestCase {
}
private void initAttentionHelper(TestableFlagResolver flagResolver) {
- mAttentionHelper = new NotificationAttentionHelper(getContext(), mock(LightsManager.class),
- mAccessibilityManager, mPackageManager, mUserManager, mUsageStats,
- mService.mNotificationManagerPrivate, mock(ZenModeHelper.class), flagResolver);
+ mAttentionHelper = new NotificationAttentionHelper(getContext(), new Object(),
+ mock(LightsManager.class),mAccessibilityManager, mPackageManager,
+ mUserManager, mUsageStats, mService.mNotificationManagerPrivate,
+ mock(ZenModeHelper.class), flagResolver);
mAttentionHelper.onSystemReady();
mAttentionHelper.setVibratorHelper(spy(new VibratorHelper(getContext())));
mAttentionHelper.setAudioManager(mAudioManager);
diff --git a/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger/ConversionUtilTest.java b/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger/ConversionUtilTest.java
index ff2ce15a7946..6dba96766b48 100644
--- a/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger/ConversionUtilTest.java
+++ b/services/tests/voiceinteractiontests/src/com/android/server/soundtrigger/ConversionUtilTest.java
@@ -41,6 +41,8 @@ import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Locale;
@RunWith(AndroidJUnit4.class)
@@ -62,18 +64,23 @@ public class ConversionUtilTest {
final int flags = SoundTrigger.ModuleProperties.AUDIO_CAPABILITY_ECHO_CANCELLATION
| SoundTrigger.ModuleProperties.AUDIO_CAPABILITY_NOISE_SUPPRESSION;
final var data = new byte[] {0x11, 0x22};
- final var keyphrases = new SoundTrigger.KeyphraseRecognitionExtra[2];
- keyphrases[0] = new SoundTrigger.KeyphraseRecognitionExtra(99,
+ final var keyphrases = new ArrayList<SoundTrigger.KeyphraseRecognitionExtra>(2);
+ keyphrases.add(new SoundTrigger.KeyphraseRecognitionExtra(99,
RECOGNITION_MODE_VOICE_TRIGGER | RECOGNITION_MODE_USER_IDENTIFICATION, 13,
new ConfidenceLevel[] {new ConfidenceLevel(9999, 50),
- new ConfidenceLevel(5000, 80)});
- keyphrases[1] = new SoundTrigger.KeyphraseRecognitionExtra(101,
+ new ConfidenceLevel(5000, 80)}));
+ keyphrases.add(new SoundTrigger.KeyphraseRecognitionExtra(101,
RECOGNITION_MODE_GENERIC, 8, new ConfidenceLevel[] {
new ConfidenceLevel(7777, 30),
- new ConfidenceLevel(2222, 60)});
+ new ConfidenceLevel(2222, 60)}));
- var apiconfig = new SoundTrigger.RecognitionConfig(true, false /** must be false **/,
- keyphrases, data, flags);
+ var apiconfig = new SoundTrigger.RecognitionConfig.Builder()
+ .setCaptureRequested(true)
+ .setAllowMultipleTriggers(false) // must be false
+ .setKeyphrases(keyphrases)
+ .setData(data)
+ .setAudioCapabilities(flags)
+ .build();
assertEquals(apiconfig, aidl2apiRecognitionConfig(api2aidlRecognitionConfig(apiconfig)));
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index c30b4bb6f65d..c3466b9cee18 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -139,7 +139,6 @@ import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsEnabled;
import android.provider.DeviceConfig;
import android.util.MutableBoolean;
import android.view.DisplayInfo;
@@ -2662,8 +2661,11 @@ public class ActivityRecordTests extends WindowTestsBase {
}
@Test
- @RequiresFlagsEnabled(Flags.FLAG_UNIVERSAL_RESIZABLE_BY_DEFAULT)
public void testSetOrientation_restrictedByTargetSdk() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_UNIVERSAL_RESIZABLE_BY_DEFAULT);
+ mDisplayContent.setIgnoreOrientationRequest(true);
+ makeDisplayLargeScreen(mDisplayContent);
+
assertSetOrientation(Build.VERSION_CODES.CUR_DEVELOPMENT, CATEGORY_SOCIAL, false);
assertSetOrientation(Build.VERSION_CODES.CUR_DEVELOPMENT, CATEGORY_GAME, true);
@@ -2673,12 +2675,13 @@ public class ActivityRecordTests extends WindowTestsBase {
}
private void assertSetOrientation(int targetSdk, int category, boolean expectRotate) {
- final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
- activity.mTargetSdk = targetSdk;
+ final String packageName = targetSdk <= Build.VERSION_CODES.VANILLA_ICE_CREAM
+ ? mContext.getPackageName() // WmTests uses legacy sdk.
+ : null; // Simulate CUR_DEVELOPMENT by invalid package (see PlatformCompat).
+ final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true)
+ .setComponent(getUniqueComponentName(packageName)).build();
activity.info.applicationInfo.category = category;
- activity.setVisible(true);
-
// Assert orientation is unspecified to start.
assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, activity.getOrientation());
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java
index c8a35598479f..08963f1c7647 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java
@@ -307,6 +307,8 @@ class AppCompatActivityRobot {
void createNewTaskWithBaseActivity() {
final Task newTask = new WindowTestsBase.TaskBuilder(mSupervisor)
.setCreateActivity(true)
+ // Respect "@ChangeId" according to test package's target sdk.
+ .setPackage(mAtm.mContext.getPackageName())
.setDisplay(mDisplayContent).build();
mTaskStack.push(newTask);
pushActivity(newTask.getTopNonFinishingActivity());
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 5c0d424f4f42..2bebcc30c872 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1081,7 +1081,8 @@ public class DisplayContentTests extends WindowTestsBase {
final DisplayRotation dr = dc.getDisplayRotation();
spyOn(dr);
doReturn(false).when(dr).useDefaultSettingsProvider();
- final ActivityRecord app = new ActivityBuilder(mAtm).setCreateTask(true).build();
+ final ActivityRecord app = new ActivityBuilder(mAtm).setCreateTask(true)
+ .setComponent(getUniqueComponentName(mContext.getPackageName())).build();
app.setOrientation(SCREEN_ORIENTATION_LANDSCAPE, app);
assertFalse(dc.getRotationReversionController().isAnyOverrideActive());
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
index 35c9e3fb3aaf..f4fa12ea361d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
@@ -51,6 +51,7 @@ import static org.mockito.Mockito.times;
import android.app.servertransaction.RefreshCallbackItem;
import android.app.servertransaction.ResumeActivityItem;
import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -592,6 +593,11 @@ public final class DisplayRotationCompatPolicyTests extends WindowTestsBase {
.setTask(mTask)
.build();
+ spyOn(mActivity.info.applicationInfo);
+ // Disable for camera compat.
+ doReturn(false).when(mActivity.info.applicationInfo).isChangeEnabled(
+ ActivityInfo.UNIVERSAL_RESIZABLE_BY_DEFAULT);
+
spyOn(mActivity.mAtmService.getLifecycleManager());
spyOn(mActivity.mAppCompatController.getAppCompatCameraOverrides());
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index cf1dcd0515d1..7e8bd38fb6a9 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -285,6 +285,52 @@ public class RootWindowContainerTests extends WindowTestsBase {
}
@Test
+ public void testTaskLayerRankFreeform() {
+ mSetFlagsRule.enableFlags(com.android.window.flags.Flags
+ .FLAG_PROCESS_PRIORITY_POLICY_FOR_MULTI_WINDOW_MODE);
+ final Task[] freeformTasks = new Task[3];
+ final WindowProcessController[] processes = new WindowProcessController[3];
+ for (int i = 0; i < freeformTasks.length; i++) {
+ freeformTasks[i] = new TaskBuilder(mSupervisor)
+ .setWindowingMode(WINDOWING_MODE_FREEFORM).setCreateActivity(true).build();
+ final ActivityRecord r = freeformTasks[i].getTopMostActivity();
+ r.setState(RESUMED, "test");
+ processes[i] = r.app;
+ }
+ resizeDisplay(mDisplayContent, 2400, 2000);
+ // ---------
+ // | 2 | 1 |
+ // ---------
+ // | 0 | |
+ // ---------
+ freeformTasks[2].setBounds(0, 0, 1000, 1000);
+ freeformTasks[1].setBounds(1000, 0, 2000, 1000);
+ freeformTasks[0].setBounds(0, 1000, 1000, 2000);
+ mRootWindowContainer.rankTaskLayers();
+ assertEquals(1, freeformTasks[2].mLayerRank);
+ assertEquals(2, freeformTasks[1].mLayerRank);
+ assertEquals(3, freeformTasks[0].mLayerRank);
+ assertFalse("Top doesn't need perceptible hint", (processes[2].getActivityStateFlags()
+ & WindowProcessController.ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM) != 0);
+ assertTrue((processes[1].getActivityStateFlags()
+ & WindowProcessController.ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM) != 0);
+ assertTrue((processes[0].getActivityStateFlags()
+ & WindowProcessController.ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM) != 0);
+
+ // Make task2 occlude half of task0.
+ clearInvocations(mAtm);
+ freeformTasks[2].setBounds(0, 0, 1000, 1500);
+ waitHandlerIdle(mWm.mH);
+ // The process of task0 will demote from perceptible to visible.
+ final int stateFlags0 = processes[0].getActivityStateFlags();
+ assertTrue((stateFlags0
+ & WindowProcessController.ACTIVITY_STATE_FLAG_VISIBLE_MULTI_WINDOW_MODE) != 0);
+ assertFalse((stateFlags0
+ & WindowProcessController.ACTIVITY_STATE_FLAG_PERCEPTIBLE_FREEFORM) != 0);
+ verify(mAtm).updateOomAdj();
+ }
+
+ @Test
public void testForceStopPackage() {
final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true).build();
final ActivityRecord activity = task.getTopMostActivity();
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index c30f70ee2903..e66dfeb8367c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -63,9 +63,9 @@ import static com.android.server.wm.ActivityRecord.State.PAUSED;
import static com.android.server.wm.ActivityRecord.State.RESTARTING_PROCESS;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityRecord.State.STOPPED;
+import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_POSITION_MULTIPLIER_CENTER;
import static com.android.server.wm.AppCompatUtils.computeAspectRatio;
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
-import static com.android.server.wm.AppCompatConfiguration.LETTERBOX_POSITION_MULTIPLIER_CENTER;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static com.google.common.truth.Truth.assertThat;
@@ -95,13 +95,11 @@ import android.compat.testing.PlatformCompatChangeRule;
import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.content.pm.ActivityInfo.ScreenOrientation;
-import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Binder;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
@@ -1570,7 +1568,7 @@ public class SizeCompatTests extends WindowTestsBase {
new TestSplitOrganizer(mAtm, activity.getDisplayContent());
// Move activity to split screen which takes half of the screen.
- mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false, "test");
organizer.mPrimary.setBounds(0, 0, 1000, 1400);
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
assertEquals(WINDOWING_MODE_MULTI_WINDOW, activity.getWindowingMode());
@@ -1957,7 +1955,7 @@ public class SizeCompatTests extends WindowTestsBase {
final TestSplitOrganizer organizer =
new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
// Move activity to multi-window which takes half of the screen.
- mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false, "test");
organizer.mPrimary.setBounds(0, 0, screenWidth, getExpectedSplitSize(screenHeight));
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
@@ -1993,7 +1991,7 @@ public class SizeCompatTests extends WindowTestsBase {
final TestSplitOrganizer organizer =
new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
// Move activity to multi-window which takes half of the screen.
- mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false, "test");
organizer.mPrimary.setBounds(0, 0, screenWidth, getExpectedSplitSize(screenHeight));
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
@@ -2126,7 +2124,7 @@ public class SizeCompatTests extends WindowTestsBase {
setUpDisplaySizeWithApp(screenWidth, screenHeight);
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mActivity.mWmService.mAppCompatConfiguration
- .setIsSplitScreenAspectRatioForUnresizableAppsEnabled(true);
+ .setIsSplitScreenAspectRatioForUnresizableAppsEnabled(true);
mActivity.mWmService.mAppCompatConfiguration.setFixedOrientationLetterboxAspectRatio(1.1f);
@@ -2147,7 +2145,7 @@ public class SizeCompatTests extends WindowTestsBase {
final TestSplitOrganizer organizer =
new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
// Move activity to split screen which takes half of the screen.
- mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false, "test");
organizer.mPrimary.setBounds(0, 0, getExpectedSplitSize(screenWidth), screenHeight);
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
@@ -2392,13 +2390,11 @@ public class SizeCompatTests extends WindowTestsBase {
spyOn(activity.mWmService.mAppCompatConfiguration);
doReturn(enabled).when(activity.mWmService.mAppCompatConfiguration)
.isUserAppAspectRatioSettingsEnabled();
- // Set user aspect ratio override
- final IPackageManager pm = mAtm.getPackageManager();
- try {
- doReturn(aspectRatio).when(pm)
- .getUserMinAspectRatio(activity.packageName, activity.mUserId);
- } catch (RemoteException ignored) {
- }
+ final AppCompatAspectRatioOverrides aspectRatioOverrides =
+ activity.mAppCompatController.getAppCompatAspectRatioOverrides();
+ spyOn(aspectRatioOverrides);
+ // Set user aspect ratio override.
+ doReturn(aspectRatio).when(aspectRatioOverrides).getUserMinAspectRatioOverrideCode();
prepareLimitedBounds(activity, screenOrientation, isUnresizable);
@@ -2507,7 +2503,7 @@ public class SizeCompatTests extends WindowTestsBase {
final TestSplitOrganizer organizer =
new TestSplitOrganizer(mAtm, activity.getDisplayContent());
// Move activity to split screen which takes half of the screen.
- mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false, "test");
organizer.mPrimary.setBounds(0, 0, getExpectedSplitSize(screenWidth), screenHeight);
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
assertEquals(WINDOWING_MODE_MULTI_WINDOW, activity.getWindowingMode());
@@ -2542,7 +2538,7 @@ public class SizeCompatTests extends WindowTestsBase {
final TestSplitOrganizer organizer =
new TestSplitOrganizer(mAtm, activity.getDisplayContent());
// Move activity to split screen which takes half of the screen.
- mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false, "test");
organizer.mPrimary.setBounds(0, 0, screenWidth, getExpectedSplitSize(screenHeight));
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
assertEquals(WINDOWING_MODE_MULTI_WINDOW, activity.getWindowingMode());
@@ -2663,7 +2659,7 @@ public class SizeCompatTests extends WindowTestsBase {
setUpDisplaySizeWithApp(screenWidth, screenHeight);
mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
mActivity.mWmService.mAppCompatConfiguration
- .setIsSplitScreenAspectRatioForUnresizableAppsEnabled(true);
+ .setIsSplitScreenAspectRatioForUnresizableAppsEnabled(true);
mActivity.mWmService.mAppCompatConfiguration.setFixedOrientationLetterboxAspectRatio(1.1f);
@@ -2684,7 +2680,7 @@ public class SizeCompatTests extends WindowTestsBase {
final TestSplitOrganizer organizer =
new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
// Move activity to split screen which takes half of the screen.
- mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false, "test");
organizer.mPrimary.setBounds(0, 0, screenWidth, getExpectedSplitSize(screenHeight));
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
@@ -2712,7 +2708,7 @@ public class SizeCompatTests extends WindowTestsBase {
final TestSplitOrganizer organizer =
new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
// Move activity to split screen which takes half of the screen.
- mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false, "test");
organizer.mPrimary.setBounds(0, 0, displayWidth, getExpectedSplitSize(displayHeight));
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
@@ -2748,7 +2744,7 @@ public class SizeCompatTests extends WindowTestsBase {
final TestSplitOrganizer organizer =
new TestSplitOrganizer(mAtm, mActivity.getDisplayContent());
// Move activity to split screen which takes half of the screen.
- mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false, "test");
organizer.mPrimary.setBounds(0, 0, getExpectedSplitSize(displayWidth), displayHeight);
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
@@ -2879,7 +2875,7 @@ public class SizeCompatTests extends WindowTestsBase {
// App bounds should be 700x1400 with the ratio as the display.
assertEquals(rotatedDisplayBounds.height(), rotatedActivityBounds.height());
assertEquals(rotatedDisplayBounds.height() * rotatedDisplayBounds.height()
- / rotatedDisplayBounds.width(), rotatedActivityBounds.width());
+ / rotatedDisplayBounds.width(), rotatedActivityBounds.width());
}
@Test
@@ -3328,7 +3324,7 @@ public class SizeCompatTests extends WindowTestsBase {
final Rect originalBounds = new Rect(mActivity.getBounds());
// Move activity to split screen which takes half of the screen.
- mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false, "test");
organizer.mPrimary.setBounds(0, 0, 1000, 1400);
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
@@ -3444,7 +3440,7 @@ public class SizeCompatTests extends WindowTestsBase {
prepareUnresizable(mActivity, 1.1f, SCREEN_ORIENTATION_PORTRAIT);
// Move activity to split screen which takes half of the screen.
- mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false, "test");
organizer.mPrimary.setBounds(0, 0, 1400, 1000);
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
@@ -3468,7 +3464,7 @@ public class SizeCompatTests extends WindowTestsBase {
prepareUnresizable(mActivity, 1.1f, SCREEN_ORIENTATION_LANDSCAPE);
// Move activity to split screen which takes half of the screen.
- mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false , "test");
+ mTask.reparent(organizer.mPrimary, POSITION_TOP, /* moveParents= */ false, "test");
organizer.mPrimary.setBounds(0, 0, 1000, 1400);
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mTask.getWindowingMode());
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
@@ -3909,7 +3905,7 @@ public class SizeCompatTests extends WindowTestsBase {
final DisplayPolicy policy = display.getDisplayPolicy();
DisplayPolicy.DecorInsets.Info decorInfo = policy.getDecorInsetsInfo(ROTATION_90,
display.mBaseDisplayHeight, display.mBaseDisplayWidth);
- decorInfo.mNonDecorInsets.set(130, 0, 60, 0);
+ decorInfo.mNonDecorInsets.set(130, 0, 60, 0);
spyOn(policy);
doReturn(decorInfo).when(policy).getDecorInsetsInfo(ROTATION_90,
display.mBaseDisplayHeight, display.mBaseDisplayWidth);
@@ -4145,6 +4141,7 @@ public class SizeCompatTests extends WindowTestsBase {
// can be aligned inside parentAppBounds
assertEquals(activity.getBounds(), new Rect(175, 0, 2275, 1000));
}
+
@Test
@DisableCompatChanges({ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED})
public void testApplyAspectRatio_activityCannotAlignWithParentAppHorizontal() {
@@ -4198,7 +4195,7 @@ public class SizeCompatTests extends WindowTestsBase {
final DisplayPolicy policy = display.getDisplayPolicy();
DisplayPolicy.DecorInsets.Info decorInfo = policy.getDecorInsetsInfo(ROTATION_90,
display.mBaseDisplayHeight, display.mBaseDisplayWidth);
- decorInfo.mNonDecorInsets.set(0, 130, 0, 60);
+ decorInfo.mNonDecorInsets.set(0, 130, 0, 60);
spyOn(policy);
doReturn(decorInfo).when(policy).getDecorInsetsInfo(ROTATION_90,
display.mBaseDisplayHeight, display.mBaseDisplayWidth);
@@ -4451,7 +4448,7 @@ public class SizeCompatTests extends WindowTestsBase {
mActivity.mResolveConfigHint.mUseOverrideInsetsForConfig = true;
// Set task as freeform
mTask.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM);
- prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
+ prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
Rect bounds = new Rect(mActivity.getWindowConfiguration().getBounds());
Rect appBounds = new Rect(mActivity.getWindowConfiguration().getAppBounds());
@@ -4827,12 +4824,7 @@ public class SizeCompatTests extends WindowTestsBase {
assertFalse(mActivity.isUniversalResizeable());
mDisplayContent.setIgnoreOrientationRequest(true);
- final int swDp = mDisplayContent.getConfiguration().smallestScreenWidthDp;
- if (swDp < WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP) {
- final int height = 100 + (int) (mDisplayContent.getDisplayMetrics().density
- * WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP);
- resizeDisplay(mDisplayContent, 100 + height, height);
- }
+ makeDisplayLargeScreen(mDisplayContent);
assertTrue(mActivity.isUniversalResizeable());
}
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 a215c0a80b46..757c358f51d0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -1123,6 +1123,15 @@ public class WindowTestsBase extends SystemServiceTestsBase {
displayContent.onRequestedOverrideConfigurationChanged(c);
}
+ static void makeDisplayLargeScreen(DisplayContent displayContent) {
+ final int swDp = displayContent.getConfiguration().smallestScreenWidthDp;
+ if (swDp < WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP) {
+ final int height = 100 + (int) (displayContent.getDisplayMetrics().density
+ * WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP);
+ resizeDisplay(displayContent, 100 + height, height);
+ }
+ }
+
/** Used for the tests that assume the display is portrait by default. */
static void makeDisplayPortrait(DisplayContent displayContent) {
if (displayContent.mBaseDisplayHeight <= displayContent.mBaseDisplayWidth) {
@@ -1223,7 +1232,14 @@ public class WindowTestsBase extends SystemServiceTestsBase {
}
static ComponentName getUniqueComponentName() {
- return ComponentName.createRelative(DEFAULT_COMPONENT_PACKAGE_NAME,
+ return getUniqueComponentName(DEFAULT_COMPONENT_PACKAGE_NAME);
+ }
+
+ static ComponentName getUniqueComponentName(String packageName) {
+ if (packageName == null) {
+ packageName = DEFAULT_COMPONENT_PACKAGE_NAME;
+ }
+ return ComponentName.createRelative(packageName,
DEFAULT_COMPONENT_CLASS_NAME + sCurrentActivityId++);
}
@@ -1298,8 +1314,7 @@ public class WindowTestsBase extends SystemServiceTestsBase {
ActivityBuilder setActivityTheme(int theme) {
mActivityTheme = theme;
// Use the real package of test so it can get a valid context for theme.
- mComponent = ComponentName.createRelative(mService.mContext.getPackageName(),
- DEFAULT_COMPONENT_CLASS_NAME + sCurrentActivityId++);
+ mComponent = getUniqueComponentName(mService.mContext.getPackageName());
return this;
}
@@ -1743,7 +1758,7 @@ public class WindowTestsBase extends SystemServiceTestsBase {
if (mIntent == null) {
mIntent = new Intent();
if (mComponent == null) {
- mComponent = getUniqueComponentName();
+ mComponent = getUniqueComponentName(mPackage);
}
mIntent.setComponent(mComponent);
mIntent.setFlags(mFlags);
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 44de65a009ff..79b3a7c4de65 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -582,6 +582,22 @@ public final class SatelliteManager {
"android.telephony.action.ACTION_SATELLITE_SUBSCRIBER_ID_LIST_CHANGED";
/**
+ * Meta-data represents whether the application supports P2P SMS over carrier roaming satellite
+ * which needs manual trigger to connect to satellite. The messaging applications that supports
+ * P2P SMS over carrier roaming satellites should add the following in their AndroidManifest.
+ * {@code
+ * <application
+ * <meta-data
+ * android:name="android.telephony.METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT"
+ * android:value="true"/>
+ * </application>
+ * }
+ * @hide
+ */
+ public static final String METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT =
+ "android.telephony.METADATA_SATELLITE_MANUAL_CONNECT_P2P_SUPPORT";
+
+ /**
* Request to enable or disable the satellite modem and demo mode.
* If satellite modem and cellular modem cannot work concurrently,
* then this will disable the cellular modem if satellite modem is enabled,
diff --git a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
index c6855b4a97b4..4ac567cc3937 100644
--- a/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
+++ b/tests/FlickerTests/test-apps/app-helpers/src/com/android/server/wm/flicker/helpers/DesktopModeAppHelper.kt
@@ -285,7 +285,11 @@ open class DesktopModeAppHelper(private val innerHelper: IStandardAppHelper) :
val displayRect = getDisplayRect(wmHelper)
- val endX = if (isLeft) displayRect.left else displayRect.right
+ val endX = if (isLeft) {
+ displayRect.left + SNAP_RESIZE_DRAG_INSET
+ } else {
+ displayRect.right - SNAP_RESIZE_DRAG_INSET
+ }
val endY = displayRect.centerY() / 2
// drag the window to snap resize
@@ -391,6 +395,7 @@ open class DesktopModeAppHelper(private val innerHelper: IStandardAppHelper) :
private companion object {
val TIMEOUT: Duration = Duration.ofSeconds(3)
+ const val SNAP_RESIZE_DRAG_INSET: Int = 5 // inset to avoid dragging to display edge
const val CAPTION: String = "desktop_mode_caption"
const val MAXIMIZE_BUTTON_VIEW: String = "maximize_button_view"
const val MAXIMIZE_MENU: String = "maximize_menu"
diff --git a/tests/Input/Android.bp b/tests/Input/Android.bp
index 6742cbe1f19a..168141bf6e7d 100644
--- a/tests/Input/Android.bp
+++ b/tests/Input/Android.bp
@@ -41,6 +41,7 @@ android_test {
"hamcrest-library",
"junit-params",
"kotlin-test",
+ "mockito-kotlin-nodeps",
"mockito-target-extended-minus-junit4",
"platform-test-annotations",
"platform-screenshot-diff-core",
diff --git a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
index 7526737f60bf..787ae06cd856 100644
--- a/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
+++ b/tests/Input/src/com/android/server/input/KeyGestureControllerTests.kt
@@ -799,6 +799,27 @@ class KeyGestureControllerTests {
}
@Test
+ @EnableFlags(com.android.window.flags.Flags.FLAG_ENABLE_MOVE_TO_NEXT_DISPLAY_SHORTCUT)
+ fun testMoveToNextDisplay() {
+ val keyGestureController = KeyGestureController(context, testLooper.looper)
+ testKeyGestureInternal(
+ keyGestureController,
+ TestData(
+ "META + CTRL + D -> Move a task to next display",
+ intArrayOf(
+ KeyEvent.KEYCODE_META_LEFT,
+ KeyEvent.KEYCODE_CTRL_LEFT,
+ KeyEvent.KEYCODE_D
+ ),
+ KeyGestureEvent.KEY_GESTURE_TYPE_MOVE_TO_NEXT_DISPLAY,
+ intArrayOf(KeyEvent.KEYCODE_D),
+ KeyEvent.META_META_ON or KeyEvent.META_CTRL_ON,
+ intArrayOf(KeyGestureEvent.ACTION_GESTURE_COMPLETE)
+ )
+ )
+ }
+
+ @Test
fun testCapsLockPressNotified() {
val keyGestureController = KeyGestureController(context, testLooper.looper)
val listener = KeyGestureEventListener()
diff --git a/tests/Input/src/com/android/server/input/PointerIconCacheTest.kt b/tests/Input/src/com/android/server/input/PointerIconCacheTest.kt
new file mode 100644
index 000000000000..47e7ac720a08
--- /dev/null
+++ b/tests/Input/src/com/android/server/input/PointerIconCacheTest.kt
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2024 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.input
+
+import android.content.Context
+import android.content.ContextWrapper
+import android.os.Handler
+import android.os.test.TestLooper
+import android.platform.test.annotations.Presubmit
+import android.view.Display
+import android.view.PointerIcon
+import androidx.test.platform.app.InstrumentationRegistry
+import junit.framework.Assert.assertEquals
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.kotlin.times
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+/**
+ * Tests for {@link PointerIconCache}.
+ */
+@Presubmit
+class PointerIconCacheTest {
+
+ @get:Rule
+ val rule = MockitoJUnit.rule()!!
+
+ @Mock
+ private lateinit var native: NativeInputManagerService
+ @Mock
+ private lateinit var defaultDisplay: Display
+
+ private lateinit var context: Context
+ private lateinit var testLooper: TestLooper
+ private lateinit var cache: PointerIconCache
+
+ @Before
+ fun setup() {
+ whenever(defaultDisplay.displayId).thenReturn(Display.DEFAULT_DISPLAY)
+
+ context = object : ContextWrapper(InstrumentationRegistry.getInstrumentation().context) {
+ override fun getDisplay() = defaultDisplay
+ }
+
+ testLooper = TestLooper()
+ cache = PointerIconCache(context, native, Handler(testLooper.looper))
+ }
+
+ @Test
+ fun testSetPointerScale() {
+ val defaultBitmap = getDefaultIcon().bitmap
+ cache.setPointerScale(2f)
+
+ testLooper.dispatchAll()
+ verify(native).reloadPointerIcons()
+
+ val bitmap =
+ cache.getLoadedPointerIcon(Display.DEFAULT_DISPLAY, PointerIcon.TYPE_ARROW).bitmap
+
+ assertEquals(defaultBitmap.height * 2, bitmap.height)
+ assertEquals(defaultBitmap.width * 2, bitmap.width)
+ }
+
+ @Test
+ fun testSetAccessibilityScaleFactor() {
+ val defaultBitmap = getDefaultIcon().bitmap
+ cache.setAccessibilityScaleFactor(Display.DEFAULT_DISPLAY, 4f)
+
+ testLooper.dispatchAll()
+ verify(native).reloadPointerIcons()
+
+ val bitmap =
+ cache.getLoadedPointerIcon(Display.DEFAULT_DISPLAY, PointerIcon.TYPE_ARROW).bitmap
+
+ assertEquals(defaultBitmap.height * 4, bitmap.height)
+ assertEquals(defaultBitmap.width * 4, bitmap.width)
+ }
+
+ @Test
+ fun testSetAccessibilityScaleFactorOnSecondaryDisplay() {
+ val defaultBitmap = getDefaultIcon().bitmap
+ val secondaryDisplayId = Display.DEFAULT_DISPLAY + 1
+ cache.setAccessibilityScaleFactor(secondaryDisplayId, 4f)
+
+ testLooper.dispatchAll()
+ verify(native).reloadPointerIcons()
+
+ val bitmap =
+ cache.getLoadedPointerIcon(Display.DEFAULT_DISPLAY, PointerIcon.TYPE_ARROW).bitmap
+ assertEquals(defaultBitmap.height, bitmap.height)
+ assertEquals(defaultBitmap.width, bitmap.width)
+
+ val bitmapSecondary =
+ cache.getLoadedPointerIcon(secondaryDisplayId, PointerIcon.TYPE_ARROW).bitmap
+ assertEquals(defaultBitmap.height * 4, bitmapSecondary.height)
+ assertEquals(defaultBitmap.width * 4, bitmapSecondary.width)
+ }
+
+ @Test
+ fun testSetPointerScaleAndAccessibilityScaleFactor() {
+ val defaultBitmap = getDefaultIcon().bitmap
+ cache.setPointerScale(2f)
+ cache.setAccessibilityScaleFactor(Display.DEFAULT_DISPLAY, 3f)
+
+ testLooper.dispatchAll()
+ verify(native, times(2)).reloadPointerIcons()
+
+ val bitmap =
+ cache.getLoadedPointerIcon(Display.DEFAULT_DISPLAY, PointerIcon.TYPE_ARROW).bitmap
+
+ assertEquals(defaultBitmap.height * 6, bitmap.height)
+ assertEquals(defaultBitmap.width * 6, bitmap.width)
+ }
+
+ private fun getDefaultIcon() =
+ PointerIcon.getLoadedSystemIcon(context, PointerIcon.TYPE_ARROW, false, 1f)
+}
diff --git a/tests/Tracing/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java b/tests/Tracing/src/com/android/internal/protolog/ProcessedPerfettoProtoLogImplTest.java
index 6f3deab1d4fa..2692e12c57ed 100644
--- a/tests/Tracing/src/com/android/internal/protolog/PerfettoProtoLogImplTest.java
+++ b/tests/Tracing/src/com/android/internal/protolog/ProcessedPerfettoProtoLogImplTest.java
@@ -40,7 +40,6 @@ import android.tools.traces.io.ResultWriter;
import android.tools.traces.monitors.PerfettoTraceMonitor;
import android.tools.traces.protolog.ProtoLogTrace;
import android.tracing.perfetto.DataSource;
-import android.util.proto.ProtoInputStream;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -74,7 +73,7 @@ import java.util.concurrent.atomic.AtomicInteger;
@SuppressWarnings("ConstantConditions")
@Presubmit
@RunWith(JUnit4.class)
-public class PerfettoProtoLogImplTest {
+public class ProcessedPerfettoProtoLogImplTest {
private static final String TEST_PROTOLOG_DATASOURCE_NAME = "test.android.protolog";
private static final String MOCK_VIEWER_CONFIG_FILE = "my/mock/viewer/config/file.pb";
private final File mTracingDirectory = InstrumentationRegistry.getInstrumentation()
@@ -100,7 +99,7 @@ public class PerfettoProtoLogImplTest {
private static ProtoLogViewerConfigReader sReader;
- public PerfettoProtoLogImplTest() throws IOException {
+ public ProcessedPerfettoProtoLogImplTest() throws IOException {
}
@BeforeClass
@@ -151,7 +150,8 @@ public class PerfettoProtoLogImplTest {
ViewerConfigInputStreamProvider viewerConfigInputStreamProvider = Mockito.mock(
ViewerConfigInputStreamProvider.class);
Mockito.when(viewerConfigInputStreamProvider.getInputStream())
- .thenAnswer(it -> new ProtoInputStream(sViewerConfigBuilder.build().toByteArray()));
+ .thenAnswer(it -> new AutoClosableProtoInputStream(
+ sViewerConfigBuilder.build().toByteArray()));
sCacheUpdater = () -> {};
sReader = Mockito.spy(new ProtoLogViewerConfigReader(viewerConfigInputStreamProvider));
@@ -165,21 +165,16 @@ public class PerfettoProtoLogImplTest {
throw new RuntimeException(
"Unexpected viewer config file path provided");
}
- return new ProtoInputStream(sViewerConfigBuilder.build().toByteArray());
+ return new AutoClosableProtoInputStream(sViewerConfigBuilder.build().toByteArray());
});
};
sProtoLogConfigurationService =
new ProtoLogConfigurationServiceImpl(dataSourceBuilder, tracer);
- if (android.tracing.Flags.clientSideProtoLogging()) {
- sProtoLog = new PerfettoProtoLogImpl(
- MOCK_VIEWER_CONFIG_FILE, sReader, () -> sCacheUpdater.run(),
- TestProtoLogGroup.values(), dataSourceBuilder, sProtoLogConfigurationService);
- } else {
- sProtoLog = new PerfettoProtoLogImpl(
- viewerConfigInputStreamProvider, sReader, () -> sCacheUpdater.run(),
- TestProtoLogGroup.values(), dataSourceBuilder, sProtoLogConfigurationService);
- }
+ sProtoLog = new ProcessedPerfettoProtoLogImpl(
+ MOCK_VIEWER_CONFIG_FILE, viewerConfigInputStreamProvider, sReader,
+ () -> sCacheUpdater.run(), TestProtoLogGroup.values(), dataSourceBuilder,
+ sProtoLogConfigurationService);
busyWaitForDataSourceRegistration(TEST_PROTOLOG_DATASOURCE_NAME);
}
@@ -398,18 +393,17 @@ public class PerfettoProtoLogImplTest {
}
@Test
- public void log_logcatEnabledNoMessage() {
+ public void log_logcatEnabledNoMessageThrows() {
when(sReader.getViewerString(anyLong())).thenReturn(null);
PerfettoProtoLogImpl implSpy = Mockito.spy(sProtoLog);
TestProtoLogGroup.TEST_GROUP.setLogToLogcat(true);
TestProtoLogGroup.TEST_GROUP.setLogToProto(false);
- implSpy.log(LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321,
- new Object[]{5});
-
- verify(implSpy).passToLogcat(eq(TestProtoLogGroup.TEST_GROUP.getTag()), eq(
- LogLevel.INFO), eq("UNKNOWN MESSAGE args = (5)"));
- verify(sReader).getViewerString(eq(1234L));
+ var assertion = assertThrows(RuntimeException.class, () ->
+ implSpy.log(LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, 1234, 4321,
+ new Object[]{5}));
+ Truth.assertThat(assertion).hasMessageThat()
+ .contains("Failed to decode message for logcat");
}
@Test
@@ -539,16 +533,12 @@ public class PerfettoProtoLogImplTest {
PerfettoTraceMonitor traceMonitor = PerfettoTraceMonitor.newBuilder()
.enableProtoLog(TEST_PROTOLOG_DATASOURCE_NAME)
.build();
- long before;
- long after;
try {
traceMonitor.start();
- before = SystemClock.elapsedRealtimeNanos();
sProtoLog.log(
LogLevel.INFO, TestProtoLogGroup.TEST_GROUP, messageHash,
0b01100100,
new Object[]{"test", 1, 0.1, true});
- after = SystemClock.elapsedRealtimeNanos();
} finally {
traceMonitor.stop(mWriter);
}
@@ -606,7 +596,8 @@ public class PerfettoProtoLogImplTest {
Truth.assertThat(stacktrace).doesNotContain(DataSource.class.getSimpleName() + ".java");
Truth.assertThat(stacktrace)
.doesNotContain(ProtoLogImpl.class.getSimpleName() + ".java");
- Truth.assertThat(stacktrace).contains(PerfettoProtoLogImplTest.class.getSimpleName());
+ Truth.assertThat(stacktrace)
+ .contains(ProcessedPerfettoProtoLogImplTest.class.getSimpleName());
Truth.assertThat(stacktrace).contains("stackTraceTrimmed");
}
diff --git a/tests/Tracing/src/com/android/internal/protolog/ProtoLogTest.java b/tests/Tracing/src/com/android/internal/protolog/ProtoLogTest.java
index 8ecddaa76216..3d1e208189b0 100644
--- a/tests/Tracing/src/com/android/internal/protolog/ProtoLogTest.java
+++ b/tests/Tracing/src/com/android/internal/protolog/ProtoLogTest.java
@@ -47,12 +47,12 @@ public class ProtoLogTest {
}
@Test
- public void throwOnRegisteringDuplicateGroup() {
- final var assertion = assertThrows(RuntimeException.class,
- () -> ProtoLog.init(TEST_GROUP_1, TEST_GROUP_1, TEST_GROUP_2));
+ public void deduplicatesRegisteringDuplicateGroup() {
+ ProtoLog.init(TEST_GROUP_1, TEST_GROUP_1, TEST_GROUP_2);
- Truth.assertThat(assertion).hasMessageThat().contains("" + TEST_GROUP_1.getId());
- Truth.assertThat(assertion).hasMessageThat().contains("duplicate");
+ final var instance = ProtoLog.getSingleInstance();
+ Truth.assertThat(instance.getRegisteredGroups())
+ .containsExactly(TEST_GROUP_1, TEST_GROUP_2);
}
@Test
diff --git a/tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java b/tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java
index d78ced161eaf..9e029a8d5e57 100644
--- a/tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java
+++ b/tests/Tracing/src/com/android/internal/protolog/ProtoLogViewerConfigReaderTest.java
@@ -19,9 +19,12 @@ package com.android.internal.protolog;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
+import android.os.Build;
import android.platform.test.annotations.Presubmit;
-import android.util.proto.ProtoInputStream;
+import com.google.common.truth.Truth;
+
+import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -29,6 +32,8 @@ import org.junit.runners.JUnit4;
import perfetto.protos.ProtologCommon;
+import java.io.File;
+
@Presubmit
@RunWith(JUnit4.class)
public class ProtoLogViewerConfigReaderTest {
@@ -83,7 +88,7 @@ public class ProtoLogViewerConfigReaderTest {
).build().toByteArray();
private final ViewerConfigInputStreamProvider mViewerConfigInputStreamProvider =
- () -> new ProtoInputStream(TEST_VIEWER_CONFIG);
+ () -> new AutoClosableProtoInputStream(TEST_VIEWER_CONFIG);
private ProtoLogViewerConfigReader mConfig;
@@ -123,6 +128,31 @@ public class ProtoLogViewerConfigReaderTest {
}
@Test
+ public void viewerConfigIsOnDevice() {
+ Assume.assumeFalse(Build.FINGERPRINT.contains("robolectric"));
+
+ final String[] viewerConfigPaths;
+ if (android.tracing.Flags.perfettoProtologTracing()) {
+ viewerConfigPaths = new String[] {
+ "/system_ext/etc/wmshell.protolog.pb",
+ "/system/etc/core.protolog.pb",
+ };
+ } else {
+ viewerConfigPaths = new String[] {
+ "/system_ext/etc/wmshell.protolog.json.gz",
+ "/system/etc/protolog.conf.json.gz",
+ };
+ }
+
+ for (final var viewerConfigPath : viewerConfigPaths) {
+ File f = new File(viewerConfigPath);
+
+ Truth.assertWithMessage(f.getAbsolutePath() + " exists").that(f.exists()).isTrue();
+ }
+
+ }
+
+ @Test
public void loadUnloadAndReloadViewerConfig() {
loadViewerConfig();
unloadViewerConfig();
diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfaces.kt b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfaces.kt
index caa018d8c013..e163ef470355 100644
--- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfaces.kt
+++ b/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/ExemptAidlInterfaces.kt
@@ -485,6 +485,7 @@ val exemptAidlInterfaces = setOf(
"android.net.thread.IConfigurationReceiver",
"android.net.thread.IOperationalDatasetCallback",
"android.net.thread.IOperationReceiver",
+ "android.net.thread.IOutputReceiver",
"android.net.thread.IStateCallback",
"android.net.thread.IThreadNetworkController",
"android.net.thread.IThreadNetworkManager",
@@ -757,6 +758,7 @@ val exemptAidlInterfaces = setOf(
"com.android.server.thread.openthread.IChannelMasksReceiver",
"com.android.server.thread.openthread.INsdPublisher",
"com.android.server.thread.openthread.IOtDaemonCallback",
+ "com.android.server.thread.openthread.IOtOutputReceiver",
"com.android.server.thread.openthread.IOtStatusReceiver",
"com.google.android.clockwork.ambient.offload.IDisplayOffloadService",
"com.google.android.clockwork.ambient.offload.IDisplayOffloadTransitionFinishedCallbacks",